You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2021/01/15 17:19:25 UTC

[tomcat] 01/02: Update Commons DBCP

This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 2aaffcd5fb05daa4ee138b59c84ec3a66be3961d
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Fri Jan 15 15:42:38 2021 +0000

    Update Commons DBCP
---
 MERGE.txt                                          |   2 +-
 .../apache/tomcat/dbcp/dbcp2/BasicDataSource.java  |  24 ++---
 .../tomcat/dbcp/dbcp2/BasicDataSourceFactory.java  |  40 ++++---
 .../tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java   |   5 +-
 .../tomcat/dbcp/dbcp2/DelegatingConnection.java    |  18 ++--
 .../dbcp/dbcp2/DelegatingDatabaseMetaData.java     |   3 +-
 .../tomcat/dbcp/dbcp2/DelegatingResultSet.java     |   6 +-
 .../tomcat/dbcp/dbcp2/DelegatingStatement.java     |  17 ++-
 .../tomcat/dbcp/dbcp2/DriverConnectionFactory.java |  13 +--
 .../apache/tomcat/dbcp/dbcp2/DriverFactory.java    |   6 +-
 .../org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java |  26 +++--
 .../dbcp/dbcp2/LifetimeExceededException.java      |   1 -
 .../tomcat/dbcp/dbcp2/ObjectNameWrapper.java       |   8 +-
 java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java    |  71 +++----------
 .../dbcp/dbcp2/PoolableCallableStatement.java      |   4 +-
 .../tomcat/dbcp/dbcp2/PoolableConnection.java      |  20 +++-
 .../dbcp/dbcp2/PoolableConnectionFactory.java      |  41 ++++---
 .../dbcp/dbcp2/PoolablePreparedStatement.java      |   8 +-
 .../tomcat/dbcp/dbcp2/PoolingConnection.java       |  17 ++-
 .../tomcat/dbcp/dbcp2/PoolingDataSource.java       |   4 +-
 .../apache/tomcat/dbcp/dbcp2/PoolingDriver.java    |  16 ++-
 .../apache/tomcat/dbcp/dbcp2/SQLExceptionList.java |   2 +-
 java/org/apache/tomcat/dbcp/dbcp2/Utils.java       |  45 +++++---
 .../dbcp/dbcp2/cpdsadapter/ConnectionImpl.java     |   4 +-
 .../dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java  | 118 +++++++--------------
 .../dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java       |   4 +-
 .../dbcp2/cpdsadapter/PooledConnectionImpl.java    |  55 ++++++++--
 .../dbcp2/datasources/CPDSConnectionFactory.java   |  19 ++--
 .../dbcp2/datasources/InstanceKeyDataSource.java   |   7 --
 .../datasources/InstanceKeyDataSourceFactory.java  |  18 ++--
 .../datasources/KeyedCPDSConnectionFactory.java    |  20 ++--
 .../tomcat/dbcp/dbcp2/datasources/PoolKey.java     |  26 ++---
 .../tomcat/dbcp/dbcp2/datasources/UserPassKey.java |  23 +---
 .../dbcp/dbcp2/datasources/package-info.java       |   2 +-
 webapps/docs/changelog.xml                         |   4 +
 35 files changed, 326 insertions(+), 371 deletions(-)

diff --git a/MERGE.txt b/MERGE.txt
index 52851d9..806669a 100644
--- a/MERGE.txt
+++ b/MERGE.txt
@@ -69,4 +69,4 @@ Sub-tree
 src/main/java/org/apache/commons/dbcp2
 src/main/resources/org/apache/commons/dbcp2
 The SHA1 ID / tag for the most recent commit to be merged to Tomcat is:
-6d232e547d5725e419832fc514fc0348aa897e7c (2020-08-11)
+e24196a95bbbc531eb3c5f1b19e1dc42fd78a783 (2021-01-15)
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java
index 61afa6f..8f11d75 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java
@@ -539,7 +539,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
 
             // Set up the poolable connection factory
             boolean success = false;
