Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * $Id: PooledConnectionHandler.java 57875 2013-03-30 12:54:47Z mrotteveel $
   * 
   * Firebird Open Source J2ee connector - jdbc driver
   *
   * Distributable under LGPL license.
   * You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
   *
   * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * LGPL License for more details.
  *
  * This file was created by members of the firebird development team.
  * All individual contributions remain the Copyright (C) of those
  * individuals.  Contributors to this file are either listed here or
  * can be obtained from a CVS history command.
  *
  * All rights reserved.
  */
  
 package org.firebirdsql.pool;
 
 import static org.firebirdsql.ds.ReflectionHelper.findMethod;
 import static org.firebirdsql.ds.ReflectionHelper.getAllInterfaces;
 
 import java.util.List;
 
This is a wrapper for java.sql.Connection instances that caches prepared statements.

Author(s):
Roman Rokytskyy
 
 	
 	private static final boolean LOG_REENTRANT_ACCESS = .;
 	
 	private static Logger logChannel = LoggerFactory.getLogger(PooledConnectionHandler.classfalse);
     
     private final static Method CONNECTION_PREPARE_STATEMENT = findMethod(
         Connection.class"prepareStatement"new Class[] {String.class});
 
     private final static Method CONNECTION_PREPARE_STATEMENT2 = findMethod(
         Connection.class"prepareStatement"new Class[] {
             String.class..
         });
         
     private final static Method CONNECTION_PREPARE_STATEMENT3 = findMethod(
         Connection.class"prepareStatement"new Class[] {
             String.class...
         });
 
     private final static Method CONNECTION_PREPARE_STATEMENT_GENKEYS1 = findMethod(
         Connection.class"prepareStatement"new Class[] {
             String.class.
         });
 
     private final static Method CONNECTION_PREPARE_STATEMENT_GENKEYS2 = findMethod(
         Connection.class"prepareStatement"new Class[] {
             String.classnew int[0].getClass()
         });
 
     private final static Method CONNECTION_PREPARE_STATEMENT_GENKEYS3 = findMethod(
         Connection.class"prepareStatement"new Class[] {
             String.classnew String[0].getClass()
         });
     
     private final static Method CONNECTION_CREATE_STATEMENT = findMethod(
             Connection.class"createStatement"new Class[0]);
 
         private final static Method CONNECTION_CREATE_STATEMENT2 = findMethod(
             Connection.class"createStatement"new Class[] {
                 ..
             });
     
     private final static Method CONNECTION_CLOSE = findMethod(
         Connection.class"close"new Class[0]);
         
     private final static Method CONNECTION_COMMIT = findMethod(
         Connection.class"commit"new Class[0]);
         
    private final static Method CONNECTION_ROLLBACK = findMethod(
        Connection.class"rollback"new Class[0]);
    
    private final static Method CONNECTION_IS_CLOSED = findMethod(
        Connection.class"isClosed"new Class[0]);
        
    private Connection connection;
	private Connection proxy;
    
	private boolean closed;
Construct instance of this class. This method constructs new proxy that implements java.sql.Connection interface and uses newly constructed object as invocation handler.

Parameters:
connection connection to wrap.
owner instance of XConnectionManager that owns this connection instance.
Throws:
java.sql.SQLException if something went wrong during initialization.
    public 
            throws SQLException
        {
            
            this. = connection;
            this. = owner;
            
            Class[] implementedInterfaces = 
                getAllInterfaces(connection.getClass());
             = (Connection)Proxy.newProxyInstance(
                PooledConnectionHandler.class.getClassLoader(),
                implementedInterfaces,
                this);
		}

Get proxy implementing java.sql.Connection interface and using this instance as invocation handler.

Returns:
instance of java.sql.Connection.
	public Connection getProxy() {
		return ;
	}
    
    
Get manager of this connection wrapper.

Returns:
instance of XConnectionManager.
    public XConnectionManager getManager() {
        return ;
    }
    
    
Check whether the java.sql.Connection.close() method was called.

Returns:
true if the method was called, false otherwise.
    public boolean isClosed() {
        return ;
    }
    
    
Deallocate current connection. This call is similar to the call java.sql.Connection.close() when invoked on the proxy object. However, unlike that call no listener is notified that connection being closed;

