/** * Creates a new {@link PooledConnectionAndInfo} from the given {@link UserPassKey}. * * @param upkey {@link UserPassKey} containing user credentials * @throws SQLException if the connection could not be created. * @see org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory#makeObject(java.lang.Object) */ @Override public synchronized PooledObject<PooledConnectionAndInfo> makeObject(UserPassKey upkey) throws Exception { PooledConnectionAndInfo pci = null; PooledConnection pc = null; String username = upkey.getUsername(); String password = upkey.getPassword(); if (username == null) { pc = _cpds.getPooledConnection(); } else { pc = _cpds.getPooledConnection(username, password); } if (pc == null) { throw new IllegalStateException( "Connection pool data source returned null from getPooledConnection"); } // should we add this object as a listener or the pool. // consider the validateObject method in decision pc.addConnectionEventListener(this); pci = new PooledConnectionAndInfo(pc, username, password); pcMap.put(pc, pci); return new DefaultPooledObject<>(pci); }
/** * 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; } }