-            PoolableConnectionFactory poolableConnectionFactory;
+            final PoolableConnectionFactory poolableConnectionFactory;
             try {
                 poolableConnectionFactory = createPoolableConnectionFactory(driverConnectionFactory);
                 poolableConnectionFactory.setPoolStatements(poolPreparedStatements);
@@ -616,7 +616,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      */
     protected GenericObjectPool<PoolableConnection> createObjectPool(final PoolableConnectionFactory factory,
             final GenericObjectPoolConfig<PoolableConnection> poolConfig, final AbandonedConfig abandonedConfig) {
-        GenericObjectPool<PoolableConnection> gop;
+        final GenericObjectPool<PoolableConnection> gop;
         if (abandonedConfig != null && (abandonedConfig.getRemoveAbandonedOnBorrow()
                 || abandonedConfig.getRemoveAbandonedOnMaintenance())) {
             gop = new GenericObjectPool<>(factory, poolConfig, abandonedConfig);
@@ -697,7 +697,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      */
     @Override
     public boolean getAbandonedUsageTracking() {
-        return abandonedConfig == null ? false : abandonedConfig.getUseUsageTracking();
+        return abandonedConfig != null && abandonedConfig.getUseUsageTracking();
     }
 
     /**
@@ -793,8 +793,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      */
     @Override
     public String[] getConnectionInitSqlsAsArray() {
-        final Collection<String> result = getConnectionInitSqls();
-        return result.toArray(new String[0]);
+        return getConnectionInitSqls().toArray(Utils.EMPTY_STRING_ARRAY);
     }
 
     protected GenericObjectPool<PoolableConnection> getConnectionPool() {
@@ -889,8 +888,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      */
     @Override
     public String[] getDisconnectionSqlCodesAsArray() {
-        final Collection<String> result = getDisconnectionSqlCodes();
-        return result.toArray(new String[0]);
+        return getDisconnectionSqlCodes().toArray(Utils.EMPTY_STRING_ARRAY);
     }
 
     /**
@@ -1013,7 +1011,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      */
     @Override
     public boolean getLogAbandoned() {
-        return abandonedConfig == null ? false : abandonedConfig.getLogAbandoned();
+        return abandonedConfig != null && abandonedConfig.getLogAbandoned();
     }
 
     /**
@@ -1228,7 +1226,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      */
     @Override
     public boolean getRemoveAbandonedOnBorrow() {
-        return abandonedConfig == null ? false : abandonedConfig.getRemoveAbandonedOnBorrow();
+        return abandonedConfig != null && abandonedConfig.getRemoveAbandonedOnBorrow();
     }
 
     /**
@@ -1249,7 +1247,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      */
     @Override
     public boolean getRemoveAbandonedOnMaintenance() {
-        return abandonedConfig == null ? false : abandonedConfig.getRemoveAbandonedOnMaintenance();
+        return abandonedConfig != null && abandonedConfig.getRemoveAbandonedOnMaintenance();
     }
 
     /**
@@ -1477,8 +1475,8 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      * @param value the string to test, may be null.
      * @return boolean false if value is null, otherwise {@link String#isEmpty()}.
      */
-    private boolean isEmpty(String value) {
-        return value == null ? true : value.trim().isEmpty();
+    private boolean isEmpty(final String value) {
+        return value == null || value.trim().isEmpty();
     }
 
     /**
@@ -1526,7 +1524,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      *
      * @since 2.7.0
      */
-    protected void log(String message, Throwable throwable) {
+    protected void log(final String message, final Throwable throwable) {
         if (logWriter != null) {
             logWriter.println(message);
             throwable.printStackTrace(logWriter);
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java
index b8ae8f2..0b11b07 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java
@@ -49,7 +49,7 @@ import org.apache.tomcat.dbcp.pool2.impl.GenericObjectPoolConfig;
  * <code>BasicDataSource</code> bean properties with the following exceptions:
  * </p>
  * <ul>
- * <li><code>connectionInitSqls</code> must be passed to this factory as a single String using semi-colon to delimit the
+ * <li><code>connectionInitSqls</code> must be passed to this factory as a single String using semicolon to delimit the
  * statements whereas <code>BasicDataSource</code> requires a collection of Strings.</li>
  * </ul>
  *
@@ -299,9 +299,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
      */
     public static BasicDataSource createDataSource(final Properties properties) throws Exception {
         final BasicDataSource dataSource = new BasicDataSource();
-        String value = null;
-
-        value = properties.getProperty(PROP_DEFAULT_AUTO_COMMIT);
+        String value = properties.getProperty(PROP_DEFAULT_AUTO_COMMIT);
         if (value != null) {
             dataSource.setDefaultAutoCommit(Boolean.valueOf(value));
         }
@@ -349,7 +347,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
 
         value = properties.getProperty(PROP_CACHE_STATE);
         if (value != null) {
-            dataSource.setCacheState(Boolean.valueOf(value).booleanValue());
+            dataSource.setCacheState(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_DRIVER_CLASS_NAME);
@@ -359,7 +357,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
 
         value = properties.getProperty(PROP_LIFO);
         if (value != null) {
-            dataSource.setLifo(Boolean.valueOf(value).booleanValue());
+            dataSource.setLifo(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_MAX_TOTAL);
@@ -389,17 +387,17 @@ public class BasicDataSourceFactory implements ObjectFactory {
 
         value = properties.getProperty(PROP_TEST_ON_CREATE);
         if (value != null) {
-            dataSource.setTestOnCreate(Boolean.valueOf(value).booleanValue());
+            dataSource.setTestOnCreate(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_TEST_ON_BORROW);
         if (value != null) {
-            dataSource.setTestOnBorrow(Boolean.valueOf(value).booleanValue());
+            dataSource.setTestOnBorrow(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_TEST_ON_RETURN);
         if (value != null) {
-            dataSource.setTestOnReturn(Boolean.valueOf(value).booleanValue());
+            dataSource.setTestOnReturn(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_TIME_BETWEEN_EVICTION_RUNS_MILLIS);
@@ -429,7 +427,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
 
         value = properties.getProperty(PROP_TEST_WHILE_IDLE);
         if (value != null) {
-            dataSource.setTestWhileIdle(Boolean.valueOf(value).booleanValue());
+            dataSource.setTestWhileIdle(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_PASSWORD);
@@ -459,17 +457,17 @@ public class BasicDataSourceFactory implements ObjectFactory {
 
         value = properties.getProperty(PROP_ACCESS_TO_UNDERLYING_CONNECTION_ALLOWED);
         if (value != null) {
-            dataSource.setAccessToUnderlyingConnectionAllowed(Boolean.valueOf(value).booleanValue());
+            dataSource.setAccessToUnderlyingConnectionAllowed(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_REMOVE_ABANDONED_ON_BORROW);
         if (value != null) {
-            dataSource.setRemoveAbandonedOnBorrow(Boolean.valueOf(value).booleanValue());
+            dataSource.setRemoveAbandonedOnBorrow(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_REMOVE_ABANDONED_ON_MAINTENANCE);
         if (value != null) {
-            dataSource.setRemoveAbandonedOnMaintenance(Boolean.valueOf(value).booleanValue());
+            dataSource.setRemoveAbandonedOnMaintenance(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_REMOVE_ABANDONED_TIMEOUT);
@@ -479,22 +477,22 @@ public class BasicDataSourceFactory implements ObjectFactory {
 
         value = properties.getProperty(PROP_LOG_ABANDONED);
         if (value != null) {
-            dataSource.setLogAbandoned(Boolean.valueOf(value).booleanValue());
+            dataSource.setLogAbandoned(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_ABANDONED_USAGE_TRACKING);
         if (value != null) {
-            dataSource.setAbandonedUsageTracking(Boolean.valueOf(value).booleanValue());
+            dataSource.setAbandonedUsageTracking(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_POOL_PREPARED_STATEMENTS);
         if (value != null) {
-            dataSource.setPoolPreparedStatements(Boolean.valueOf(value).booleanValue());
+            dataSource.setPoolPreparedStatements(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_CLEAR_STATEMENT_POOL_ON_RETURN);
         if (value != null) {
-            dataSource.setClearStatementPoolOnReturn(Boolean.valueOf(value).booleanValue());
+            dataSource.setClearStatementPoolOnReturn(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_MAX_OPEN_PREPARED_STATEMENTS);
@@ -524,7 +522,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
 
         value = properties.getProperty(PROP_LOG_EXPIRED_CONNECTIONS);
         if (value != null) {
-            dataSource.setLogExpiredConnections(Boolean.valueOf(value).booleanValue());
+            dataSource.setLogExpiredConnections(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_JMX_NAME);
@@ -534,12 +532,12 @@ public class BasicDataSourceFactory implements ObjectFactory {
 
         value = properties.getProperty(PROP_ENABLE_AUTO_COMMIT_ON_RETURN);
         if (value != null) {
-            dataSource.setAutoCommitOnReturn(Boolean.valueOf(value).booleanValue());
+            dataSource.setAutoCommitOnReturn(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_ROLLBACK_ON_RETURN);
         if (value != null) {
-            dataSource.setRollbackOnReturn(Boolean.valueOf(value).booleanValue());
+            dataSource.setRollbackOnReturn(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_DEFAULT_QUERY_TIMEOUT);
@@ -549,7 +547,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
 
         value = properties.getProperty(PROP_FAST_FAIL_VALIDATION);
         if (value != null) {
-            dataSource.setFastFailValidation(Boolean.valueOf(value).booleanValue());
+            dataSource.setFastFailValidation(Boolean.parseBoolean(value));
         }
 
         value = properties.getProperty(PROP_DISCONNECTION_SQL_CODES);
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java
index 564a630..8cd178d 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java
@@ -329,15 +329,16 @@ public interface BasicDataSourceMXBean {
      *
      * @throws SQLException if an error occurs initializing the datasource
      *
-     * @since 2.8
+     * @since 2.8.0
      */
     void start() throws SQLException;
 
     /**
      * See {@link BasicDataSource#restart()}
+     *
      * @throws SQLException if an error occurs initializing the datasource
      *
-     * @since 2.8
+     * @since 2.8.0
      */
     void restart() throws SQLException;
 }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java
index 45e4dd6..5c02916 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java
@@ -80,7 +80,6 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
      *            the {@link Connection} to delegate all calls to.
      */
     public DelegatingConnection(final C c) {
-        super();
         connection = c;
     }
 
@@ -97,14 +96,12 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
                 if (conn.isClosed()) {
                     str = "connection is closed";
                 } else {
-                    final StringBuffer sb = new StringBuffer();
+                    final StringBuilder sb = new StringBuilder();
                     sb.append(hashCode());
                     final DatabaseMetaData meta = conn.getMetaData();
                     if (meta != null) {
                         sb.append(", URL=");
                         sb.append(meta.getURL());
-                        sb.append(", UserName=");
-                        sb.append(meta.getUserName());
                         sb.append(", ");
                         sb.append(meta.getDriverName());
                         str = sb.toString();
@@ -171,7 +168,7 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
      */
     public final Connection getInnermostDelegateInternal() {
         Connection conn = connection;
-        while (conn != null && conn instanceof DelegatingConnection) {
+        while (conn instanceof DelegatingConnection) {
             conn = ((DelegatingConnection<?>) conn).getDelegateInternal();
             if (this == conn) {
                 return null;
@@ -619,11 +616,11 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
         final List<AbandonedTrace> traces = getTrace();
         if (traces != null && !traces.isEmpty()) {
             final List<Exception> thrownList = new ArrayList<>();
-            for (Object trace : traces) {
+            for (final Object trace : traces) {
                 if (trace instanceof Statement) {
                     try {
                         ((Statement) trace).close();
-                    } catch (Exception e) {
+                    } catch (final Exception e) {
                         thrownList.add(e);
                     }
                 } else if (trace instanceof ResultSet) {
@@ -631,7 +628,7 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
                     // generated via DatabaseMetaData
                     try {
                         ((ResultSet) trace).close();
-                    } catch (Exception e) {
+                    } catch (final Exception e) {
                         thrownList.add(e);
                     }
                 }
@@ -767,7 +764,7 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
     }
 
     @Override
-    public PreparedStatement prepareStatement(final String sql, final int columnIndexes[]) throws SQLException {
+    public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException {
         checkOpen();
         try {
             final DelegatingPreparedStatement dps = new DelegatingPreparedStatement(this,
@@ -781,7 +778,7 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
     }
 
     @Override
-    public PreparedStatement prepareStatement(final String sql, final String columnNames[]) throws SQLException {
+    public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException {
         checkOpen();
         try {
             final DelegatingPreparedStatement dps = new DelegatingPreparedStatement(this,
@@ -964,7 +961,6 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
 
     @Override
     public void abort(final Executor executor) throws SQLException {
-        checkOpen();
         try {
             Jdbc41Bridge.abort(connection, executor);
         } catch (final SQLException e) {
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java
index a3f9bc1..571187a 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java
@@ -51,7 +51,6 @@ public class DelegatingDatabaseMetaData implements DatabaseMetaData {
      */
     public DelegatingDatabaseMetaData(final DelegatingConnection<?> connection,
             final DatabaseMetaData databaseMetaData) {
-        super();
         this.connection = connection;
         this.databaseMetaData = databaseMetaData;
     }
@@ -439,7 +438,7 @@ public class DelegatingDatabaseMetaData implements DatabaseMetaData {
      */
     public DatabaseMetaData getInnermostDelegate() {
         DatabaseMetaData m = databaseMetaData;
-        while (m != null && m instanceof DelegatingDatabaseMetaData) {
+        while (m instanceof DelegatingDatabaseMetaData) {
             m = ((DelegatingDatabaseMetaData) m).getDelegate();
             if (this == m) {
                 return null;
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java
index c5650f5..f0d8484 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java
@@ -606,7 +606,7 @@ public final class DelegatingResultSet extends AbandonedTrace implements ResultS
      */
     public ResultSet getInnermostDelegate() {
         ResultSet r = resultSet;
-        while (r != null && r instanceof DelegatingResultSet) {
+        while (r instanceof DelegatingResultSet) {
             r = ((DelegatingResultSet) r).getDelegate();
             if (this == r) {
                 return null;
@@ -1045,9 +1045,9 @@ public final class DelegatingResultSet extends AbandonedTrace implements ResultS
     }
 
     protected void handleException(final SQLException e) throws SQLException {
-        if (statement != null && statement instanceof DelegatingStatement) {
+        if (statement instanceof DelegatingStatement) {
             ((DelegatingStatement) statement).handleException(e);
-        } else if (connection != null && connection instanceof DelegatingConnection) {
+        } else if (connection instanceof DelegatingConnection) {
             ((DelegatingConnection<?>) connection).handleException(e);
         } else {
             throw e;
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java
index 9f5fec1..770680e 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java
@@ -139,13 +139,12 @@ public class DelegatingStatement extends AbandonedTrace implements Statement {
             // See bug 17301 for what could happen when ResultSets are closed twice.
             final List<AbandonedTrace> resultSetList = getTrace();
             if (resultSetList != null) {
-                final int size = resultSetList.size();
-                final ResultSet[] resultSets = resultSetList.toArray(new ResultSet[size]);
+                final ResultSet[] resultSets = resultSetList.toArray(Utils.EMPTY_RESULT_SET_ARRAY);
                 for (final ResultSet resultSet : resultSets) {
                     if (resultSet != null) {
                         try {
                             resultSet.close();
-                        } catch (Exception e) {
+                        } catch (final Exception e) {
                             if (connection != null) {
                                 // Does not rethrow e.
                                 connection.handleExceptionNoThrow(e);
@@ -159,7 +158,7 @@ public class DelegatingStatement extends AbandonedTrace implements Statement {
             if (statement != null) {
                 try {
                     statement.close();
-                } catch (Exception e) {
+                } catch (final Exception e) {
                     if (connection != null) {
                         // Does not rethrow e.
                         connection.handleExceptionNoThrow(e);
@@ -211,7 +210,7 @@ public class DelegatingStatement extends AbandonedTrace implements Statement {
     }
 
     @Override
-    public boolean execute(final String sql, final int columnIndexes[]) throws SQLException {
+    public boolean execute(final String sql, final int[] columnIndexes) throws SQLException {
         checkOpen();
         setLastUsedInParent();
         try {
@@ -223,7 +222,7 @@ public class DelegatingStatement extends AbandonedTrace implements Statement {
     }
 
     @Override
-    public boolean execute(final String sql, final String columnNames[]) throws SQLException {
+    public boolean execute(final String sql, final String[] columnNames) throws SQLException {
         checkOpen();
         setLastUsedInParent();
         try {
@@ -283,7 +282,7 @@ public class DelegatingStatement extends AbandonedTrace implements Statement {
     }
 
     @Override
-    public int executeUpdate(final String sql, final int columnIndexes[]) throws SQLException {
+    public int executeUpdate(final String sql, final int[] columnIndexes) throws SQLException {
         checkOpen();
         setLastUsedInParent();
         try {
@@ -295,7 +294,7 @@ public class DelegatingStatement extends AbandonedTrace implements Statement {
     }
 
     @Override
-    public int executeUpdate(final String sql, final String columnNames[]) throws SQLException {
+    public int executeUpdate(final String sql, final String[] columnNames) throws SQLException {
         checkOpen();
         setLastUsedInParent();
         try {
@@ -391,7 +390,7 @@ public class DelegatingStatement extends AbandonedTrace implements Statement {
      */
     public Statement getInnermostDelegate() {
         Statement s = statement;
-        while (s != null && s instanceof DelegatingStatement) {
+        while (s instanceof DelegatingStatement) {
             s = ((DelegatingStatement) s).getDelegate();
             if (this == s) {
                 return null;
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java
index 45444ec..a575291 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java
@@ -37,12 +37,9 @@ public class DriverConnectionFactory implements ConnectionFactory {
     /**
      * Constructs a connection factory for a given Driver.
      *
-     * @param driver
-     *            The Driver.
-     * @param connectString
-     *            The connection string.
-     * @param properties
-     *            The connection properties.
+     * @param driver The Driver.
+     * @param connectString The connection string.
+     * @param properties The connection properties.
      */
     public DriverConnectionFactory(final Driver driver, final String connectString, final Properties properties) {
         this.driver = driver;
@@ -81,7 +78,7 @@ public class DriverConnectionFactory implements ConnectionFactory {
 
     @Override
     public String toString() {
-        return this.getClass().getName() + " [" + String.valueOf(driver) + ";" + String.valueOf(connectionString) + ";"
-                + String.valueOf(properties) + "]";
+        return this.getClass().getName() + " [" + driver + ";" + connectionString + ";"
+            + Utils.cloneWithoutCredentials(properties) + "]";
     }
 }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java
index 82af50d..465418c 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java
@@ -31,9 +31,9 @@ class DriverFactory {
     static Driver createDriver(final BasicDataSource basicDataSource) throws SQLException {
         // Load the JDBC driver class
         Driver driverToUse = basicDataSource.getDriver();
-        String driverClassName = basicDataSource.getDriverClassName();
-        ClassLoader driverClassLoader = basicDataSource.getDriverClassLoader();
-        String url = basicDataSource.getUrl();
+        final String driverClassName = basicDataSource.getDriverClassName();
+        final ClassLoader driverClassLoader = basicDataSource.getDriverClassLoader();
+        final String url = basicDataSource.getUrl();
 
         if (driverToUse == null) {
             Class<?> driverFromCCL = null;
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java b/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java
index 0cb852a..15b943d 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java
@@ -43,13 +43,19 @@ import javax.sql.CommonDataSource;
 /**
  * Defines bridge methods to JDBC 4.1 (Java 7) methods to allow call sites to operate safely (without
  * {@link AbstractMethodError}) when using a JDBC driver written for JDBC 4.0 (Java 6).
+ * <p>
+ * There should be no need to this kind of code for JDBC 4.2 in Java 8 due to JDBC's use of default methods.
+ * </p>
+ * <p>
+ * This should probably be moved or at least copied in some form to Apache Commons DbUtils.
+ * </p>
  *
  * @since 2.6.0
  */
 public class Jdbc41Bridge {
 
     /**
-     * Delegates to {@link Connection#abort(Executor)} without throwing a {@link AbstractMethodError}.
+     * Delegates to {@link Connection#abort(Executor)} without throwing an {@link AbstractMethodError}.
      * <p>
      * If the JDBC driver does not implement {@link Connection#abort(Executor)}, then call {@link Connection#close()}.
      * </p>
@@ -94,7 +100,7 @@ public class Jdbc41Bridge {
     }
 
     /**
-     * Delegates to {@link Connection#getNetworkTimeout()} without throwing a {@link AbstractMethodError}.
+     * Delegates to {@link Connection#getNetworkTimeout()} without throwing an {@link AbstractMethodError}.
      * <p>
      * If the JDBC driver does not implement {@link Connection#getNetworkTimeout()}, then return 0.
      * </p>
@@ -115,7 +121,7 @@ public class Jdbc41Bridge {
     }
 
     /**
-     * Delegates to {@link ResultSet#getObject(int, Class)} without throwing a {@link AbstractMethodError}.
+     * Delegates to {@link ResultSet#getObject(int, Class)} without throwing an {@link AbstractMethodError}.
      * <p>
      * If the JDBC driver does not implement {@link ResultSet#getObject(int, Class)}, then return 0.
      * </p>
@@ -215,7 +221,7 @@ public class Jdbc41Bridge {
     }
 
     /**
-     * Delegates to {@link ResultSet#getObject(String, Class)} without throwing a {@link AbstractMethodError}.
+     * Delegates to {@link ResultSet#getObject(String, Class)} without throwing an {@link AbstractMethodError}.
      *
      * @param <T>
      *            See {@link ResultSet#getObject(String, Class)}
@@ -343,7 +349,7 @@ public class Jdbc41Bridge {
     }
 
     /**
-     * Delegates to {@link Connection#getSchema()} without throwing a {@link AbstractMethodError}.
+     * Delegates to {@link Connection#getSchema()} without throwing an {@link AbstractMethodError}.
      * <p>
      * If the JDBC driver does not implement {@link Connection#getSchema()}, then return null.
      * </p>
@@ -365,7 +371,7 @@ public class Jdbc41Bridge {
     }
 
     /**
-     * Delegates to {@link Connection#setNetworkTimeout(Executor, int)} without throwing a {@link AbstractMethodError}.
+     * Delegates to {@link Connection#setNetworkTimeout(Executor, int)} without throwing an {@link AbstractMethodError}.
      * <p>
      * If the JDBC driver does not implement {@link Connection#setNetworkTimeout(Executor, int)}, then do nothing.
      * </p>
@@ -390,7 +396,7 @@ public class Jdbc41Bridge {
     }
 
     /**
-     * Delegates to {@link Connection#setSchema(String)} without throwing a {@link AbstractMethodError}.
+     * Delegates to {@link Connection#setSchema(String)} without throwing an {@link AbstractMethodError}.
      * <p>
      * If the JDBC driver does not implement {@link Connection#setSchema(String)}, then do nothing.
      * </p>
@@ -412,7 +418,7 @@ public class Jdbc41Bridge {
     }
 
     /**
-     * Delegates to {@link Statement#closeOnCompletion()} without throwing a {@link AbstractMethodError}.
+     * Delegates to {@link Statement#closeOnCompletion()} without throwing an {@link AbstractMethodError}.
      * <p>
      * If the JDBC driver does not implement {@link Statement#closeOnCompletion()}, then just check that the connection
      * is closed to then throw an SQLException.
@@ -435,7 +441,7 @@ public class Jdbc41Bridge {
     }
 
     /**
-     * Delegates to {@link Statement#isCloseOnCompletion()} without throwing a {@link AbstractMethodError}.
+     * Delegates to {@link Statement#isCloseOnCompletion()} without throwing an {@link AbstractMethodError}.
      * <p>
      * If the JDBC driver does not implement {@link Statement#isCloseOnCompletion()}, then just check that the
      * connection is closed to then throw an SQLException.
@@ -460,7 +466,7 @@ public class Jdbc41Bridge {
     }
 
     /**
-     * Delegates to {@link CommonDataSource#getParentLogger()} without throwing a {@link AbstractMethodError}.
+     * Delegates to {@link CommonDataSource#getParentLogger()} without throwing an {@link AbstractMethodError}.
      * <p>
      * If the JDBC driver does not implement {@link CommonDataSource#getParentLogger()}, then return null.
      * </p>
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java b/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java
index 2d440cb..dd2bbdd 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java
@@ -29,7 +29,6 @@ class LifetimeExceededException extends Exception {
      * Create a LifetimeExceededException.
      */
     public LifetimeExceededException() {
-        super();
     }
 
     /**
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java b/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java
index 9c78936..ec68460 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java
@@ -36,12 +36,12 @@ class ObjectNameWrapper {
 
     private static final Log log = LogFactory.getLog(ObjectNameWrapper.class);
 
-    private static MBeanServer MBEAN_SERVER = getPlatformMBeanServer();
+    private static final MBeanServer MBEAN_SERVER = getPlatformMBeanServer();
 
     private static MBeanServer getPlatformMBeanServer() {
         try {
             return ManagementFactory.getPlatformMBeanServer();
-        } catch (LinkageError | Exception e) {
+        } catch (final LinkageError | Exception e) {
             // ignore - JMX not available
             log.debug("Failed to get platform MBeanServer", e);
             return null;
@@ -72,7 +72,7 @@ class ObjectNameWrapper {
         }
         try {
             MBEAN_SERVER.registerMBean(object, objectName);
-        } catch (LinkageError | Exception e) {
+        } catch (final LinkageError | Exception e) {
             log.warn("Failed to complete JMX registration for " + objectName, e);
         }
     }
@@ -92,7 +92,7 @@ class ObjectNameWrapper {
         if (MBEAN_SERVER.isRegistered(objectName)) {
             try {
                 MBEAN_SERVER.unregisterMBean(objectName);
-            } catch (LinkageError | Exception e) {
+            } catch (final LinkageError | Exception e) {
                 log.warn("Failed to complete JMX unregistration for " + objectName, e);
             }
         }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java b/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java
index 39d149a..3b5daf3 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java
@@ -20,6 +20,7 @@ import java.sql.Connection;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.Arrays;
+import java.util.Objects;
 
 import org.apache.tomcat.dbcp.dbcp2.PoolingConnection.StatementType;
 
@@ -56,8 +57,7 @@ public class PStmtKey {
     private class PreparedCallWithResultSetHoldability implements StatementBuilder {
         @Override
         public Statement createStatement(final Connection connection) throws SQLException {
-            return connection.prepareCall(sql, resultSetType.intValue(), resultSetConcurrency.intValue(),
-                    resultSetHoldability.intValue());
+            return connection.prepareCall(sql, resultSetType.intValue(), resultSetConcurrency.intValue(), resultSetHoldability.intValue());
         }
     }
 
@@ -117,8 +117,7 @@ public class PStmtKey {
     private class PreparedStatementWithResultSetHoldability implements StatementBuilder {
         @Override
         public Statement createStatement(final Connection connection) throws SQLException {
-            return connection.prepareStatement(sql, resultSetType.intValue(), resultSetConcurrency.intValue(),
-                    resultSetHoldability.intValue());
+            return connection.prepareStatement(sql, resultSetType.intValue(), resultSetConcurrency.intValue(), resultSetHoldability.intValue());
         }
     }
 
@@ -798,18 +797,10 @@ public class PStmtKey {
             return false;
         }
         final PStmtKey other = (PStmtKey) obj;
-        if (autoGeneratedKeys == null) {
-            if (other.autoGeneratedKeys != null) {
-                return false;
-            }
-        } else if (!autoGeneratedKeys.equals(other.autoGeneratedKeys)) {
+        if (!Objects.equals(autoGeneratedKeys, other.autoGeneratedKeys)) {
             return false;
         }
-        if (catalog == null) {
-            if (other.catalog != null) {
-                return false;
-            }
-        } else if (!catalog.equals(other.catalog)) {
+        if (!Objects.equals(catalog, other.catalog)) {
             return false;
         }
         if (!Arrays.equals(columnIndexes, other.columnIndexes)) {
@@ -818,45 +809,22 @@ public class PStmtKey {
         if (!Arrays.equals(columnNames, other.columnNames)) {
             return false;
         }
-        if (resultSetConcurrency == null) {
-            if (other.resultSetConcurrency != null) {
-                return false;
-            }
-        } else if (!resultSetConcurrency.equals(other.resultSetConcurrency)) {
+        if (!Objects.equals(resultSetConcurrency, other.resultSetConcurrency)) {
             return false;
         }
-        if (resultSetHoldability == null) {
-            if (other.resultSetHoldability != null) {
-                return false;
-            }
-        } else if (!resultSetHoldability.equals(other.resultSetHoldability)) {
+        if (!Objects.equals(resultSetHoldability, other.resultSetHoldability)) {
             return false;
         }
-        if (resultSetType == null) {
-            if (other.resultSetType != null) {
-                return false;
-            }
-        } else if (!resultSetType.equals(other.resultSetType)) {
+        if (!Objects.equals(resultSetType, other.resultSetType)) {
             return false;
         }
-        if (schema == null) {
-            if (other.schema != null) {
-                return false;
-            }
-        } else if (!schema.equals(other.schema)) {
+        if (!Objects.equals(schema, other.schema)) {
             return false;
         }
-        if (sql == null) {
-            if (other.sql != null) {
-                return false;
-            }
-        } else if (!sql.equals(other.sql)) {
+        if (!Objects.equals(sql, other.sql)) {
             return false;
         }
-        if (statementType != other.statementType) {
-            return false;
-        }
-        return true;
+        return statementType == other.statementType;
     }
 
     /**
@@ -955,24 +923,13 @@ public class PStmtKey {
 
     @Override
     public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((autoGeneratedKeys == null) ? 0 : autoGeneratedKeys.hashCode());
-        result = prime * result + ((catalog == null) ? 0 : catalog.hashCode());
-        result = prime * result + Arrays.hashCode(columnIndexes);
-        result = prime * result + Arrays.hashCode(columnNames);
-        result = prime * result + ((resultSetConcurrency == null) ? 0 : resultSetConcurrency.hashCode());
-        result = prime * result + ((resultSetHoldability == null) ? 0 : resultSetHoldability.hashCode());
-        result = prime * result + ((resultSetType == null) ? 0 : resultSetType.hashCode());
-        result = prime * result + ((schema == null) ? 0 : schema.hashCode());
-        result = prime * result + ((sql == null) ? 0 : sql.hashCode());
-        result = prime * result + ((statementType == null) ? 0 : statementType.hashCode());
-        return result;
+        return Objects.hash(autoGeneratedKeys, catalog, Integer.valueOf(Arrays.hashCode(columnIndexes)), Integer.valueOf(Arrays.hashCode(columnNames)),
+            resultSetConcurrency, resultSetHoldability, resultSetType, schema, sql, statementType);
     }
 
     @Override
     public String toString() {
-        final StringBuffer buf = new StringBuffer();
+        final StringBuilder buf = new StringBuilder();
         buf.append("PStmtKey: sql=");
         buf.append(sql);
         buf.append(", catalog=");
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java
index f8456980..5057701 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java
@@ -121,12 +121,12 @@ public class PoolableCallableStatement extends DelegatingCallableStatement {
         final List<AbandonedTrace> resultSetList = getTrace();
         if (resultSetList != null) {
             final List<Exception> thrownList = new ArrayList<>();
-            final ResultSet[] resultSets = resultSetList.toArray(new ResultSet[0]);
+            final ResultSet[] resultSets = resultSetList.toArray(Utils.EMPTY_RESULT_SET_ARRAY);
             for (final ResultSet resultSet : resultSets) {
                 if (resultSet != null) {
                     try {
                         resultSet.close();
-                    } catch (Exception e) {
+                    } catch (final Exception e) {
                         thrownList.add(e);
                     }
                 }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java
index bdca159..6b052ce 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java
@@ -22,6 +22,7 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.Collection;
+import java.util.concurrent.Executor;
 
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.MBeanRegistrationException;
@@ -44,7 +45,7 @@ public class PoolableConnection extends DelegatingConnection<Connection> impleme
     static {
         try {
             MBEAN_SERVER = ManagementFactory.getPlatformMBeanServer();
-        } catch (NoClassDefFoundError | Exception ex) {
+        } catch (final NoClassDefFoundError | Exception ex) {
             // ignore - JMX not available
         }
     }
@@ -205,9 +206,7 @@ public class PoolableConnection extends DelegatingConnection<Connection> impleme
                 // pool is closed, so close the connection
                 passivate();
                 getInnermostDelegate().close();
-            } catch (final SQLException e) {
-                throw e;
-            } catch (final RuntimeException e) {
+            } catch (final SQLException | RuntimeException e) {
                 throw e;
             } catch (final Exception e) {
                 throw new SQLException("Cannot close connection (return to pool failed)", e);
@@ -236,6 +235,19 @@ public class PoolableConnection extends DelegatingConnection<Connection> impleme
     }
 
     /**
+     * Abort my underlying {@link Connection}.
+     *
+     * @since 2.9.0
+     */
+    @Override
+    public void abort(Executor executor) throws SQLException {
+        if (jmxObjectName != null) {
+            jmxObjectName.unregisterMBean();
+        }
+        super.abort(executor);
+    }
+
+    /**
      * Expose the {@link #toString()} method via a bean getter so it can be read as a property via JMX.
      */
     @Override
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java
index b25bb9a..97d1897 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java
@@ -28,6 +28,7 @@ import javax.management.ObjectName;
 
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.dbcp.pool2.DestroyMode;
 import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
 import org.apache.tomcat.dbcp.pool2.ObjectPool;
 import org.apache.tomcat.dbcp.pool2.PooledObject;
@@ -140,6 +141,14 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
     }
 
     /**
+     * @since 2.9.0
+     */
+    @Override
+    public void destroyObject(final PooledObject<PoolableConnection> p, final DestroyMode mode) throws Exception {
+        destroyObject(p);
+    }
+
+    /**
      * @return The cache state.
      * @since Made public in 2.6.0.
      */
@@ -269,7 +278,6 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
     protected int getMaxOpenPreparedStatements() {
         return maxOpenPreparedStatements;
     }
-
     /**
      * Returns the {@link ObjectPool} in which {@link Connection}s are pooled.
      *
@@ -278,7 +286,6 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
     public synchronized ObjectPool<PoolableConnection> getPool() {
         return pool;
     }
-
     /**
      * @return Whether to pool statements.
      * @since Made public in 2.6.0.
@@ -293,6 +300,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
     public String getValidationQuery() {
         return validationQuery;
     }
+
     /**
      * @return Validation query timeout in seconds.
      * @since 2.6.0
@@ -300,6 +308,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
     public int getValidationQueryTimeoutSeconds() {
         return validationQueryTimeoutSeconds;
     }
+
     protected void initializeConnection(final Connection conn) throws SQLException {
         final Collection<String> sqls = connectionInitSqls;
         if (conn.isClosed()) {
@@ -384,7 +393,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
             if (dataSourceJmxObjectName != null) {
                 final StringBuilder base = new StringBuilder(dataSourceJmxObjectName.toString());
                 base.append(Constants.JMX_CONNECTION_BASE_EXT);
-                base.append(Long.toString(connIndex));
+                base.append(connIndex);
                 config.setJmxNameBase(base.toString());
                 config.setJmxNamePrefix(Constants.JMX_STATEMENT_POOL_PREFIX);
             } else {
@@ -399,7 +408,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
         }
 
         // Register this connection with JMX
-        ObjectName connJmxName;
+        final ObjectName connJmxName;
         if (dataSourceJmxObjectName == null) {
             connJmxName = null;
         } else {
@@ -453,6 +462,17 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
     }
 
     /**
+     * Sets whether the pool of statements (which was enabled with {@link #setPoolStatements(boolean)}) should
+     * be cleared when the connection is returned to its pool. Default is false.
+     *
+     * @param clearStatementPoolOnReturn clear or not
+     * @since 2.8.0
+     */
+    public void setClearStatementPoolOnReturn(final boolean clearStatementPoolOnReturn) {
+        this.clearStatementPoolOnReturn = clearStatementPoolOnReturn;
+    }
+
+    /**
      * Sets the SQL statements I use to initialize newly created {@link Connection}s. Using {@code null} turns off
      * connection initialization.
      *
@@ -462,7 +482,6 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
     public void setConnectionInitSql(final Collection<String> connectionInitSqls) {
         this.connectionInitSqls = connectionInitSqls;
     }
-
     /**
      * Sets the default "auto commit" setting for borrowed {@link Connection}s
      *
@@ -486,6 +505,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
     public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) {
         this.defaultQueryTimeoutSeconds = defaultQueryTimeoutSeconds;
     }
+
     /**
      * Sets the default "read only" setting for borrowed {@link Connection}s
      *
@@ -600,17 +620,6 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
         this.poolStatements = poolStatements;
     }
 
-    /**
-     * Sets whether the pool of statements (which was enabled with {@link #setPoolStatements(boolean)}) should
-     * be cleared when the connection is returned to its pool. Default is false.
-     *
-     * @param clearStatementPoolOnReturn clear or not
-     * @since 2.8.0
-     */
-    public void setClearStatementPoolOnReturn(final boolean clearStatementPoolOnReturn) {
-        this.clearStatementPoolOnReturn = clearStatementPoolOnReturn;
-    }
-
     public void setRollbackOnReturn(final boolean rollbackOnReturn) {
         this.rollbackOnReturn = rollbackOnReturn;
     }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java
index 0da2fab..765213d 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java
@@ -102,9 +102,7 @@ public class PoolablePreparedStatement<K> extends DelegatingPreparedStatement {
         if (!isClosed()) {
             try {
                 pool.returnObject(key, this);
-            } catch (final SQLException e) {
-                throw e;
-            } catch (final RuntimeException e) {
+            } catch (final SQLException | RuntimeException e) {
                 throw e;
             } catch (final Exception e) {
                 throw new SQLException("Cannot close preparedstatement (return to pool failed)", e);
@@ -138,12 +136,12 @@ public class PoolablePreparedStatement<K> extends DelegatingPreparedStatement {
         final List<AbandonedTrace> resultSetList = getTrace();
         if (resultSetList != null) {
             final List<Exception> thrownList = new ArrayList<>();
-            final ResultSet[] resultSets = resultSetList.toArray(new ResultSet[0]);
+            final ResultSet[] resultSets = resultSetList.toArray(Utils.EMPTY_RESULT_SET_ARRAY);
             for (final ResultSet resultSet : resultSets) {
                 if (resultSet != null) {
                     try {
                         resultSet.close();
-                    } catch (Exception e) {
+                    } catch (final Exception e) {
                         thrownList.add(e);
                     }
                 }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java
index 6dd738f..f029a28 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java
@@ -23,6 +23,7 @@ import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.util.NoSuchElementException;
 
+import org.apache.tomcat.dbcp.pool2.DestroyMode;
 import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
 import org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory;
 import org.apache.tomcat.dbcp.pool2.PooledObject;
@@ -129,7 +130,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
         if (pstmtPool != null && clearStatementPoolOnReturn) {
             try {
                 pstmtPool.clear();
-            } catch (Exception e) {
+            } catch (final Exception e) {
                 throw new SQLException("Error clearing statement pool", e);
             }
         }
@@ -158,7 +159,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
      *
      * @return the PStmtKey created for the given arguments.
      */
-    protected PStmtKey createKey(final String sql, final int columnIndexes[]) {
+    protected PStmtKey createKey(final String sql, final int[] columnIndexes) {
         return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), columnIndexes);
     }
 
@@ -278,7 +279,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
      *
      * @return the PStmtKey created for the given arguments.
      */
-    protected PStmtKey createKey(final String sql, final String columnNames[]) {
+    protected PStmtKey createKey(final String sql, final String[] columnNames) {
         return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), columnNames);
     }
 
@@ -297,6 +298,12 @@ public class PoolingConnection extends DelegatingConnection<Connection>
         pooledObject.getObject().getInnermostDelegate().close();
     }
 
+    @Override
+    public void destroyObject(PStmtKey key, PooledObject<DelegatingPreparedStatement> p,
+            DestroyMode mode) throws Exception {
+        destroyObject(key, p);
+    }
+
     private String getCatalogOrNull() {
         String catalog = null;
         try {
@@ -517,7 +524,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
      *
      */
     @Override
-    public PreparedStatement prepareStatement(final String sql, final int columnIndexes[]) throws SQLException {
+    public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException {
         return prepareStatement(createKey(sql, columnIndexes));
     }
 
@@ -573,7 +580,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
      *             Wraps an underlying exception.
      */
     @Override
-    public PreparedStatement prepareStatement(final String sql, final String columnNames[]) throws SQLException {
+    public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException {
         return prepareStatement(createKey(sql, columnNames));
     }
 
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java
index 38a0472..5f0ca20 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java
@@ -136,11 +136,9 @@ public class PoolingDataSource<C extends Connection> implements DataSource, Auto
                 return null;
             }
             return new PoolGuardConnectionWrapper<>(conn);
-        } catch (final SQLException e) {
-            throw e;
         } catch (final NoSuchElementException e) {
             throw new SQLException("Cannot get a connection, pool error " + e.getMessage(), e);
-        } catch (final RuntimeException e) {
+        } catch (final SQLException | RuntimeException e) {
             throw e;
         } catch (final InterruptedException e) {
             // Reset the interrupt status so it is visible to callers
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java
index bf9b97a..67b4c4d 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java
@@ -25,7 +25,6 @@ import java.sql.SQLFeatureNotSupportedException;
 import java.util.HashMap;
 import java.util.NoSuchElementException;
 import java.util.Properties;
-import java.util.Set;
 import java.util.logging.Logger;
 
 import org.apache.tomcat.dbcp.pool2.ObjectPool;
@@ -37,7 +36,9 @@ import org.apache.tomcat.dbcp.pool2.ObjectPool;
  */
 public class PoolingDriver implements Driver {
 
-    /** Register myself with the {@link DriverManager}. */
+    private static final DriverPropertyInfo[] EMPTY_DRIVER_PROPERTY_INFO_ARRAY = new DriverPropertyInfo[0];
+
+    /* Register myself with the {@link DriverManager}. */
     static {
         try {
             DriverManager.registerDriver(new PoolingDriver());
@@ -133,13 +134,12 @@ public class PoolingDriver implements Driver {
      * @return the pool names.
      */
     public synchronized String[] getPoolNames() {
-        final Set<String> names = pools.keySet();
-        return names.toArray(new String[0]);
+        return pools.keySet().toArray(Utils.EMPTY_STRING_ARRAY);
     }
 
     @Override
     public boolean acceptsURL(final String url) throws SQLException {
-        return url == null ? false : url.startsWith(URL_PREFIX);
+        return url != null && url.startsWith(URL_PREFIX);
     }
 
     @Override
@@ -153,11 +153,9 @@ public class PoolingDriver implements Driver {
                     return null;
                 }
                 return new PoolGuardConnectionWrapper(pool, conn);
-            } catch (final SQLException e) {
-                throw e;
             } catch (final NoSuchElementException e) {
                 throw new SQLException("Cannot get a connection, pool error: " + e.getMessage(), e);
-            } catch (final RuntimeException e) {
+            } catch (final SQLException | RuntimeException e) {
                 throw e;
             } catch (final Exception e) {
                 throw new SQLException("Cannot get a connection, general error: " + e.getMessage(), e);
@@ -212,7 +210,7 @@ public class PoolingDriver implements Driver {
 
     @Override
     public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) {
-        return new DriverPropertyInfo[0];
+        return EMPTY_DRIVER_PROPERTY_INFO_ARRAY;
     }
 
     /** My URL prefix */
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/SQLExceptionList.java b/java/org/apache/tomcat/dbcp/dbcp2/SQLExceptionList.java
index 3f8d1af..a8392b2 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/SQLExceptionList.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/SQLExceptionList.java
@@ -39,7 +39,7 @@ public class SQLExceptionList extends SQLException {
      *
      * @param causeList a list of cause exceptions.
      */
-    public SQLExceptionList(List<? extends Throwable> causeList) {
+    public SQLExceptionList(final List<? extends Throwable> causeList) {
         super(String.format("%,d exceptions: %s", Integer.valueOf(causeList == null ? 0 : causeList.size()), causeList),
                 causeList == null ? null : causeList.get(0));
         this.causeList = causeList;
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/Utils.java b/java/org/apache/tomcat/dbcp/dbcp2/Utils.java
index a24360f..ce497ff 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/Utils.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/Utils.java
@@ -18,8 +18,10 @@
 
 package org.apache.tomcat.dbcp.dbcp2;
 
+import java.sql.ResultSet;
 import java.text.MessageFormat;
 import java.util.HashSet;
+import java.util.Properties;
 import java.util.ResourceBundle;
 import java.util.Set;
 
@@ -31,7 +33,7 @@ import java.util.Set;
 public final class Utils {
 
     private static final ResourceBundle messages = ResourceBundle
-            .getBundle(Utils.class.getPackage().getName() + ".LocalStrings");
+        .getBundle(Utils.class.getPackage().getName() + ".LocalStrings");
 
     /**
      * Whether the security manager is enabled.
@@ -54,6 +56,9 @@ public final class Utils {
      */
     public static final Set<String> DISCONNECTION_SQL_CODES;
 
+    static final ResultSet[] EMPTY_RESULT_SET_ARRAY = new ResultSet[0];
+    static final String[] EMPTY_STRING_ARRAY = new String[0];
+
     static {
         DISCONNECTION_SQL_CODES = new HashSet<>();
         DISCONNECTION_SQL_CODES.add("57P01"); // Admin shutdown
@@ -67,8 +72,7 @@ public final class Utils {
     /**
      * Clones the given char[] if not null.
      *
-     * @param value
-     *            may be null.
+     * @param value may be null.
      * @return a cloned char[] or null.
      */
     public static char[] clone(final char[] value) {
@@ -76,10 +80,26 @@ public final class Utils {
     }
 
     /**
+     * Clones the given {@link Properties} without the standard "user" or "password" entries.
+     *
+     * @param properties may be null
+     * @return a clone of the input without the standard "user" or "password" entries.
+     * @since 2.8.0
+     */
+    public static Properties cloneWithoutCredentials(final Properties properties) {
+        if (properties != null) {
+            final Properties temp = (Properties) properties.clone();
+            temp.remove("user");
+            temp.remove("password");
+            return temp;
+        }
+        return properties;
+    }
+
+    /**
      * Closes the AutoCloseable (which may be null).
      *
-     * @param autoCloseable
-     *            an AutoCloseable, may be {@code null}
+     * @param autoCloseable an AutoCloseable, may be {@code null}
      * @since 2.6.0
      */
     public static void closeQuietly(final AutoCloseable autoCloseable) {
@@ -95,8 +115,7 @@ public final class Utils {
     /**
      * Gets the correct i18n message for the given key.
      *
-     * @param key
-     *            The key to look up an i18n message.
+     * @param key The key to look up an i18n message.
      * @return The i18n message.
      */
     public static String getMessage(final String key) {
@@ -106,10 +125,8 @@ public final class Utils {
     /**
      * Gets the correct i18n message for the given key with placeholders replaced by the supplied arguments.
      *
-     * @param key
-     *            A message key.
-     * @param args
-     *            The message arguments.
+     * @param key A message key.
+     * @param args The message arguments.
      * @return An i18n message.
      */
     public static String getMessage(final String key, final Object... args) {
@@ -124,8 +141,7 @@ public final class Utils {
     /**
      * Converts the given String to a char[].
      *
-     * @param value
-     *            may be null.
+     * @param value may be null.
      * @return a char[] or null.
      */
     public static char[] toCharArray(final String value) {
@@ -135,8 +151,7 @@ public final class Utils {
     /**
      * Converts the given char[] to a String.
      *
-     * @param value
-     *            may be null.
+     * @param value may be null.
      * @return a String or null.
      */
     public static String toString(final char[] value) {
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java
index ca6498a..720c36b 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java
@@ -242,7 +242,7 @@ class ConnectionImpl extends DelegatingConnection<Connection> {
     }
 
     @Override
-    public PreparedStatement prepareStatement(final String sql, final int columnIndexes[]) throws SQLException {
+    public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException {
         checkOpen();
         try {
             return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, columnIndexes));
@@ -253,7 +253,7 @@ class ConnectionImpl extends DelegatingConnection<Connection> {
     }
 
     @Override
-    public PreparedStatement prepareStatement(final String sql, final String columnNames[]) throws SQLException {
+    public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException {
         checkOpen();
         try {
             return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, columnNames));
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java
index 772682f..b912ba6 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java
@@ -85,7 +85,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     private static final long serialVersionUID = -4820523787212147844L;
 
     private static final String GET_CONNECTION_CALLED = "A PooledConnection was already requested from this source, "
-            + "further initialization is not allowed.";
+        + "further initialization is not allowed.";
 
     static {
         // Attempt to prevent deadlocks - see DBCP - 272
@@ -147,8 +147,8 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
         }
     }
 
-    private boolean getBooleanContentString(RefAddr ra) {
-        return Boolean.valueOf(getStringContent(ra)).booleanValue();
+    private boolean getBooleanContentString(final RefAddr ra) {
+        return Boolean.parseBoolean(getStringContent(ra));
     }
 
     /**
@@ -248,7 +248,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
      */
     @Override
     public Object getObjectInstance(final Object refObj, final Name name, final Context context,
-            final Hashtable<?, ?> env) throws Exception {
+        final Hashtable<?, ?> env) throws Exception {
         // The spec says to return null if we can't create an instance
         // of the reference
         DriverAdapterCPDS cpds = null;
@@ -351,14 +351,12 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     /**
      * Attempts to establish a database connection.
      *
-     * @param pooledUserName
-     *            name to be used for the connection
-     * @param pooledUserPassword
-     *            password to be used fur the connection
+     * @param pooledUserName name to be used for the connection
+     * @param pooledUserPassword password to be used fur the connection
      */
     @Override
     public PooledConnection getPooledConnection(final String pooledUserName, final String pooledUserPassword)
-            throws SQLException {
+        throws SQLException {
         getConnectionCalled = true;
         PooledConnectionImpl pooledConnection = null;
         // Workaround for buggy WebLogic 5.1 classloader - ignore the exception upon first invocation.
@@ -367,19 +365,19 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
                 update(connectionProperties, KEY_USER, pooledUserName);
                 update(connectionProperties, KEY_PASSWORD, pooledUserPassword);
                 pooledConnection = new PooledConnectionImpl(
-                        DriverManager.getConnection(getUrl(), connectionProperties));
+                    DriverManager.getConnection(getUrl(), connectionProperties));
             } else {
                 pooledConnection = new PooledConnectionImpl(
-                        DriverManager.getConnection(getUrl(), pooledUserName, pooledUserPassword));
+                    DriverManager.getConnection(getUrl(), pooledUserName, pooledUserPassword));
             }
             pooledConnection.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
         } catch (final ClassCircularityError e) {
             if (connectionProperties != null) {
                 pooledConnection = new PooledConnectionImpl(
-                        DriverManager.getConnection(getUrl(), connectionProperties));
+                    DriverManager.getConnection(getUrl(), connectionProperties));
             } else {
                 pooledConnection = new PooledConnectionImpl(
-                        DriverManager.getConnection(getUrl(), pooledUserName, pooledUserPassword));
+                    DriverManager.getConnection(getUrl(), pooledUserName, pooledUserPassword));
             }
             pooledConnection.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
         }
@@ -438,7 +436,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
         return ref;
     }
 
-    private String getStringContent(RefAddr ra) {
+    private String getStringContent(final RefAddr ra) {
         return ra.getContent().toString();
     }
 
@@ -480,7 +478,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
         return this.accessToUnderlyingConnectionAllowed;
     }
 
-    private boolean isNotEmpty(RefAddr ra) {
+    private boolean isNotEmpty(final RefAddr ra) {
         return ra != null && ra.getContent() != null;
     }
 
@@ -497,8 +495,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
      * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to
      * the underlying connection. (Default: false)
      *
-     * @param allow
-     *            Access to the underlying connection is granted when true.
+     * @param allow Access to the underlying connection is granted when true.
      */
     public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) {
         this.accessToUnderlyingConnectionAllowed = allow;
@@ -515,10 +512,8 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
      * null.
      * </p>
      *
-     * @param props
-     *            Connection properties to use when creating new connections.
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
+     * @param props Connection properties to use when creating new connections.
+     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
      */
     public void setConnectionProperties(final Properties props) {
         assertInitializationAllowed();
@@ -537,8 +532,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
      * Sets the value of description. This property is here for use by the code which will deploy this datasource. It is
      * not used internally.
      *
-     * @param v
-     *            Value to assign to description.
+     * @param v Value to assign to description.
      */
     public void setDescription(final String v) {
         this.description = v;
@@ -548,12 +542,9 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
      * Sets the driver class name. Setting the driver class name cause the driver to be registered with the
      * DriverManager.
      *
-     * @param v
-     *            Value to assign to driver.
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
-     * @throws ClassNotFoundException
-     *             if the class cannot be located
+     * @param v Value to assign to driver.
+     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
+     * @throws ClassNotFoundException if the class cannot be located
      */
     public void setDriver(final String v) throws ClassNotFoundException {
         assertInitializationAllowed();
@@ -583,10 +574,8 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
      * Gets the maximum number of statements that can remain idle in the pool, without extra ones being released, or
      * negative for no limit.
      *
-     * @param maxIdle
-     *            The maximum number of statements that can remain idle
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
+     * @param maxIdle The maximum number of statements that can remain idle
+     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
      */
     public void setMaxIdle(final int maxIdle) {
         assertInitializationAllowed();
@@ -596,8 +585,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     /**
      * Sets the maximum number of prepared statements.
      *
-     * @param maxPreparedStatements
-     *            the new maximum number of prepared statements
+     * @param maxPreparedStatements the new maximum number of prepared statements
      */
     public void setMaxPreparedStatements(final int maxPreparedStatements) {
         this.maxPreparedStatements = maxPreparedStatements;
@@ -607,12 +595,10 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
      * Sets the minimum amount of time a statement may sit idle in the pool before it is eligible for eviction by the
      * idle object evictor (if any). When non-positive, no objects will be evicted from the pool due to idle time alone.
      *
-     * @param minEvictableIdleTimeMillis
-     *            minimum time to set (in ms)
+     * @param minEvictableIdleTimeMillis minimum time to set (in ms)
      * @see #getMinEvictableIdleTimeMillis()
      * @see #setTimeBetweenEvictionRunsMillis(long)
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
+     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
      */
     public void setMinEvictableIdleTimeMillis(final int minEvictableIdleTimeMillis) {
         assertInitializationAllowed();
@@ -640,10 +626,8 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     /**
      * Sets the value of password for the default user.
      *
-     * @param userPassword
-     *            Value to assign to password.
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
+     * @param userPassword Value to assign to password.
+     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
      */
     public void setPassword(final char[] userPassword) {
         assertInitializationAllowed();
@@ -654,10 +638,8 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     /**
      * Sets the value of password for the default user.
      *
-     * @param userPassword
-     *            Value to assign to password.
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
+     * @param userPassword Value to assign to password.
+     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
      */
     public void setPassword(final String userPassword) {
         assertInitializationAllowed();
@@ -668,10 +650,8 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     /**
      * Whether to toggle the pooling of <code>PreparedStatement</code>s
      *
-     * @param poolPreparedStatements
-     *            true to pool statements.
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
+     * @param poolPreparedStatements true to pool statements.
+     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
      */
     public void setPoolPreparedStatements(final boolean poolPreparedStatements) {
         assertInitializationAllowed();
@@ -682,12 +662,10 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
      * Sets the number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no
      * idle object evictor thread will be run.
      *
-     * @param timeBetweenEvictionRunsMillis
-     *            The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive,
-     *            no idle object evictor thread will be run.
+     * @param timeBetweenEvictionRunsMillis The number of milliseconds to sleep between runs of the idle object evictor
+     *        thread. When non-positive, no idle object evictor thread will be run.
      * @see #getTimeBetweenEvictionRunsMillis()
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
+     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
      */
     public void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
         assertInitializationAllowed();
@@ -697,10 +675,8 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     /**
      * Sets the value of URL string used to locate the database for this datasource.
      *
-     * @param v
-     *            Value to assign to url.
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
+     * @param v Value to assign to url.
+     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
      */
     public void setUrl(final String v) {
         assertInitializationAllowed();
@@ -710,10 +686,8 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     /**
      * Sets the value of default user (login or user name).
      *
-     * @param v
-     *            Value to assign to user.
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
+     * @param v Value to assign to user.
+     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
      */
     public void setUser(final String v) {
         assertInitializationAllowed();
@@ -732,7 +706,8 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
         builder.append("[description=");
         builder.append(description);
         builder.append(", url=");
-        // TODO What if the connection string contains a 'user' or 'password' query parameter but that connection string is not in a legal URL format?
+        // TODO What if the connection string contains a 'user' or 'password' query parameter but that connection string
+        // is not in a legal URL format?
         builder.append(url);
         builder.append(", driver=");
         builder.append(driver);
@@ -753,24 +728,13 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
         builder.append(", getConnectionCalled=");
         builder.append(getConnectionCalled);
         builder.append(", connectionProperties=");
-        Properties tmpProps = connectionProperties;
-        tmpProps = mask(tmpProps, "user");
-        tmpProps = mask(tmpProps, "password");
-        builder.append(tmpProps);
+        builder.append(Utils.cloneWithoutCredentials(connectionProperties));
         builder.append(", accessToUnderlyingConnectionAllowed=");
         builder.append(accessToUnderlyingConnectionAllowed);
         builder.append("]");
         return builder.toString();
     }
 
-    private Properties mask(Properties properties, final String maskValueAtKey) {
-        if (connectionProperties != null && connectionProperties.contains(maskValueAtKey)) {
-            properties = (Properties) connectionProperties.clone();
-            properties.put(maskValueAtKey, "[" + maskValueAtKey + "]");
-        }
-        return properties;
-    }
-
     private void update(final Properties properties, final String key, final String value) {
         if (properties != null && key != null) {
             if (value == null) {
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java
index 0bce400..083f3ba 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java
@@ -95,7 +95,7 @@ public class PStmtKeyCPDS extends PStmtKey {
      *            An array of column indexes indicating the columns that should be returned from the inserted row or
      *            rows.
      */
-    public PStmtKeyCPDS(final String sql, final int columnIndexes[]) {
+    public PStmtKeyCPDS(final String sql, final int[] columnIndexes) {
         super(sql, null, columnIndexes);
     }
 
@@ -107,7 +107,7 @@ public class PStmtKeyCPDS extends PStmtKey {
      * @param columnNames
      *            An array of column names indicating the columns that should be returned from the inserted row or rows.
      */
-    public PStmtKeyCPDS(final String sql, final String columnNames[]) {
+    public PStmtKeyCPDS(final String sql, final String[] columnNames) {
         super(sql, null, columnNames);
     }
 }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java
index 147ee26..c2cf544 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java
@@ -35,6 +35,7 @@ import org.apache.tomcat.dbcp.dbcp2.PStmtKey;
 import org.apache.tomcat.dbcp.dbcp2.PoolableCallableStatement;
 import org.apache.tomcat.dbcp.dbcp2.PoolablePreparedStatement;
 import org.apache.tomcat.dbcp.dbcp2.PoolingConnection.StatementType;
+import org.apache.tomcat.dbcp.pool2.DestroyMode;
 import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
 import org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory;
 import org.apache.tomcat.dbcp.pool2.PooledObject;
@@ -108,10 +109,7 @@ class PooledConnectionImpl
     /**
      * My {@link KeyedPooledObjectFactory} method for activating {@link PreparedStatement}s.
      *
-     * @param key
-     *            Ignored.
-     * @param pooledObject
-     *            Ignored.
+     * @param pooledObject Activates the underlying object.
      */
     @Override
     public void activateObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject)
@@ -214,7 +212,7 @@ class PooledConnectionImpl
      *            rows.
      * @return a key to uniquely identify a prepared statement.
      */
-    protected PStmtKey createKey(final String sql, final int columnIndexes[]) {
+    protected PStmtKey createKey(final String sql, final int[] columnIndexes) {
         return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), columnIndexes);
     }
 
@@ -327,7 +325,7 @@ class PooledConnectionImpl
      *            An array of column names indicating the columns that should be returned from the inserted row or rows.
      * @return a key to uniquely identify a prepared statement.
      */
-    protected PStmtKey createKey(final String sql, final String columnNames[]) {
+    protected PStmtKey createKey(final String sql, final String[] columnNames) {
         return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), columnNames);
     }
 
@@ -345,6 +343,12 @@ class PooledConnectionImpl
         pooledObject.getObject().getInnermostDelegate().close();
     }
 
+    @Override
+    public void destroyObject(PStmtKey key, PooledObject<DelegatingPreparedStatement> p,
+            DestroyMode mode) throws Exception {
+        destroyObject(key, p);
+    }
+
     /**
      * Closes the physical connection and checks that the logical connection was closed as well.
      */
@@ -572,9 +576,10 @@ class PooledConnectionImpl
     /**
      * Creates or obtains a {@link PreparedStatement} from my pool.
      *
-     * @param sql
-     *            the SQL statement.
+     * @param sql the SQL statement.
      * @return a {@link PoolablePreparedStatement}
+     * @throws SQLException Thrown if a database access error occurs, this method is called on a closed connection, or
+     *         the borrow failed.
      */
     PreparedStatement prepareStatement(final String sql) throws SQLException {
         if (pStmtPool == null) {
@@ -598,6 +603,8 @@ class PooledConnectionImpl
      *            a flag indicating whether auto-generated keys should be returned; one of
      *            <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>.
      * @return a {@link PoolablePreparedStatement}
+     * @throws SQLException Thrown if a database access error occurs, this method is called on a closed connection, or
+     *         the borrow failed.
      * @see Connection#prepareStatement(String, int)
      */
     PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException {
@@ -613,7 +620,7 @@ class PooledConnectionImpl
         }
     }
 
-    PreparedStatement prepareStatement(final String sql, final int columnIndexes[]) throws SQLException {
+    PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException {
         if (pStmtPool == null) {
             return connection.prepareStatement(sql, columnIndexes);
         }
@@ -640,6 +647,8 @@ class PooledConnectionImpl
      *            <code>ResultSet.CONCUR_UPDATABLE</code>.
      *
      * @return a {@link PoolablePreparedStatement}.
+     * @throws SQLException Thrown if a database access error occurs, this method is called on a closed connection, or
+     *         the borrow failed.
      * @see Connection#prepareStatement(String, int, int)
      */
     PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency)
@@ -670,7 +679,7 @@ class PooledConnectionImpl
         }
     }
 
-    PreparedStatement prepareStatement(final String sql, final String columnNames[]) throws SQLException {
+    PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException {
         if (pStmtPool == null) {
             return connection.prepareStatement(sql, columnNames);
         }
@@ -726,4 +735,30 @@ class PooledConnectionImpl
     public boolean validateObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject) {
         return true;
     }
+
+    /**
+     * @since 2.6.0
+     */
+    @Override
+    public synchronized String toString() {
+        final StringBuilder builder = new StringBuilder(super.toString());
+        builder.append("[connection=");
+        builder.append(connection);
+        builder.append(", delegatingConnection=");
+        builder.append(delegatingConnection);
+        builder.append(", logicalConnection=");
+        builder.append(logicalConnection);
+        builder.append(", eventListeners=");
+        builder.append(eventListeners);
+        builder.append(", statementEventListeners=");
+        builder.append(statementEventListeners);
+        builder.append(", closed=");
+        builder.append(closed);
+        builder.append(", pStmtPool=");
+        builder.append(pStmtPool);
+        builder.append(", accessToUnderlyingConnectionAllowed=");
+        builder.append(accessToUnderlyingConnectionAllowed);
+        builder.append("]");
+        return builder.toString();
+    }
 }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java
index 93363a4..6c91099 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java
@@ -31,6 +31,7 @@ import javax.sql.ConnectionPoolDataSource;
 import javax.sql.PooledConnection;
 
 import org.apache.tomcat.dbcp.dbcp2.Utils;
+import org.apache.tomcat.dbcp.pool2.DestroyMode;
 import org.apache.tomcat.dbcp.pool2.ObjectPool;
 import org.apache.tomcat.dbcp.pool2.PooledObject;
 import org.apache.tomcat.dbcp.pool2.PooledObjectFactory;
@@ -58,8 +59,7 @@ class CPDSConnectionFactory
     /**
      * Map of PooledConnections for which close events are ignored. Connections are muted when they are being validated.
      */
-    private final Set<PooledConnection> validatingSet = Collections
-            .newSetFromMap(new ConcurrentHashMap<PooledConnection, Boolean>());
+    private final Set<PooledConnection> validatingSet = Collections.newSetFromMap(new ConcurrentHashMap<PooledConnection,Boolean>());
 
     /**
      * Map of PooledConnectionAndInfo instances
@@ -150,7 +150,7 @@ class CPDSConnectionFactory
 
     @Override
     public synchronized PooledObject<PooledConnectionAndInfo> makeObject() {
-        PooledConnectionAndInfo pci;
+        final PooledConnectionAndInfo pci;
         try {
             PooledConnection pc = null;
             if (userName == null) {
@@ -182,6 +182,13 @@ class CPDSConnectionFactory
         doDestroyObject(p.getObject());
     }
 
+
+    @Override
+    public void destroyObject(PooledObject<PooledConnectionAndInfo> p, DestroyMode mode)
+            throws Exception {
+        destroyObject(p);
+    }
+
     private void doDestroyObject(final PooledConnectionAndInfo pci) throws Exception {
         final PooledConnection pc = pci.getPooledConnection();
         pc.removeConnectionEventListener(this);
@@ -226,11 +233,7 @@ class CPDSConnectionFactory
                 conn = pconn.getConnection();
                 stmt = conn.createStatement();
                 rset = stmt.executeQuery(validationQuery);
-                if (rset.next()) {
-                    valid = true;
-                } else {
-                    valid = false;
-                }
+                valid = rset.next();
                 if (rollbackAfterValidation) {
                     conn.rollback();
                 }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java
index e9457e6..a556f56 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java
@@ -24,7 +24,6 @@ import java.nio.charset.StandardCharsets;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
-import java.util.NoSuchElementException;
 import java.util.Properties;
 import java.util.logging.Logger;
 
@@ -913,9 +912,6 @@ public abstract class InstanceKeyDataSource implements DataSource, Referenceable
         PooledConnectionAndInfo info = null;
         try {
             info = getPooledConnectionAndInfo(userName, userPassword);
-        } catch (final NoSuchElementException e) {
-            closeDueToException(info);
-            throw new SQLException("Cannot borrow connection from pool", e);
         } catch (final RuntimeException | SQLException e) {
             closeDueToException(info);
             throw e;
@@ -950,9 +946,6 @@ public abstract class InstanceKeyDataSource implements DataSource, Referenceable
             for (int i = 0; i < 10; i++) { // Bound the number of retries - only needed if bad instances return
                 try {
                     info = getPooledConnectionAndInfo(userName, userPassword);
-                } catch (final NoSuchElementException e) {
-                    closeDueToException(info);
-                    throw new SQLException("Cannot borrow connection from pool", e);
                 } catch (final RuntimeException | SQLException e) {
                     closeDueToException(info);
                     throw e;
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java
index 0e2c1eb..defa46a 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java
@@ -46,7 +46,7 @@ abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
 
     static synchronized String registerNewInstance(final InstanceKeyDataSource ds) {
         int max = 0;
-        for (String s : instanceMap.keySet()) {
+        for (final String s : instanceMap.keySet()) {
             if (s != null) {
                 try {
                     max = Math.max(max, Integer.parseInt(s));
@@ -81,7 +81,7 @@ abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
     public static void closeAll() throws Exception {
         // Get iterator to loop over all instances of this data source.
         final List<Throwable> exceptionList = new ArrayList<>(instanceMap.size());
-        for (Entry<String, InstanceKeyDataSource> next : instanceMap.entrySet()) {
+        for (final Entry<String, InstanceKeyDataSource> next : instanceMap.entrySet()) {
             // Bullet-proof to avoid anything else but problems from InstanceKeyDataSource#close().
             if (next != null) {
                 final InstanceKeyDataSource value = next.getValue();
@@ -166,7 +166,7 @@ abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
         // Pool properties
         refAddr = ref.get("blockWhenExhausted");
         if (refAddr != null && refAddr.getContent() != null) {
-            ikds.setDefaultBlockWhenExhausted(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
+            ikds.setDefaultBlockWhenExhausted(Boolean.parseBoolean(refAddr.getContent().toString()));
         }
 
         refAddr = ref.get("evictionPolicyClassName");
@@ -177,7 +177,7 @@ abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
         // Pool properties
         refAddr = ref.get("lifo");
         if (refAddr != null && refAddr.getContent() != null) {
-            ikds.setDefaultLifo(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
+            ikds.setDefaultLifo(Boolean.parseBoolean(refAddr.getContent().toString()));
         }
 
         refAddr = ref.get("maxIdlePerKey");
@@ -217,22 +217,22 @@ abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
 
         refAddr = ref.get("testOnCreate");
         if (refAddr != null && refAddr.getContent() != null) {
-            ikds.setDefaultTestOnCreate(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
+            ikds.setDefaultTestOnCreate(Boolean.parseBoolean(refAddr.getContent().toString()));
         }
 
         refAddr = ref.get("testOnBorrow");
         if (refAddr != null && refAddr.getContent() != null) {
-            ikds.setDefaultTestOnBorrow(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
+            ikds.setDefaultTestOnBorrow(Boolean.parseBoolean(refAddr.getContent().toString()));
         }
 
         refAddr = ref.get("testOnReturn");
         if (refAddr != null && refAddr.getContent() != null) {
-            ikds.setDefaultTestOnReturn(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
+            ikds.setDefaultTestOnReturn(Boolean.parseBoolean(refAddr.getContent().toString()));
         }
 
         refAddr = ref.get("testWhileIdle");
         if (refAddr != null && refAddr.getContent() != null) {
-            ikds.setDefaultTestWhileIdle(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
+            ikds.setDefaultTestWhileIdle(Boolean.parseBoolean(refAddr.getContent().toString()));
         }
 
         refAddr = ref.get("timeBetweenEvictionRunsMillis");
@@ -254,7 +254,7 @@ abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
 
         refAddr = ref.get("rollbackAfterValidation");
         if (refAddr != null && refAddr.getContent() != null) {
-            ikds.setRollbackAfterValidation(Boolean.valueOf(refAddr.getContent().toString()).booleanValue());
+            ikds.setRollbackAfterValidation(Boolean.parseBoolean(refAddr.getContent().toString()));
         }
 
         refAddr = ref.get("maxConnLifetimeMillis");
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java
index 3f15b79..ada37fe 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java
@@ -32,6 +32,7 @@ import javax.sql.ConnectionPoolDataSource;
 import javax.sql.PooledConnection;
 
 import org.apache.tomcat.dbcp.dbcp2.Utils;
+import org.apache.tomcat.dbcp.pool2.DestroyMode;
 import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
 import org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory;
 import org.apache.tomcat.dbcp.pool2.PooledObject;
@@ -59,8 +60,7 @@ class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey
     /**
      * Map of PooledConnections for which close events are ignored. Connections are muted when they are being validated.
      */
-    private final Set<PooledConnection> validatingSet = Collections
-            .newSetFromMap(new ConcurrentHashMap<PooledConnection, Boolean>());
+    private final Set<PooledConnection> validatingSet = Collections.newSetFromMap(new ConcurrentHashMap<PooledConnection,Boolean>());
 
     /**
      * Map of PooledConnectionAndInfo instances
@@ -113,8 +113,6 @@ class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey
      */
     @Override
     public synchronized PooledObject<PooledConnectionAndInfo> makeObject(final UserPassKey upkey) throws Exception {
-        PooledConnectionAndInfo pci = null;
-
         PooledConnection pc = null;
         final String userName = upkey.getUsername();
         final String password = upkey.getPassword();
@@ -131,7 +129,7 @@ class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey
         // 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, upkey.getPasswordCharArray());
+        final PooledConnectionAndInfo pci = new PooledConnectionAndInfo(pc, userName, upkey.getPasswordCharArray());
         pcMap.put(pc, pci);
 
         return new DefaultPooledObject<>(pci);
@@ -148,6 +146,12 @@ class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey
         pc.close();
     }
 
+    @Override
+    public void destroyObject(UserPassKey key, PooledObject<PooledConnectionAndInfo> p,
+            DestroyMode mode) throws Exception {
+        destroyObject(key, p);
+    }
+
     /**
      * Validates a pooled connection.
      *
@@ -194,11 +198,7 @@ class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey
                 conn = pconn.getConnection();
                 stmt = conn.createStatement();
                 rset = stmt.executeQuery(validationQuery);
-                if (rset.next()) {
-                    valid = true;
-                } else {
-                    valid = false;
-                }
+                valid = rset.next();
                 if (rollbackAfterValidation) {
                     conn.rollback();
                 }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java
index f38e04f..17f8551 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java
@@ -18,6 +18,7 @@
 package org.apache.tomcat.dbcp.dbcp2.datasources;
 
 import java.io.Serializable;
+import java.util.Objects;
 
 /**
  * @since 2.0
@@ -45,37 +46,22 @@ class PoolKey implements Serializable {
             return false;
         }
         final PoolKey other = (PoolKey) obj;
-        if (dataSourceName == null) {
-            if (other.dataSourceName != null) {
-                return false;
-            }
-        } else if (!dataSourceName.equals(other.dataSourceName)) {
+        if (!Objects.equals(dataSourceName, other.dataSourceName)) {
             return false;
         }
-        if (userName == null) {
-            if (other.userName != null) {
-                return false;
-            }
-        } else if (!userName.equals(other.userName)) {
-            return false;
-        }
-        return true;
+        return Objects.equals(userName, other.userName);
     }
 
     @Override
     public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((dataSourceName == null) ? 0 : dataSourceName.hashCode());
-        result = prime * result + ((userName == null) ? 0 : userName.hashCode());
-        return result;
+        return Objects.hash(dataSourceName, userName);
     }
 
     @Override
     public String toString() {
-        final StringBuffer sb = new StringBuffer(50);
+        final StringBuilder sb = new StringBuilder(50);
         sb.append("PoolKey(");
-        sb.append(userName).append(", ").append(dataSourceName);
+        sb.append("UserName").append(", ").append(dataSourceName);
         sb.append(')');
         return sb.toString();
     }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java
index e357028..b589809 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java
@@ -18,6 +18,7 @@
 package org.apache.tomcat.dbcp.dbcp2.datasources;
 
 import java.io.Serializable;
+import java.util.Objects;
 
 import org.apache.tomcat.dbcp.dbcp2.Utils;
 
@@ -75,14 +76,7 @@ class UserPassKey implements Serializable {
             return false;
         }
         final UserPassKey other = (UserPassKey) obj;
-        if (userName == null) {
-            if (other.userName != null) {
-                return false;
-            }
-        } else if (!userName.equals(other.userName)) {
-            return false;
-        }
-        return true;
+        return Objects.equals(userName, other.userName);
     }
 
     /**
@@ -117,18 +111,7 @@ class UserPassKey implements Serializable {
      */
     @Override
     public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((userName == null) ? 0 : userName.hashCode());
-        return result;
+        return Objects.hash(userName);
     }
 
-    @Override
-    public String toString() {
-        final StringBuffer sb = new StringBuffer(super.toString());
-        sb.append("[");
-        sb.append(userName);
-        sb.append(']');
-        return sb.toString();
-    }
 }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java
index 531db68..5b24360 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java
@@ -82,7 +82,7 @@
  * <strong>java:comp/env</strong> namespace.  So the JNDI path given for
  * the dataSourceName parameter is valid for a
  * <code>ConnectionPoolDataSource</code> that is deployed as given in the
- * <a href="../cpdsadapter/package.html">cpdsadapter example</a>
+ * <a href="../cpdsadapter/package-summary.html">cpdsadapter example</a>
  * </p>
  *
  * <p>
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 7a0979f..185c386 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -215,6 +215,10 @@
         Update the internal fork of Apache Commons Pool to 2.9.1-SNAPSHOT
         (2021-01-15). (markt)
       </add>
+      <add>
+        Update the internal fork of Apache Commons DBCP to 2.9.0-SNAPSHOT
+        (2021-01-15). (markt)
+      </add>
     </changelog>
   </subsection>
 </section>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org