[tomcat] branch 9.0.x updated: Update Commons DBCP

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[tomcat] branch 9.0.x updated: Update Commons DBCP

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

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


The following commit(s) were added to refs/heads/9.0.x by this push:
     new c615856  Update Commons DBCP
c615856 is described below

commit c61585616d9f7bcf68c93ad3d2eefdbf9ebb53a4
Author: Mark Thomas <[hidden email]>
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   |  13 ++-
 .../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 |   6 ++
 .../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      |  45 +++++---
 .../dbcp/dbcp2/PoolablePreparedStatement.java      |   8 +-
 .../tomcat/dbcp/dbcp2/PoolingConnection.java       |  10 +-
 .../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    |  22 ++--
 .../dbcp2/datasources/CPDSConnectionFactory.java   |  11 +-
 .../dbcp2/datasources/InstanceKeyDataSource.java   |   7 --
 .../datasources/InstanceKeyDataSourceFactory.java  |  18 ++--
 .../datasources/KeyedCPDSConnectionFactory.java    |  13 +--
 .../tomcat/dbcp/dbcp2/datasources/PoolKey.java     |  26 ++---
 .../tomcat/dbcp/dbcp2/datasources/UserPassKey.java |  23 +---
 .../dbcp/dbcp2/datasources/package-info.java       |   2 +-
 .../dbcp/dbcp2/managed/BasicManagedDataSource.java |  32 +++---
 .../managed/DataSourceXAConnectionFactory.java     |  34 +++---
 .../dbcp2/managed/LocalXAConnectionFactory.java    |  35 +++---
 .../dbcp/dbcp2/managed/ManagedConnection.java      |  35 +++---
 .../dbcp/dbcp2/managed/ManagedDataSource.java      |  32 +++---
 .../managed/PoolableManagedConnectionFactory.java  |   2 +-
 .../dbcp/dbcp2/managed/TransactionContext.java     |  34 +++---
 .../dbcp2/managed/TransactionContextListener.java  |  32 +++---
 .../dbcp/dbcp2/managed/TransactionRegistry.java    |  34 +++---
 .../dbcp/dbcp2/managed/XAConnectionFactory.java    |  32 +++---
 webapps/docs/changelog.xml                         |   4 +
 45 files changed, 424 insertions(+), 512 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 5ac1372..08762f0 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java
@@ -528,7 +528,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);
@@ -605,7 +605,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);
@@ -686,7 +686,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      */
     @Override
     public boolean getAbandonedUsageTracking() {
-        return abandonedConfig == null ? false : abandonedConfig.getUseUsageTracking();
+        return abandonedConfig != null && abandonedConfig.getUseUsageTracking();
     }
 
     /**
@@ -779,8 +779,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() {
@@ -872,8 +871,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);
     }
 
     /**
@@ -996,7 +994,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      */
     @Override
     public boolean getLogAbandoned() {
-        return abandonedConfig == null ? false : abandonedConfig.getLogAbandoned();
+        return abandonedConfig != null && abandonedConfig.getLogAbandoned();
     }
 
     /**
@@ -1211,7 +1209,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      */
     @Override
     public boolean getRemoveAbandonedOnBorrow() {
-        return abandonedConfig == null ? false : abandonedConfig.getRemoveAbandonedOnBorrow();
+        return abandonedConfig != null && abandonedConfig.getRemoveAbandonedOnBorrow();
     }
 
     /**
@@ -1232,7 +1230,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
      */
     @Override
     public boolean getRemoveAbandonedOnMaintenance() {
-        return abandonedConfig == null ? false : abandonedConfig.getRemoveAbandonedOnMaintenance();
+        return abandonedConfig != null && abandonedConfig.getRemoveAbandonedOnMaintenance();
     }
 
     /**
@@ -1460,8 +1458,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();
     }
 
     /**
@@ -1509,7 +1507,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 5dc6b7a..5a637da 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java
@@ -333,15 +333,20 @@ public interface BasicDataSourceMXBean {
      *
      * @throws SQLException if an error occurs initializing the datasource
      *
-     * @since 2.8
+     * @since 2.8.0
      */
-    default void start() throws SQLException {}
+    default void start() throws SQLException {
+        // do nothing
+    }
 
     /**
      * See {@link BasicDataSource#restart()}
+     *
      * @throws SQLException if an error occurs initializing the datasource
      *
-     * @since 2.8
+     * @since 2.8.0
      */
