Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * $Id: PooledConnectionHandler.java 56968 2012-04-30 12:11:30Z 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.ds;
 
 import static org.firebirdsql.ds.ReflectionHelper.findMethod;
 import static org.firebirdsql.ds.ReflectionHelper.getAllInterfaces;
 
 import java.util.List;
 import java.util.Set;
 
InvocationHandler for the logical connection returned by FBPooledConnection.

Using an InvocationHandler together with a Proxy removes the need to create wrappers for every individual JDBC version.

Author(s):
Mark Rotteveel
Since:
2.2
 
 
     protected static final String CLOSED_MESSAGE = "Logical connection already closed";
     protected static final String FORCIBLY_CLOSED_MESSAGE = "Logical connection was forcibly closed by the connection pool";
     protected final AbstractPooledConnection owner;
     protected volatile Connection connection;
     protected volatile Connection proxy;
     protected volatile boolean forcedClose;
 
     private final List openStatements = Collections.synchronizedList(new LinkedList());
 
     protected PooledConnectionHandler(Connection connectionAbstractPooledConnection owner) {
         this. = connection;
         this. = owner;
          = (Connection) Proxy.newProxyInstance(getClass().getClassLoader(),
                 getAllInterfaces(connection.getClass()), this);
     }
 
     public Object invoke(Object proxyMethod methodObject[] argsthrows Throwable {
         // Methods from object
         if (method.equals()) {
             return "Proxy for " + ;
         }
         if (method.equals()) {
             // Using parameter proxy (and not field) on purpose as field is
             // nulled after closing
             return Boolean.valueOf(proxy == args[0]);
         }
         if (method.equals()) {
             // Using parameter proxy (and not field) on purpose as field is
             // nulled after closing
             return Integer.valueOf(System.identityHashCode(proxy));
         }
         // Other methods from object
         if (method.getDeclaringClass().equals(Object.class)) {
             try {
                 return method.invoke(args);
             } catch (InvocationTargetException e) {
                 throw e.getTargetException();
             }
         }
 
         // Methods from Connection
         if (method.equals()) {
             return Boolean.valueOf(isClosed());
         }
        if (isClosed() && !method.equals()) {
            String message =  ?  : ;
            throw new FBSQLException(message.);
        }
        try {
            // Life cycle methods
            if (method.equals()) {
                if (!isClosed()) {
                    handleClose(true);
                }
                return null;
            }
            if (method.getDeclaringClass().equals(Connection.class)
                    && .contains(method.getName())) {
                Statement pstmt = (Statementmethod.invoke(args);
                StatementHandler stmtHandler = new StatementHandler(thispstmt);
                .add(stmtHandler);
                return stmtHandler.getProxy();
            }
            // All other methods
            return method.invoke(args);
        } catch (InvocationTargetException ite) {
            Throwable inner = ite.getTargetException();
            if (inner instanceof SQLException) {
                .fireConnectionError((SQLExceptioninner);
            }
            throw inner;
        } catch (SQLException se) {
            .fireConnectionError(se);
            throw se;
        }
    }
    
    
Method to decide if calling rollback on the physical connection for cleanup (in handleClose()) is allowed.

NOTE: This method is not involved in rollback decisions for calls to the proxy.

Returns:
true when calling rollback is allowed
    protected boolean isRollbackAllowed() throws SQLException {
        return !.getAutoCommit();
    }

    
Handle java.sql.Connection.close() method. This implementation closes the connection and associated statements.

Parameters:
notifyOwner true when connection owner should be notified of closure.
Throws:
java.sql.SQLException if underlying connection threw an exception.
    protected void handleClose(boolean notifyOwnerthrows SQLException {
        SQLExceptionChainBuilder chain = new SQLExceptionChainBuilder();
        try {
            closeStatements();
        } catch (SQLException ex) {
            chain.append(ex);
        }
        if (isRollbackAllowed()) {
            try {
                .rollback();
            } catch (SQLException ex) {
                chain.append(ex);
            }
        }
        try {
            .clearWarnings();
        } catch (SQLException ex) {
            chain.append(ex);
        }
         = null;
         = null;
        .releaseConnectionHandler(this);
        if (notifyOwner) {
            .fireConnectionClosed();
        }
        if (chain.hasException()) {
            throw chain.getException();
        }
    }

    

Returns:
Proxy for the Connection object
    protected Connection getProxy() {
        return ;
    }

    
Closes this PooledConnectionHandler. Intended to be called by the ConnectionPoolDataSource when it wants to forcibly close the logical connection to reuse it.

    protected void close() throws SQLException {
        if (!isClosed()) {
            try {
                handleClose(false);
            } finally {
                 = true;
            }
        }
    }
    protected boolean isClosed() {
        return  == null ||  == null;
    }
    protected void statementErrorOccurred(StatementHandler stmtHandlerSQLException sqle) {
        // TODO: Log?, forward fatal connection related errors?
        .fireConnectionError(sqle);
    }
    protected void forgetStatement(StatementHandler stmtHandler) {
        .remove(stmtHandler);
    }
    protected void closeStatements() throws SQLException {
        SQLExceptionChainBuilder chain = new SQLExceptionChainBuilder();
        synchronized () {
            // Make copy as the StatementHandler close will remove itself from openStatements
            List statementsCopy = new ArrayList();
            Iterator iter = statementsCopy.iterator();
            while (iter.hasNext()) {
                StatementHandler stmt = (StatementHandleriter.next();
                try {
                    stmt.close();
                } catch (SQLException ex) {
                    chain.append(ex);
                    // TODO : Log, ignore, something else?
                } catch (Throwable t) {
                    // ignore?
                }
            }
            .clear();
        }
        if (chain.hasException()) {
            throw chain.getException();
        }
    }
    // Connection methods
    private final static Method CONNECTION_IS_CLOSED = findMethod(Connection.class"isClosed",
            new Class[0]);
    private final static Method CONNECTION_CLOSE = findMethod(Connection.class"close",
            new Class[0]);
    
    private static final Set STATEMENT_CREATION_METHOD_NAMES;
    static {
        Set temp = new HashSet();
        temp.add("createStatement");
        temp.add("prepareCall");
        temp.add("prepareStatement");
         = Collections.unmodifiableSet(temp);
    }
    // Object Methods
    private final static Method TO_STRING = findMethod(Object.class"toString"new Class[0]);
    private final static Method EQUALS = findMethod(Object.class"equals",
            new Class[] { Object.class });
    private final static Method HASH_CODE = findMethod(Object.class"hashCode"new Class[0]);
New to GrepCode? Check out our FAQ X