Throws:
java.sql.SQLException if something goes wrong.
    public void deallocate() throws SQLException {
        handleConnectionClose(false);
    }
	private boolean invokeEntered;

    
Invoke method on a specified proxy. Here we check if method is a method java.sql.Connection.prepareStatement(java.lang.String). If yes, we check if there is already a prepared statement for the wrapped connection or wrap a newly created one.

Parameters:
proxy proxy on which method is invoked.
method instance of java.lang.reflect.Method describing method being invoked.
args array with arguments.
Returns:
result of method invokation.
Throws:
java.lang.Throwable if invoked method threw an exception.
    public Object invoke(Object proxyMethod methodObject[] args
        throws Throwable 
    {
		try {
			    .warn("Re-entrant access detected."new Exception());
			 = true;
            // if object is closed, throw an exception
			if () { 
                // check whether Connection.isClose() method is called first
                if (.equals(method))
                    return .;
                
			    FBSQLException ex = new FBSQLException(
				    "Connection " + this + " was closed. " +
                            "See the attached exception to find the place " +
                            "where it was closed");
                ex.setNextException();
                throw ex;
            }
            
			if (( != null && !.isValid(this)))
			    throw new SQLException(
				    "This connection owner is not valid anymore.");
			// Connection.prepareStatement(...) methods
				String statement = (String)args[0];
                    statement
                    .,
                    .,
                    .);
            } else
            if (method.equals()) {
                String statement = (String)args[0];
                Integer resultSetType = (Integer)args[1];
                Integer resultSetConcurrency = (Integer)args[2];
                return handlePrepareStatement(
                    statement
                    resultSetType.intValue(), 
                    resultSetConcurrency.intValue(),
                    .);
else
            if (method.equals()) {
                String statement = (String)args[0];
                Integer resultSetType = (Integer)args[1];
                Integer resultSetConcurrency = (Integer)args[2];
                Integer resultSetHoldability = (Integer)args[3];
                return handlePrepareStatement(
                    statement
                    resultSetType.intValue(), 
                    resultSetConcurrency.intValue(),
                    resultSetHoldability.intValue());
            } else
            
            // Connection.prepareStatement(...) for generated keys
                
            if (method.equals()){
                String statement = (String)args[0];
                Integer returnGeneratedKeys = (Integer)args[1];
                
                if (returnGeneratedKeys.intValue() == .)
                    return handlePrepareStatement(statementnullnull);
                else
                    return handlePrepareStatement(
                        statement
                        .,
                        .,
                        .);
            } else
            if (method.equals()) {
                String statement = (String)args[0];
                int[] keyIndexes = (int[])args[1];
                return handlePrepareStatement(statementkeyIndexesnull);
            } else
                if (method.equals()) {
                    String statement = (String)args[0];
                    String[] keyColumns = (String[])args[1];
                    return handlePrepareStatement(statementnullkeyColumns);
            } else
                
            // Connection.createStatement(...) methods
            if (method.equals()){
                return handleCreateStatement(
                    .,
                    .);
            } else
            if (method.equals()) {
                Integer resultSetType = (Integer)args[0];
                Integer resultSetConcurrency = (Integer)args[1];
                return handleCreateStatement(
                    resultSetType.intValue(), 
                    resultSetConcurrency.intValue());
            } else
                
            // Connection lifycycle methods
			if (method.equals()) {
				return .;
else
			if (method.equals()) {
				return .;
else
			if (method.equals()) {
				return .;
else
				return method.invoke(args);
        } catch(InvocationTargetException ex) {
            
            if (ex.getTargetException() instanceof SQLException &&  != null)
                .connectionErrorOccured(this, (SQLException)ex.getTargetException());
                
            throw ex.getTargetException();
            
catch(SQLException ex) {
			if ( != null
			throw ex;
finally {
			 = false;
		}
    }
    
    
Handle java.sql.Connection.prepareStatement(java.lang.String) method call. This method check internal cache first and returns prepared statement if found. Otherwise, it prepares statement and caches it.

Parameters:
statement statement to prepare.
resultSetType result set type.
resultSetConcurrency result set concurrency.
resultSetHoldability result set holdability
Returns:
instance of java.sql.PreparedStatement corresponding to the statement.
Throws:
java.sql.SQLException if there was problem preparing statement.
    synchronized PreparedStatement handlePrepareStatement(String statement,
            int resultSetTypeint resultSetConcurrency,
            int resultSetHoldabilitythrows SQLException {
        
        return getManager().getPreparedStatement(statementresultSetType,
            resultSetConcurrencyresultSetHoldability);
    }

    
Handle java.sql.Connection.prepareStatement(java.lang.String,int), java.sql.Connection.prepareStatement(java.lang.String,int[]) and java.sql.Connection.prepareStatement(java.lang.String,java.lang.String[]) calls. This method checks internal cache first and returns the prepared statement if found. Otherwise, it prepares statement and caches it.

Parameters:
statement statement to prepare.
Returns:
instance of java.sql.PreparedStatement corresponding to the statement.
Throws:
java.sql.SQLException if there was problem preparing statement.
    synchronized PreparedStatement handlePrepareStatement(String statement,
            int[] keyIndexesString[] keyColumnsthrows SQLException {
        
        return getManager().getPreparedStatement(statementkeyIndexes,
            keyColumns);
    }
    
    private HashSet openStatements = new HashSet();
    
    
Handle java.sql.Connection.createStatement(int,int) method call.

Parameters:
resultSetType
resultSetConcurrency
Returns:
Throws:
java.sql.SQLException
    synchronized Statement handleCreateStatement(int resultSetType
            int resultSetConcurrencythrows SQLException 
    {
        Statement result = 
            .createStatement(resultSetTyperesultSetConcurrency);
        
        StatementHandler handler = new StatementHandler(thisresult);
        .add(handler);
        
        return handler.getProxy();
    }
    
    
Forget about a statement. This method removes a statement from the internal collection containing open statements. This method should be called only from a dynamic proxy intercepting java.sql.Statement.close() method.

Parameters:
handler instance of StatementHandler wrapping a statement to forget.
    public synchronized void forgetStatement(StatementHandler handler) {
        .remove(handler);
    }
    
    
Close all open statements that were not correctly closed by the application.

Throws:
java.sql.SQLException if some error happened during close.
    synchronized void closeOpenStatements() throws SQLException {
        SQLExceptionChainBuilder chain = new SQLExceptionChainBuilder();
        
        // Copy to prevent ConcurrentModificationException
        List copyStatements = new ArrayList();
        for (Iterator iter = copyStatements.iterator(); iter.hasNext();) {
            StatementHandler handler = (StatementHandleriter.next();
            
            try {
                handler.getWrappedObject().close();
            } catch(SQLException ex) {
                chain.append(ex);
            }
        }
        .clear();
        
        if (chain.hasException())
            throw chain.getException();
    }
    
    
Handle java.sql.Connection.close() method. This implementation closes the connection, cleans the cache and notifies the owner.

Throws:
java.sql.SQLException if underlying connection threw this exception.
    synchronized void handleConnectionClose() throws SQLException {
        handleConnectionClose(true);
    }
    
    
Handle java.sql.Connection.close() method. This implementation closes the connection and cleans the cache.

Parameters:
notifyOwner true when connection owner should be notified.
Throws:
java.sql.SQLException if underlying connection threw this exception.
    synchronized void handleConnectionClose(boolean notifyOwnerthrows SQLException {
        try {
            closeOpenStatements();
        } finally {
    		if ( != null && notifyOwner) {
    			.connectionClosed(this);            
            }
    
    		 = true;
             = new ObjectCloseTraceException();
        }
	}
    
    
Handle java.sql.Connection.commit() method. This implementation commits the connection and cleans the cache.

Throws:
java.sql.SQLException if underlying connection threw this exception.
    synchronized void handleConnectionCommit() throws SQLException {
        .commit();
    }
    
    
Handle java.sql.Connection.rollback() method. This implementation rolls the connection back and cleans the cache.

Throws:
java.sql.SQLException if underlying connection threw this exception.
    synchronized void handleConnectionRollback() throws SQLException {
        .rollback();
    }
New to GrepCode? Check out our FAQ X