-    default void restart() throws SQLException {}
+    default void restart() throws SQLException {
+        // do nothing by default?
+    }
 }
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 b75b09c..7b45869 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 ad1021e..e29071a 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java
@@ -607,7 +607,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;
@@ -1046,9 +1046,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 aa30871..4c150b4 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 {
@@ -358,7 +357,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 {
@@ -370,7 +369,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 {
@@ -466,7 +465,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 efd9dc5..15b943d 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java
@@ -43,6 +43,12 @@ 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
  */
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..6988871 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,18 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
     }
 
     /**
+     * @since 2.9.0
+     */
+    @Override
+    public void destroyObject(final PooledObject<PoolableConnection> p, final DestroyMode mode) throws Exception {
+        if (mode != null && mode.equals(DestroyMode.ABANDONED)) {
+            p.getObject().getInnermostDelegate().abort(Runnable::run);
+        } else {
+            p.getObject().reallyClose();
+        }
+    }
+
+    /**
      * @return The cache state.
      * @since Made public in 2.6.0.
      */
@@ -269,7 +282,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 +290,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 +304,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
     public String getValidationQuery() {
         return validationQuery;
     }
+
     /**
      * @return Validation query timeout in seconds.
      * @since 2.6.0
@@ -300,6 +312,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 +397,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 +412,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 +466,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 +486,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 +509,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 +624,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 8615074..9453f15 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java
@@ -129,7 +129,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 +158,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 +278,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);
     }
 
@@ -517,7 +517,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 +573,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 d15fb40..c44f908 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java
@@ -108,10 +108,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 +211,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 +324,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);
     }
 
@@ -572,9 +569,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 +596,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 +613,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 +640,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 +672,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);
         }
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java
index 93363a4..311bad9 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java
@@ -58,8 +58,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<>());
 
     /**
      * Map of PooledConnectionAndInfo instances
@@ -150,7 +149,7 @@ class CPDSConnectionFactory
 
     @Override
     public synchronized PooledObject<PooledConnectionAndInfo> makeObject() {
-        PooledConnectionAndInfo pci;
+        final PooledConnectionAndInfo pci;
         try {
             PooledConnection pc = null;
             if (userName == null) {
@@ -226,11 +225,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..037e45c 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java
@@ -59,8 +59,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<>());
 
     /**
      * Map of PooledConnectionAndInfo instances
@@ -113,8 +112,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 +128,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);
@@ -194,11 +191,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/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.java
index 9129598..5d082e3 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.java
@@ -1,19 +1,19 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+/*
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
  */
 package org.apache.tomcat.dbcp.dbcp2.managed;
 
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java
index 71a3f37..52affd1 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java
@@ -1,19 +1,19 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+/*
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
  */
 package org.apache.tomcat.dbcp.dbcp2.managed;
 
@@ -140,7 +140,7 @@ public class DataSourceXAConnectionFactory implements XAConnectionFactory {
     @Override
     public Connection createConnection() throws SQLException {
         // create a new XAConnection
-        XAConnection xaConnection;
+        final XAConnection xaConnection;
         if (userName == null) {
             xaConnection = xaDataSource.getXAConnection();
         } else {
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java
index a50b7ed..aa4ed1e 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java
@@ -1,19 +1,19 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+/*
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
  */
 package org.apache.tomcat.dbcp.dbcp2.managed;
 
@@ -51,6 +51,7 @@ public class LocalXAConnectionFactory implements XAConnectionFactory {
      * @since 2.0
      */
     protected static class LocalXAResource implements XAResource {
+        private static final Xid[] EMPTY_XID_ARRAY = new Xid[0];
         private final Connection connection;
         private Xid currentXid; // @GuardedBy("this")
         private boolean originalAutoCommit; // @GuardedBy("this")
@@ -208,7 +209,7 @@ public class LocalXAConnectionFactory implements XAConnectionFactory {
          */
         @Override
         public Xid[] recover(final int flag) {
-            return new Xid[0];
+            return EMPTY_XID_ARRAY;
         }
 
         /**
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java
index a2e7373..c91faef 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java
@@ -1,19 +1,19 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+/*
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
  */
 package org.apache.tomcat.dbcp.dbcp2.managed;
 
@@ -216,6 +216,9 @@ public class ManagedConnection<C extends Connection> extends DelegatingConnectio
             isSharedConnection = false;
         }
 
+        // autoCommit may have been changed directly on the underlying connection
+        clearCachedState();
+
         // If this connection was closed during the transaction and there is
         // still a delegate present close it
         final Connection delegate = getDelegateInternal();
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java
index 74ae7cf..2457d8d 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java
@@ -1,19 +1,19 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+/*
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
  */
 package org.apache.tomcat.dbcp.dbcp2.managed;
 
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java
index e3fbd62..e130bbb 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java
@@ -90,7 +90,7 @@ public class PoolableManagedConnectionFactory extends PoolableConnectionFactory
             if (dataSourceJmxName != null) {
                 final StringBuilder base = new StringBuilder(dataSourceJmxName.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 {
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java
index 6266262..d314e2d 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java
@@ -1,19 +1,19 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+/*
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
  */
 package org.apache.tomcat.dbcp.dbcp2.managed;
 
@@ -134,7 +134,7 @@ public class TransactionContext {
             if (!isActive()) {
                 final Transaction transaction = this.transactionRef.get();
                 listener.afterCompletion(TransactionContext.this,
-                        transaction == null ? false : transaction.getStatus() == Status.STATUS_COMMITTED);
+                        transaction != null && transaction.getStatus() == Status.STATUS_COMMITTED);
                 return;
             }
             final Synchronization s = new Synchronization() {
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContextListener.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContextListener.java
index 95eae21..b8320c0 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContextListener.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContextListener.java
@@ -1,19 +1,19 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+/*
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
  */
 package org.apache.tomcat.dbcp.dbcp2.managed;
 
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java
index 6a01610..6d5d04b 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java
@@ -1,19 +1,19 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+/*
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
  */
 package org.apache.tomcat.dbcp.dbcp2.managed;
 
@@ -148,7 +148,7 @@ public class TransactionRegistry {
     }
 
     private Connection getConnectionKey(final Connection connection) {
-        Connection result;
+        final Connection result;
         if (connection instanceof DelegatingConnection) {
             result = ((DelegatingConnection<?>) connection).getInnermostDelegateInternal();
         } else {
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/XAConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/XAConnectionFactory.java
index b7dce97..a3d9906 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/XAConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/XAConnectionFactory.java
@@ -1,19 +1,19 @@
-/**
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+/*
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
  */
 package org.apache.tomcat.dbcp.dbcp2.managed;
 
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 89e6c40..f64bbac 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -218,6 +218,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: [hidden email]
For additional commands, e-mail: [hidden email]