private void closeDueToException(PooledConnectionAndInfo info) { if (info != null) { try { info.getPooledConnection().getConnection().close(); } catch (Exception e) { // do not throw this exception because we are in the middle // of handling another exception. But record it because // it potentially leaks connections from the pool. getLogWriter() .println( "[ERROR] Could not return connection to " + "pool during exception handling. " + e.getMessage()); } } }
/** Attempt to establish a database connection. */ public synchronized Connection getConnection(String username, String password) throws SQLException { if (isNew) { throw new SQLException( "Must set the ConnectionPoolDataSource " + "through setDataSourceName or setConnectionPoolDataSource" + " before calling getConnection."); } getConnectionCalled = true; Map pools = (Map) dsInstanceMap.get(instanceKey); PoolKey key = getPoolKey(username); Object pool = pools.get(key); if (pool == null) { try { registerPool(username, password); pool = pools.get(key); } catch (Exception e) { e.printStackTrace(); throw new SQLException(e.getMessage()); } } PooledConnectionAndInfo info = null; if (pool instanceof ObjectPool) { try { info = (PooledConnectionAndInfo) ((ObjectPool) pool).borrowObject(); } catch (NoSuchElementException e) { closeDueToException(info); throw new SQLException(e.getMessage()); } catch (RuntimeException e) { closeDueToException(info); throw e; } catch (SQLException e) { closeDueToException(info); throw e; } catch (Exception e) { closeDueToException(info); throw new SQLException(e.getMessage()); } } else { // assume KeyedObjectPool try { UserPassKey upkey = getUserPassKey(username, password); info = (PooledConnectionAndInfo) ((KeyedObjectPool) pool).borrowObject(upkey); } catch (NoSuchElementException e) { closeDueToException(info); throw new SQLException(e.getMessage()); } catch (RuntimeException e) { closeDueToException(info); throw e; } catch (SQLException e) { closeDueToException(info); throw e; } catch (Exception e) { closeDueToException(info); throw new SQLException(e.getMessage()); } } if (!(null == password ? null == info.getPassword() : password.equals(info.getPassword()))) { closeDueToException(info); throw new SQLException( "Given password did not match password used " + "to create the PooledConnection."); } PooledConnection pc = info.getPooledConnection(); boolean defaultAutoCommit = isDefaultAutoCommit(); if (username != null) { Boolean userMax = getPerUserDefaultAutoCommit(username); if (userMax != null) { defaultAutoCommit = userMax.booleanValue(); } } boolean defaultReadOnly = isDefaultReadOnly(); if (username != null) { Boolean userMax = getPerUserDefaultReadOnly(username); if (userMax != null) { defaultReadOnly = userMax.booleanValue(); } } Connection con = pc.getConnection(); con.setAutoCommit(defaultAutoCommit); con.setReadOnly(defaultReadOnly); return con; }
/** * Attempt to retrieve a database connection using {@link #getPooledConnectionAndInfo(String, * String)} with the provided username and password. The password on the {@link * PooledConnectionAndInfo} instance returned by <code>getPooledConnectionAndInfo</code> is * compared to the <code>password</code> parameter. If the comparison fails, a database connection * using the supplied username and password is attempted. If the connection attempt fails, an * SQLException is thrown, indicating that the given password did not match the password used to * create the pooled connection. If the connection attempt succeeds, this means that the database * password has been changed. In this case, the <code>PooledConnectionAndInfo</code> instance * retrieved with the old password is destroyed and the <code>getPooledConnectionAndInfo</code> is * repeatedly invoked until a <code>PooledConnectionAndInfo</code> instance with the new password * is returned. */ @Override public Connection getConnection(String username, String password) throws SQLException { if (instanceKey == null) { throw new SQLException( "Must set the ConnectionPoolDataSource " + "through setDataSourceName or setConnectionPoolDataSource" + " before calling getConnection."); } getConnectionCalled = true; PooledConnectionAndInfo info = null; try { info = getPooledConnectionAndInfo(username, password); } catch (NoSuchElementException e) { closeDueToException(info); throw new SQLException("Cannot borrow connection from pool", e); } catch (RuntimeException e) { closeDueToException(info); throw e; } catch (SQLException e) { closeDueToException(info); throw e; } catch (Exception e) { closeDueToException(info); throw new SQLException("Cannot borrow connection from pool", e); } if (!(null == password ? null == info.getPassword() : password.equals( info.getPassword()))) { // Password on PooledConnectionAndInfo does not match try { // See if password has changed by attempting connection testCPDS(username, password); } catch (SQLException ex) { // Password has not changed, so refuse client, but return connection to the pool closeDueToException(info); throw new SQLException( "Given password did not match password used" + " to create the PooledConnection.", ex); } catch (javax.naming.NamingException ne) { throw new SQLException("NamingException encountered connecting to database", ne); } /* * Password must have changed -> destroy connection and keep retrying until we get a new, good one, * destroying any idle connections with the old passowrd as we pull them from the pool. */ final UserPassKey upkey = info.getUserPassKey(); final PooledConnectionManager manager = getConnectionManager(upkey); manager.invalidate(info.getPooledConnection()); // Destroy and remove from pool manager.setPassword( upkey.getPassword()); // Reset the password on the factory if using CPDSConnectionFactory info = null; for (int i = 0; i < 10; i++) { // Bound the number of retries - only needed if bad instances return try { info = getPooledConnectionAndInfo(username, password); } catch (NoSuchElementException e) { closeDueToException(info); throw new SQLException("Cannot borrow connection from pool", e); } catch (RuntimeException e) { closeDueToException(info); throw e; } catch (SQLException e) { closeDueToException(info); throw e; } catch (Exception e) { closeDueToException(info); throw new SQLException("Cannot borrow connection from pool", e); } if (info != null && password != null && password.equals(info.getPassword())) { break; } if (info != null) { manager.invalidate(info.getPooledConnection()); } info = null; } if (info == null) { throw new SQLException("Cannot borrow connection from pool - password change failure."); } } Connection con = info.getPooledConnection().getConnection(); try { setupDefaults(con, username); con.clearWarnings(); return con; } catch (SQLException ex) { try { con.close(); } catch (Exception exc) { getLogWriter().println("ignoring exception during close: " + exc); } throw ex; } }