You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2023/01/03 14:44:55 UTC
[tomcat] branch main updated: Update package renamed fork of Commons DBCP
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new aa4f7669bc Update package renamed fork of Commons DBCP
aa4f7669bc is described below
commit aa4f7669bc33bde65f13457599a0dd4fb3747d44
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Jan 3 14:44:40 2023 +0000
Update package renamed fork of Commons DBCP
---
MERGE.txt | 4 +-
.../apache/tomcat/dbcp/dbcp2/AbandonedTrace.java | 25 +-
.../apache/tomcat/dbcp/dbcp2/BasicDataSource.java | 355 ++++------
.../tomcat/dbcp/dbcp2/BasicDataSourceFactory.java | 78 ++-
.../dbcp/dbcp2/ConnectionFactoryFactory.java | 8 +-
.../dbcp/dbcp2/DataSourceConnectionFactory.java | 2 +-
.../tomcat/dbcp/dbcp2/DelegatingConnection.java | 43 +-
.../dbcp/dbcp2/DelegatingPreparedStatement.java | 23 +
.../tomcat/dbcp/dbcp2/DelegatingStatement.java | 35 +-
.../apache/tomcat/dbcp/dbcp2/DriverFactory.java | 2 +-
.../dbcp/dbcp2/DriverManagerConnectionFactory.java | 8 +-
.../org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java | 4 +-
.../dbcp/dbcp2/LifetimeExceededException.java | 15 +-
.../tomcat/dbcp/dbcp2/LocalStrings.properties | 2 +-
.../tomcat/dbcp/dbcp2/ObjectNameWrapper.java | 2 +-
java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java | 758 +++++++--------------
.../dbcp/dbcp2/PoolableCallableStatement.java | 33 +-
.../tomcat/dbcp/dbcp2/PoolableConnection.java | 14 +-
.../dbcp/dbcp2/PoolableConnectionFactory.java | 58 +-
.../dbcp/dbcp2/PoolableConnectionMXBean.java | 5 +-
.../dbcp/dbcp2/PoolablePreparedStatement.java | 33 +-
.../tomcat/dbcp/dbcp2/PoolingConnection.java | 66 +-
.../apache/tomcat/dbcp/dbcp2/PoolingDriver.java | 13 +-
java/org/apache/tomcat/dbcp/dbcp2/Utils.java | 61 +-
.../dbcp/dbcp2/cpdsadapter/ConnectionImpl.java | 60 +-
.../dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java | 63 +-
.../dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java | 22 +-
.../dbcp2/cpdsadapter/PooledConnectionImpl.java | 165 ++---
.../dbcp/dbcp2/cpdsadapter/package-info.java | 4 +-
.../dbcp2/datasources/CPDSConnectionFactory.java | 31 +-
.../tomcat/dbcp/dbcp2/datasources/CharArray.java | 14 +-
.../dbcp2/datasources/InstanceKeyDataSource.java | 39 +-
.../datasources/InstanceKeyDataSourceFactory.java | 26 +-
.../datasources/KeyedCPDSConnectionFactory.java | 26 +-
.../dbcp2/datasources/PerUserPoolDataSource.java | 294 +++-----
.../datasources/PerUserPoolDataSourceFactory.java | 2 +-
.../tomcat/dbcp/dbcp2/datasources/PoolKey.java | 2 +-
.../dbcp2/datasources/PooledConnectionManager.java | 20 +-
.../dbcp2/datasources/SharedPoolDataSource.java | 10 +-
.../tomcat/dbcp/dbcp2/datasources/UserPassKey.java | 2 +-
.../dbcp/dbcp2/datasources/package-info.java | 18 +-
.../managed/DataSourceXAConnectionFactory.java | 50 +-
.../dbcp2/managed/LocalXAConnectionFactory.java | 34 +-
.../dbcp/dbcp2/managed/ManagedConnection.java | 8 +-
.../dbcp/dbcp2/managed/ManagedDataSource.java | 2 +-
.../managed/PoolableManagedConnectionFactory.java | 5 +-
.../SynchronizationAdapter.java} | 31 +-
.../dbcp/dbcp2/managed/TransactionContext.java | 18 +-
.../dbcp/dbcp2/managed/TransactionRegistry.java | 13 +-
webapps/docs/changelog.xml | 4 +
50 files changed, 1044 insertions(+), 1566 deletions(-)
diff --git a/MERGE.txt b/MERGE.txt
index 5673ec8d95..63075f061d 100644
--- a/MERGE.txt
+++ b/MERGE.txt
@@ -54,7 +54,7 @@ Unused code is removed
Sub-tree:
src/main/java/org/apache/commons/fileupload2
The SHA1 ID / tag for the most recent commit to be merged to Tomcat is:
-34eb241c051b02eca3b0b1b04f67b3b4e6c3a24d (2023-02-03)
+34eb241c051b02eca3b0b1b04f67b3b4e6c3a24d (2023-01-03)
Note: Tomcat's copy of fileupload also includes classes copied manually from
Commons IO.
@@ -77,4 +77,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:
-rel/commons-dbcp-2.9.0 (2021-08-03)
+f13128604536e78bb1b45b44f74128e93cfbb7cc (2023-01-03)
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java b/java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java
index c10758017e..a094f16d31 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java
@@ -17,11 +17,13 @@
package org.apache.tomcat.dbcp.dbcp2;
import java.lang.ref.WeakReference;
+import java.sql.SQLException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.function.Consumer;
import org.apache.tomcat.dbcp.pool2.TrackedUse;
@@ -33,7 +35,7 @@ import org.apache.tomcat.dbcp.pool2.TrackedUse;
*
* @since 2.0
*/
-public class AbandonedTrace implements TrackedUse {
+public class AbandonedTrace implements TrackedUse, AutoCloseable {
/** A list of objects created by children of this object. */
private final List<WeakReference<AbandonedTrace>> traceList = new ArrayList<>();
@@ -80,6 +82,27 @@ public class AbandonedTrace implements TrackedUse {
}
}
+ /**
+ * Subclasses can implement this nop.
+ *
+ * @throws SQLException Ignored here, for subclasses.
+ * @since 2.10.0
+ */
+ @Override
+ public void close() throws SQLException {
+ // nop
+ }
+
+ /**
+ * Closes this resource and if an exception is caught, then calls {@code exceptionHandler}.
+ *
+ * @param exceptionHandler Consumes exception thrown closing this resource.
+ * @since 2.10.0
+ */
+ protected void close(final Consumer<Exception> exceptionHandler) {
+ Utils.close(this, exceptionHandler);
+ }
+
/**
* Gets the last time this object was used in milliseconds.
*
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java
index f260a536c4..a9cf96761c 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java
@@ -28,15 +28,16 @@ import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.time.Duration;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
+import java.util.function.BiConsumer;
import java.util.logging.Logger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
@@ -56,7 +57,7 @@ import org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool;
import org.apache.tomcat.dbcp.pool2.impl.GenericObjectPoolConfig;
/**
- * Basic implementation of <code>javax.sql.DataSource</code> that is configured via JavaBeans properties.
+ * Basic implementation of {@code javax.sql.DataSource} that is configured via JavaBeans properties.
*
* <p>
* This is not the only way to combine the <em>commons-dbcp2</em> and <em>commons-pool2</em> packages, but provides a
@@ -102,9 +103,9 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
* Validates the given factory.
*
* @param connectionFactory the factory
- * @throws Exception Thrown by one of the factory methods while managing a temporary pooled object.
+ * @throws SQLException Thrown by one of the factory methods while managing a temporary pooled object.
*/
- protected static void validateConnectionFactory(final PoolableConnectionFactory connectionFactory) throws Exception {
+ protected static void validateConnectionFactory(final PoolableConnectionFactory connectionFactory) throws SQLException {
PoolableConnection conn = null;
PooledObject<PoolableConnection> p = null;
try {
@@ -212,7 +213,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
private Duration maxWaitDuration = BaseObjectPoolConfig.DEFAULT_MAX_WAIT;
/**
- * Prepared statement pooling for this pool. When this property is set to <code>true</code> both PreparedStatements
+ * Prepared statement pooling for this pool. When this property is set to {@code true} both PreparedStatements
* and CallableStatements are pooled.
*/
private boolean poolPreparedStatements;
@@ -228,7 +229,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
* <p>
* Note: As of version 1.3, CallableStatements (those produced by {@link Connection#prepareCall}) are pooled along
* with PreparedStatements (produced by {@link Connection#prepareStatement}) and
- * <code>maxOpenPreparedStatements</code> limits the total number of prepared or callable statements that may be in
+ * {@code maxOpenPreparedStatements} limits the total number of prepared or callable statements that may be in
* use at a given time.
* </p>
*/
@@ -290,9 +291,9 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
private volatile String password;
/**
- * The connection URL to be passed to our JDBC driver to establish a connection.
+ * The connection string to be passed to our JDBC driver to establish a connection.
*/
- private String url;
+ private String connectionString;
/**
* The connection user name to be passed to our JDBC driver to establish a connection.
@@ -336,6 +337,8 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
private String jmxName;
+ private boolean registerConnectionMBean = true;
+
private boolean autoCommitOnReturn = true;
private boolean rollbackOnReturn = true;
@@ -358,7 +361,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
/**
* The data source we will use to manage connections. This object should be acquired <strong>ONLY</strong> by calls
- * to the <code>createDataSource()</code> method.
+ * to the {@code createDataSource()} method.
*/
private volatile DataSource dataSource;
@@ -447,7 +450,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
* with the specified {@link ClassLoader}.</li>
* <li>If {code driverClassName} is specified and the previous attempt fails, the class is loaded using the
* context class loader of the current thread.</li>
- * <li>If a driver still isn't loaded one is loaded via the {@link DriverManager} using the specified {code url}.
+ * <li>If a driver still isn't loaded one is loaded via the {@link DriverManager} using the specified {code connectionString}.
* </ol>
* <p>
* This method exists so subclasses can replace the implementation class.
@@ -505,7 +508,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
* @return The current internal DataSource or a newly created instance if it has not yet been created.
* @throws SQLException if the object pool cannot be created.
*/
- protected DataSource createDataSource() throws SQLException {
+ protected synchronized DataSource createDataSource() throws SQLException {
if (closed) {
throw new SQLException("Data source is closed");
}
@@ -526,56 +529,28 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
final ConnectionFactory driverConnectionFactory = createConnectionFactory();
// Set up the poolable connection factory
- boolean success = false;
final PoolableConnectionFactory poolableConnectionFactory;
try {
poolableConnectionFactory = createPoolableConnectionFactory(driverConnectionFactory);
poolableConnectionFactory.setPoolStatements(poolPreparedStatements);
poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements);
- success = true;
- } catch (final SQLException | RuntimeException se) {
- throw se;
- } catch (final Exception ex) {
- throw new SQLException("Error creating connection factory", ex);
- }
-
- if (success) {
// create a pool for our connections
createConnectionPool(poolableConnectionFactory);
- }
-
- // Create the pooling data source to manage connections
- DataSource newDataSource;
- success = false;
- try {
- newDataSource = createDataSourceInstance();
+ final DataSource newDataSource = createDataSourceInstance();
newDataSource.setLogWriter(logWriter);
- success = true;
+ connectionPool.addObjects(initialSize);
+ // If timeBetweenEvictionRunsMillis > 0, start the pool's evictor
+ // task
+ startPoolMaintenance();
+ dataSource = newDataSource;
} catch (final SQLException | RuntimeException se) {
+ closeConnectionPool();
throw se;
} catch (final Exception ex) {
- throw new SQLException("Error creating datasource", ex);
- } finally {
- if (!success) {
- closeConnectionPool();
- }
- }
-
- // If initialSize > 0, preload the pool
- try {
- for (int i = 0; i < initialSize; i++) {
- connectionPool.addObject();
- }
- } catch (final Exception e) {
closeConnectionPool();
- throw new SQLException("Error preloading the connection pool", e);
+ throw new SQLException("Error creating connection factory", ex);
}
- // If timeBetweenEvictionRunsMillis > 0, start the pool's evictor
- // task
- startPoolMaintenance();
-
- dataSource = newDataSource;
return dataSource;
}
}
@@ -627,7 +602,11 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
throws SQLException {
PoolableConnectionFactory connectionFactory = null;
try {
- connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, ObjectNameWrapper.unwrap(registeredJmxObjectName));
+ if (registerConnectionMBean) {
+ connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, ObjectNameWrapper.unwrap(registeredJmxObjectName));
+ } else {
+ connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, null);
+ }
connectionFactory.setValidationQuery(validationQuery);
connectionFactory.setValidationQueryTimeout(validationQueryTimeoutDuration);
connectionFactory.setConnectionInitSql(connectionInitSqls);
@@ -680,7 +659,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
* connection pool record a stack trace every time a method is called on a pooled connection and retain the most
* recent stack trace to aid debugging of abandoned connections?
*
- * @return <code>true</code> if usage tracking is enabled
+ * @return {@code true} if usage tracking is enabled
*/
@Override
public boolean getAbandonedUsageTracking() {
@@ -690,7 +669,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
/**
* Gets the value of the flag that controls whether or not connections being returned to the pool will be checked
* and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
- * setting is {@code false} when the connection is returned. It is <code>true</code> by default.
+ * setting is {@code false} when the connection is returned. It is {@code true} by default.
*
* @return Whether or not connections being returned to the pool will be checked and configured with auto-commit.
*/
@@ -815,7 +794,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
/**
* Gets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
- * connection. <code>null</code> means that the driver default will be used.
+ * connection. {@code null} means that the driver default will be used.
*
* @return The default query timeout in seconds.
* @deprecated Use {@link #getDefaultQueryTimeoutDuration()}.
@@ -827,7 +806,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
/**
* Gets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
- * connection. <code>null</code> means that the driver default will be used.
+ * connection. {@code null} means that the driver default will be used.
*
* @return The default query timeout Duration.
* @since 2.10.0
@@ -904,7 +883,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
}
/**
- * Gets the class loader specified for loading the JDBC driver. Returns <code>null</code> if no class loader has
+ * Gets the class loader specified for loading the JDBC driver. Returns {@code null} if no class loader has
* been explicitly specified.
* <p>
* Note: This getter only returns the last value set by a call to {@link #setDriverClassLoader(ClassLoader)}. It
@@ -934,7 +913,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
/**
* Gets the value of the flag that controls whether or not connections being returned to the pool will be checked
* and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
- * setting is {@code false} when the connection is returned. It is <code>true</code> by default.
+ * setting is {@code false} when the connection is returned. It is {@code true} by default.
*
* @return Whether or not connections being returned to the pool will be checked and configured with auto-commit.
* @deprecated Use {@link #getAutoCommitOnReturn()}.
@@ -1093,7 +1072,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
}
/**
- * Gets the value of the <code>maxOpenPreparedStatements</code> property.
+ * Gets the value of the {@code maxOpenPreparedStatements} property.
*
* @return the maximum number of open statements
*/
@@ -1446,13 +1425,13 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
}
/**
- * Gets the JDBC connection {code url} property.
+ * Gets the JDBC connection {code connectionString} property.
*
- * @return the {code url} passed to the JDBC driver to establish connections
+ * @return the {code connectionString} passed to the JDBC driver to establish connections
*/
@Override
public synchronized String getUrl() {
- return this.url;
+ return this.connectionString;
}
/**
@@ -1703,39 +1682,42 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
start();
}
- /**
- * Sets the print writer to be used by this configuration to log information on abandoned objects.
- *
- * @param logWriter The new log writer
- */
- public void setAbandonedLogWriter(final PrintWriter logWriter) {
+ private <T> void setAbandoned(final BiConsumer<AbandonedConfig, T> consumer, final T object) {
if (abandonedConfig == null) {
abandonedConfig = new AbandonedConfig();
}
- abandonedConfig.setLogWriter(logWriter);
+ consumer.accept(abandonedConfig, object);
final GenericObjectPool<?> gop = this.connectionPool;
if (gop != null) {
gop.setAbandonedConfig(abandonedConfig);
}
}
+ private <T> void setConnectionPool(final BiConsumer<GenericObjectPool<PoolableConnection>, T> consumer, final T object) {
+ if (connectionPool != null) {
+ consumer.accept(connectionPool, object);
+ }
+ }
+
+ /**
+ * Sets the print writer to be used by this configuration to log information on abandoned objects.
+ *
+ * @param logWriter The new log writer
+ */
+ public void setAbandonedLogWriter(final PrintWriter logWriter) {
+ setAbandoned(AbandonedConfig::setLogWriter, logWriter);
+ }
+
/**
* If the connection pool implements {@link org.apache.tomcat.dbcp.pool2.UsageTracking UsageTracking}, configure whether
* the connection pool should record a stack trace every time a method is called on a pooled connection and retain
* the most recent stack trace to aid debugging of abandoned connections.
*
- * @param usageTracking A value of <code>true</code> will enable the recording of a stack trace on every use of a
+ * @param usageTracking A value of {@code true} will enable the recording of a stack trace on every use of a
* pooled connection
*/
public void setAbandonedUsageTracking(final boolean usageTracking) {
- if (abandonedConfig == null) {
- abandonedConfig = new AbandonedConfig();
- }
- abandonedConfig.setUseUsageTracking(usageTracking);
- final GenericObjectPool<?> gop = this.connectionPool;
- if (gop != null) {
- gop.setAbandonedConfig(abandonedConfig);
- }
+ setAbandoned(AbandonedConfig::setUseUsageTracking, Boolean.valueOf(usageTracking));
}
/**
@@ -1756,7 +1738,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
/**
* Sets the value of the flag that controls whether or not connections being returned to the pool will be checked
* and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
- * setting is {@code false} when the connection is returned. It is <code>true</code> by default.
+ * setting is {@code false} when the connection is returned. It is {@code true} by default.
*
* @param autoCommitOnReturn Whether or not connections being returned to the pool will be checked and configured
* with auto-commit.
@@ -1807,20 +1789,23 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
* @param connectionInitSqls Collection of SQL statements to execute on connection creation
*/
public void setConnectionInitSqls(final Collection<String> connectionInitSqls) {
- if (connectionInitSqls != null && !connectionInitSqls.isEmpty()) {
- ArrayList<String> newVal = null;
- for (final String s : connectionInitSqls) {
- if (!isEmpty(s)) {
- if (newVal == null) {
- newVal = new ArrayList<>();
- }
- newVal.add(s);
- }
- }
- this.connectionInitSqls = newVal;
- } else {
- this.connectionInitSqls = null;
- }
+// if (connectionInitSqls != null && !connectionInitSqls.isEmpty()) {
+// ArrayList<String> newVal = null;
+// for (final String s : connectionInitSqls) {
+// if (!isEmpty(s)) {
+// if (newVal == null) {
+// newVal = new ArrayList<>();
+// }
+// newVal.add(s);
+// }
+// }
+// this.connectionInitSqls = newVal;
+// } else {
+// this.connectionInitSqls = null;
+// }
+ final List<String> collect = Utils.isEmpty(connectionInitSqls) ? null
+ : connectionInitSqls.stream().filter(s -> !isEmpty(s)).collect(Collectors.toList());
+ this.connectionInitSqls = Utils.isEmpty(collect) ? null : collect;
}
/**
@@ -1835,23 +1820,21 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
* @param connectionProperties the connection properties used to create new connections
*/
public void setConnectionProperties(final String connectionProperties) {
- Objects.requireNonNull(connectionProperties, "connectionProperties is null");
+ Objects.requireNonNull(connectionProperties, "connectionProperties");
final String[] entries = connectionProperties.split(";");
final Properties properties = new Properties();
- for (final String entry : entries) {
- if (!entry.isEmpty()) {
- final int index = entry.indexOf('=');
- if (index > 0) {
- final String name = entry.substring(0, index);
- final String value = entry.substring(index + 1);
- properties.setProperty(name, value);
- } else {
- // no value is empty string which is how
- // java.util.Properties works
- properties.setProperty(entry, "");
- }
+ Stream.of(entries).filter(e -> !e.isEmpty()).forEach(entry -> {
+ final int index = entry.indexOf('=');
+ if (index > 0) {
+ final String name = entry.substring(0, index);
+ final String value = entry.substring(index + 1);
+ properties.setProperty(name, value);
+ } else {
+ // no value is empty string which is how
+ // java.util.Properties works
+ properties.setProperty(entry, "");
}
- }
+ });
this.connectionProperties = properties;
}
@@ -1885,7 +1868,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
/**
* Sets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
- * connection. <code>null</code> means that the driver default will be used.
+ * connection. {@code null} means that the driver default will be used.
*
* @param defaultQueryTimeoutDuration The default query timeout Duration.
* @since 2.10.0
@@ -1896,7 +1879,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
/**
* Sets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
- * connection. <code>null</code> means that the driver default will be used.
+ * connection. {@code null} means that the driver default will be used.
*
* @param defaultQueryTimeoutSeconds The default query timeout in seconds.
* @deprecated Use {@link #setDefaultQueryTimeout(Duration)}.
@@ -1953,7 +1936,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
/**
* Sets the SQL_STATE codes considered to signal fatal conditions.
* <p>
- * Overrides the defaults in {@link Utils#DISCONNECTION_SQL_CODES} (plus anything starting with
+ * Overrides the defaults in {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with
* {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #getFastFailValidation()}
* is {@code true}, whenever connections created by this datasource generate exceptions with SQL_STATE codes in this
* list, they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at
@@ -1972,20 +1955,23 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
* @since 2.1
*/
public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) {
- if (disconnectionSqlCodes != null && !disconnectionSqlCodes.isEmpty()) {
- HashSet<String> newVal = null;
- for (final String s : disconnectionSqlCodes) {
- if (!isEmpty(s)) {
- if (newVal == null) {
- newVal = new HashSet<>();
- }
- newVal.add(s);
- }
- }
- this.disconnectionSqlCodes = newVal;
- } else {
- this.disconnectionSqlCodes = null;
- }
+// if (disconnectionSqlCodes != null && !disconnectionSqlCodes.isEmpty()) {
+// HashSet<String> newVal = null;
+// for (final String s : disconnectionSqlCodes) {
+// if (!isEmpty(s)) {
+// if (newVal == null) {
+// newVal = new HashSet<>();
+// }
+// newVal.add(s);
+// }
+// }
+// this.disconnectionSqlCodes = newVal;
+// } else {
+// this.disconnectionSqlCodes = null;
+// }
+ final Set<String> collect = Utils.isEmpty(disconnectionSqlCodes) ? null
+ : disconnectionSqlCodes.stream().filter(s -> !isEmpty(s)).collect(Collectors.toSet());
+ this.disconnectionSqlCodes = Utils.isEmpty(collect) ? null : collect;
}
/**
@@ -2033,7 +2019,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
/**
* Sets the value of the flag that controls whether or not connections being returned to the pool will be checked
* and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
- * setting is {@code false} when the connection is returned. It is <code>true</code> by default.
+ * setting is {@code false} when the connection is returned. It is {@code true} by default.
*
* @param autoCommitOnReturn Whether or not connections being returned to the pool will be checked and configured
* with auto-commit.
@@ -2050,9 +2036,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
* @param evictionPolicyClassName The fully qualified class name of the EvictionPolicy implementation
*/
public synchronized void setEvictionPolicyClassName(final String evictionPolicyClassName) {
- if (connectionPool != null) {
- connectionPool.setEvictionPolicyClassName(evictionPolicyClassName);
- }
+ setConnectionPool(GenericObjectPool::setEvictionPolicyClassName, evictionPolicyClassName);
this.evictionPolicyClassName = evictionPolicyClassName;
}
@@ -2091,6 +2075,16 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
this.jmxName = jmxName;
}
+ /**
+ * Sets if connection level JMX tracking is requested for this DataSource. If true, each connection will be
+ * registered for tracking with JMX.
+ *
+ * @param registerConnectionMBean connection tracking requested for this DataSource.
+ */
+ public void setRegisterConnectionMBean(final boolean registerConnectionMBean) {
+ this.registerConnectionMBean = registerConnectionMBean;
+ }
+
/**
* Sets the LIFO property. True means the pool behaves as a LIFO queue; false means FIFO.
*
@@ -2098,23 +2092,14 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
*/
public synchronized void setLifo(final boolean lifo) {
this.lifo = lifo;
- if (connectionPool != null) {
- connectionPool.setLifo(lifo);
- }
+ setConnectionPool(GenericObjectPool::setLifo, Boolean.valueOf(lifo));
}
/**
* @param logAbandoned new logAbandoned property value
*/
public void setLogAbandoned(final boolean logAbandoned) {
- if (abandonedConfig == null) {
- abandonedConfig = new AbandonedConfig();
- }
- abandonedConfig.setLogAbandoned(logAbandoned);
- final GenericObjectPool<?> gop = this.connectionPool;
- if (gop != null) {
- gop.setAbandonedConfig(abandonedConfig);
- }
+ setAbandoned(AbandonedConfig::setLogAbandoned, Boolean.valueOf(logAbandoned));
}
/**
@@ -2208,13 +2193,11 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
*/
public synchronized void setMaxIdle(final int maxIdle) {
this.maxIdle = maxIdle;
- if (connectionPool != null) {
- connectionPool.setMaxIdle(maxIdle);
- }
+ setConnectionPool(GenericObjectPool::setMaxIdle, Integer.valueOf(maxIdle));
}
/**
- * Sets the value of the <code>maxOpenPreparedStatements</code> property.
+ * Sets the value of the {@code maxOpenPreparedStatements} property.
* <p>
* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
* time one of the following methods is invoked: <code>getConnection, setLogwriter,
@@ -2236,9 +2219,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
*/
public synchronized void setMaxTotal(final int maxTotal) {
this.maxTotal = maxTotal;
- if (connectionPool != null) {
- connectionPool.setMaxTotal(maxTotal);
- }
+ setConnectionPool(GenericObjectPool::setMaxTotal, Integer.valueOf(maxTotal));
}
/**
@@ -2250,9 +2231,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
*/
public synchronized void setMaxWait(final Duration maxWaitDuration) {
this.maxWaitDuration = maxWaitDuration;
- if (connectionPool != null) {
- connectionPool.setMaxWait(maxWaitDuration);
- }
+ setConnectionPool(GenericObjectPool::setMaxWait, maxWaitDuration);
}
/**
@@ -2276,9 +2255,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
*/
public synchronized void setMinEvictableIdle(final Duration minEvictableIdleDuration) {
this.minEvictableIdleDuration = minEvictableIdleDuration;
- if (connectionPool != null) {
- connectionPool.setMinEvictableIdle(minEvictableIdleDuration);
- }
+ setConnectionPool(GenericObjectPool::setMinEvictableIdle, minEvictableIdleDuration);
}
/**
@@ -2303,9 +2280,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
*/
public synchronized void setMinIdle(final int minIdle) {
this.minIdle = minIdle;
- if (connectionPool != null) {
- connectionPool.setMinIdle(minIdle);
- }
+ setConnectionPool(GenericObjectPool::setMinIdle, Integer.valueOf(minIdle));
}
/**
@@ -2316,9 +2291,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
*/
public synchronized void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
this.numTestsPerEvictionRun = numTestsPerEvictionRun;
- if (connectionPool != null) {
- connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
- }
+ setConnectionPool(GenericObjectPool::setNumTestsPerEvictionRun, Integer.valueOf(numTestsPerEvictionRun));
}
/**
@@ -2355,14 +2328,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
* @see #getRemoveAbandonedOnBorrow()
*/
public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) {
- if (abandonedConfig == null) {
- abandonedConfig = new AbandonedConfig();
- }
- abandonedConfig.setRemoveAbandonedOnBorrow(removeAbandonedOnBorrow);
- final GenericObjectPool<?> gop = this.connectionPool;
- if (gop != null) {
- gop.setAbandonedConfig(abandonedConfig);
- }
+ setAbandoned(AbandonedConfig::setRemoveAbandonedOnBorrow, Boolean.valueOf(removeAbandonedOnBorrow));
}
/**
@@ -2370,14 +2336,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
* @see #getRemoveAbandonedOnMaintenance()
*/
public void setRemoveAbandonedOnMaintenance(final boolean removeAbandonedOnMaintenance) {
- if (abandonedConfig == null) {
- abandonedConfig = new AbandonedConfig();
- }
- abandonedConfig.setRemoveAbandonedOnMaintenance(removeAbandonedOnMaintenance);
- final GenericObjectPool<?> gop = this.connectionPool;
- if (gop != null) {
- gop.setAbandonedConfig(abandonedConfig);
- }
+ setAbandoned(AbandonedConfig::setRemoveAbandonedOnMaintenance, Boolean.valueOf(removeAbandonedOnMaintenance));
}
/**
@@ -2394,14 +2353,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
* @since 2.10.0
*/
public void setRemoveAbandonedTimeout(final Duration removeAbandonedTimeout) {
- if (abandonedConfig == null) {
- abandonedConfig = new AbandonedConfig();
- }
- abandonedConfig.setRemoveAbandonedTimeout(removeAbandonedTimeout);
- final GenericObjectPool<?> gop = this.connectionPool;
- if (gop != null) {
- gop.setAbandonedConfig(abandonedConfig);
- }
+ setAbandoned(AbandonedConfig::setRemoveAbandonedTimeout, removeAbandonedTimeout);
}
/**
@@ -2419,14 +2371,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
*/
@Deprecated
public void setRemoveAbandonedTimeout(final int removeAbandonedTimeout) {
- if (abandonedConfig == null) {
- abandonedConfig = new AbandonedConfig();
- }
- abandonedConfig.setRemoveAbandonedTimeout(Duration.ofSeconds(removeAbandonedTimeout));
- final GenericObjectPool<?> gop = this.connectionPool;
- if (gop != null) {
- gop.setAbandonedConfig(abandonedConfig);
- }
+ setAbandoned(AbandonedConfig::setRemoveAbandonedTimeout, Duration.ofSeconds(removeAbandonedTimeout));
}
/**
@@ -2451,9 +2396,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
*/
public synchronized void setSoftMinEvictableIdle(final Duration softMinEvictableIdleTimeMillis) {
this.softMinEvictableIdleDuration = softMinEvictableIdleTimeMillis;
- if (connectionPool != null) {
- connectionPool.setSoftMinEvictableIdle(softMinEvictableIdleTimeMillis);
- }
+ setConnectionPool(GenericObjectPool::setSoftMinEvictableIdle, softMinEvictableIdleTimeMillis);
}
/**
@@ -2479,9 +2422,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
*/
public synchronized void setTestOnBorrow(final boolean testOnBorrow) {
this.testOnBorrow = testOnBorrow;
- if (connectionPool != null) {
- connectionPool.setTestOnBorrow(testOnBorrow);
- }
+ setConnectionPool(GenericObjectPool::setTestOnBorrow, Boolean.valueOf(testOnBorrow));
}
/**
@@ -2492,35 +2433,29 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
*/
public synchronized void setTestOnCreate(final boolean testOnCreate) {
this.testOnCreate = testOnCreate;
- if (connectionPool != null) {
- connectionPool.setTestOnCreate(testOnCreate);
- }
+ setConnectionPool(GenericObjectPool::setTestOnCreate, Boolean.valueOf(testOnCreate));
}
/**
- * Sets the <code>testOnReturn</code> property. This property determines whether or not the pool will validate
+ * Sets the {@code testOnReturn} property. This property determines whether or not the pool will validate
* objects before they are returned to the pool.
*
* @param testOnReturn new value for testOnReturn property
*/
public synchronized void setTestOnReturn(final boolean testOnReturn) {
this.testOnReturn = testOnReturn;
- if (connectionPool != null) {
- connectionPool.setTestOnReturn(testOnReturn);
- }
+ setConnectionPool(GenericObjectPool::setTestOnReturn, Boolean.valueOf(testOnReturn));
}
/**
- * Sets the <code>testWhileIdle</code> property. This property determines whether or not the idle object evictor
+ * Sets the {@code testWhileIdle} property. This property determines whether or not the idle object evictor
* will validate connections.
*
* @param testWhileIdle new value for testWhileIdle property
*/
public synchronized void setTestWhileIdle(final boolean testWhileIdle) {
this.testWhileIdle = testWhileIdle;
- if (connectionPool != null) {
- connectionPool.setTestWhileIdle(testWhileIdle);
- }
+ setConnectionPool(GenericObjectPool::setTestWhileIdle, Boolean.valueOf(testWhileIdle));
}
/**
@@ -2532,9 +2467,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
*/
public synchronized void setDurationBetweenEvictionRuns(final Duration timeBetweenEvictionRunsMillis) {
this.durationBetweenEvictionRuns = timeBetweenEvictionRunsMillis;
- if (connectionPool != null) {
- connectionPool.setTimeBetweenEvictionRuns(timeBetweenEvictionRunsMillis);
- }
+ setConnectionPool(GenericObjectPool::setTimeBetweenEvictionRuns, timeBetweenEvictionRunsMillis);
}
/**
@@ -2550,17 +2483,17 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean
}
/**
- * Sets the {code url}.
+ * Sets the {code connection string}.
* <p>
* Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
* time one of the following methods is invoked: <code>getConnection, setLogwriter,
* setLoginTimeout, getLoginTimeout, getLogWriter.</code>
* </p>
*
- * @param url the new value for the JDBC connection url
+ * @param connectionString the new value for the JDBC connection connectionString
*/
- public synchronized void setUrl(final String url) {
- this.url = url;
+ public synchronized void setUrl(final String connectionString) {
+ this.connectionString = connectionString;
}
/**
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java
index 7a77f40cfb..daa7cf0091 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java
@@ -20,6 +20,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
+import java.sql.SQLException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
@@ -49,12 +50,12 @@ import org.apache.tomcat.dbcp.pool2.impl.BaseObjectPoolConfig;
import org.apache.tomcat.dbcp.pool2.impl.GenericObjectPoolConfig;
/**
- * JNDI object factory that creates an instance of <code>BasicDataSource</code> that has been configured based on the
- * <code>RefAddr</code> values of the specified <code>Reference</code>, which must match the names and data types of the
- * <code>BasicDataSource</code> bean properties with the following exceptions:
+ * JNDI object factory that creates an instance of {@code BasicDataSource} that has been configured based on the
+ * {@code RefAddr} values of the specified {@code Reference}, which must match the names and data types of the
+ * {@code BasicDataSource} bean properties with the following exceptions:
* <ul>
- * <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>
+ * <li>{@code connectionInitSqls} must be passed to this factory as a single String using semicolon to delimit the
+ * statements whereas {@code BasicDataSource} requires a collection of Strings.</li>
* </ul>
*
* @since 2.0
@@ -85,12 +86,13 @@ public class BasicDataSourceFactory implements ObjectFactory {
private static final String PROP_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = "softMinEvictableIdleTimeMillis";
private static final String PROP_EVICTION_POLICY_CLASS_NAME = "evictionPolicyClassName";
private static final String PROP_TEST_WHILE_IDLE = "testWhileIdle";
- private static final String PROP_PASSWORD = "password";
+ private static final String PROP_PASSWORD = Constants.KEY_PASSWORD;
private static final String PROP_URL = "url";
private static final String PROP_USER_NAME = "username";
private static final String PROP_VALIDATION_QUERY = "validationQuery";
private static final String PROP_VALIDATION_QUERY_TIMEOUT = "validationQueryTimeout";
private static final String PROP_JMX_NAME = "jmxName";
+ private static final String PROP_REGISTER_CONNECTION_MBEAN = "registerConnectionMBean";
private static final String PROP_CONNECTION_FACTORY_CLASS_NAME = "connectionFactoryClassName";
/**
@@ -136,7 +138,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
private static final String SILENT_PROP_SINGLETON = "singleton";
private static final String SILENT_PROP_AUTH = "auth";
- private static final String[] ALL_PROPERTIES = {PROP_DEFAULT_AUTO_COMMIT, PROP_DEFAULT_READ_ONLY,
+ private static final List<String> ALL_PROPERTY_NAMES = Arrays.asList(PROP_DEFAULT_AUTO_COMMIT, PROP_DEFAULT_READ_ONLY,
PROP_DEFAULT_TRANSACTION_ISOLATION, PROP_DEFAULT_CATALOG, PROP_DEFAULT_SCHEMA, PROP_CACHE_STATE,
PROP_DRIVER_CLASS_NAME, PROP_LIFO, PROP_MAX_TOTAL, PROP_MAX_IDLE, PROP_MIN_IDLE, PROP_INITIAL_SIZE,
PROP_MAX_WAIT_MILLIS, PROP_TEST_ON_CREATE, PROP_TEST_ON_BORROW, PROP_TEST_ON_RETURN,
@@ -149,7 +151,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
PROP_MAX_OPEN_PREPARED_STATEMENTS, PROP_CONNECTION_PROPERTIES, PROP_MAX_CONN_LIFETIME_MILLIS,
PROP_LOG_EXPIRED_CONNECTIONS, PROP_ROLLBACK_ON_RETURN, PROP_ENABLE_AUTO_COMMIT_ON_RETURN,
PROP_DEFAULT_QUERY_TIMEOUT, PROP_FAST_FAIL_VALIDATION, PROP_DISCONNECTION_SQL_CODES, PROP_JMX_NAME,
- PROP_CONNECTION_FACTORY_CLASS_NAME };
+ PROP_REGISTER_CONNECTION_MBEAN, PROP_CONNECTION_FACTORY_CLASS_NAME);
/**
* Obsolete properties from DBCP 1.x. with warning strings suggesting new properties. LinkedHashMap will guarantee
@@ -215,10 +217,10 @@ public class BasicDataSourceFactory implements ObjectFactory {
* @param properties
* The data source configuration properties.
* @return A new a {@link BasicDataSource} instance based on the given properties.
- * @throws Exception
+ * @throws SQLException
* Thrown when an error occurs creating the data source.
*/
- public static BasicDataSource createDataSource(final Properties properties) throws Exception {
+ public static BasicDataSource createDataSource(final Properties properties) throws SQLException {
final BasicDataSource dataSource = new BasicDataSource();
acceptBoolean(properties, PROP_DEFAULT_AUTO_COMMIT, dataSource::setDefaultAutoCommit);
acceptBoolean(properties, PROP_DEFAULT_READ_ONLY, dataSource::setDefaultReadOnly);
@@ -295,6 +297,7 @@ public class BasicDataSourceFactory implements ObjectFactory {
acceptDurationOfMillis(properties, PROP_MAX_CONN_LIFETIME_MILLIS, dataSource::setMaxConn);
acceptBoolean(properties, PROP_LOG_EXPIRED_CONNECTIONS, dataSource::setLogExpiredConnections);
acceptString(properties, PROP_JMX_NAME, dataSource::setJmxName);
+ acceptBoolean(properties, PROP_REGISTER_CONNECTION_MBEAN, dataSource::setRegisterConnectionMBean);
acceptBoolean(properties, PROP_ENABLE_AUTO_COMMIT_ON_RETURN, dataSource::setAutoCommitOnReturn);
acceptBoolean(properties, PROP_ROLLBACK_ON_RETURN, dataSource::setRollbackOnReturn);
acceptDurationOfSeconds(properties, PROP_DEFAULT_QUERY_TIMEOUT, dataSource::setDefaultQueryTimeout);
@@ -319,14 +322,18 @@ public class BasicDataSourceFactory implements ObjectFactory {
/**
* Parse properties from the string. Format of the string must be [propertyName=property;]*
*
- * @param propText The string containing the properties
- * @return Properties
- * @throws IOException If the properties string is not correctly formatted
+ * @param propText The source text
+ * @return Properties A new Properties instance
+ * @throws SQLException When a paring exception occurs
*/
- private static Properties getProperties(final String propText) throws IOException {
+ private static Properties getProperties(final String propText) throws SQLException {
final Properties p = new Properties();
if (propText != null) {
- p.load(new ByteArrayInputStream(propText.replace(';', '\n').getBytes(StandardCharsets.ISO_8859_1)));
+ try {
+ p.load(new ByteArrayInputStream(propText.replace(';', '\n').getBytes(StandardCharsets.ISO_8859_1)));
+ } catch (IOException e) {
+ throw new SQLException(propText, e);
+ }
}
return p;
}
@@ -350,28 +357,28 @@ public class BasicDataSourceFactory implements ObjectFactory {
}
/**
- * Creates and return a new <code>BasicDataSource</code> instance. If no instance can be created, return
- * <code>null</code> instead.
+ * Creates and return a new {@code BasicDataSource} instance. If no instance can be created, return
+ * {@code null} instead.
*
* @param obj
* The possibly null object containing location or reference information that can be used in creating an
* object
* @param name
- * The name of this object relative to <code>nameCtx</code>
+ * The name of this object relative to {@code nameCtx}
* @param nameCtx
- * The context relative to which the <code>name</code> parameter is specified, or <code>null</code> if
- * <code>name</code> is relative to the default initial context
+ * The context relative to which the {@code name} parameter is specified, or {@code null} if
+ * {@code name} is relative to the default initial context
* @param environment
* The possibly null environment that is used in creating this object
*
- * @throws Exception
+ * @throws SQLException
* if an exception occurs creating the instance
*/
@Override
public Object getObjectInstance(final Object obj, final Name name, final Context nameCtx,
- final Hashtable<?, ?> environment) throws Exception {
+ final Hashtable<?, ?> environment) throws SQLException {
- // We only know how to deal with <code>javax.naming.Reference</code>s
+ // We only know how to deal with {@code javax.naming.Reference}s
// that specify a class name of "javax.sql.DataSource"
if (obj == null || !(obj instanceof Reference)) {
return null;
@@ -389,12 +396,12 @@ public class BasicDataSourceFactory implements ObjectFactory {
infoMessages.forEach(log::info);
final Properties properties = new Properties();
- for (final String propertyName : ALL_PROPERTIES) {
+ ALL_PROPERTY_NAMES.forEach(propertyName -> {
final RefAddr ra = ref.get(propertyName);
if (ra != null) {
properties.setProperty(propertyName, Objects.toString(ra.getContent(), null));
}
- }
+ });
return createDataSource(properties);
}
@@ -413,21 +420,19 @@ public class BasicDataSourceFactory implements ObjectFactory {
* container for info messages
*/
private void validatePropertyNames(final Reference ref, final Name name, final List<String> warnMessages,
- final List<String> infoMessages) {
- final List<String> allPropsAsList = Arrays.asList(ALL_PROPERTIES);
+ final List<String> infoMessages) {
final String nameString = name != null ? "Name = " + name.toString() + " " : "";
if (NUPROP_WARNTEXT != null && !NUPROP_WARNTEXT.isEmpty()) {
- for (final String propertyName : NUPROP_WARNTEXT.keySet()) {
+ NUPROP_WARNTEXT.forEach((propertyName, value) -> {
final RefAddr ra = ref.get(propertyName);
- if (ra != null && !allPropsAsList.contains(ra.getType())) {
+ if (ra != null && !ALL_PROPERTY_NAMES.contains(ra.getType())) {
final StringBuilder stringBuilder = new StringBuilder(nameString);
final String propertyValue = Objects.toString(ra.getContent(), null);
- stringBuilder.append(NUPROP_WARNTEXT.get(propertyName)).append(" You have set value of \"")
- .append(propertyValue).append("\" for \"").append(propertyName)
- .append("\" property, which is being ignored.");
+ stringBuilder.append(value).append(" You have set value of \"").append(propertyValue).append("\" for \"").append(propertyName)
+ .append("\" property, which is being ignored.");
warnMessages.add(stringBuilder.toString());
}
- }
+ });
}
final Enumeration<RefAddr> allRefAddrs = ref.getAll();
@@ -436,12 +441,11 @@ public class BasicDataSourceFactory implements ObjectFactory {
final String propertyName = ra.getType();
// If property name is not in the properties list, we haven't warned on it
// and it is not in the "silent" list, tell user we are ignoring it.
- if (!(allPropsAsList.contains(propertyName) || NUPROP_WARNTEXT.containsKey(propertyName)
- || SILENT_PROPERTIES.contains(propertyName))) {
+ if (!(ALL_PROPERTY_NAMES.contains(propertyName) || NUPROP_WARNTEXT.containsKey(propertyName) || SILENT_PROPERTIES.contains(propertyName))) {
final String propertyValue = Objects.toString(ra.getContent(), null);
final StringBuilder stringBuilder = new StringBuilder(nameString);
- stringBuilder.append("Ignoring unknown property: ").append("value of \"").append(propertyValue)
- .append("\" for \"").append(propertyName).append("\" property");
+ stringBuilder.append("Ignoring unknown property: ").append("value of \"").append(propertyValue).append("\" for \"").append(propertyName)
+ .append("\" property");
infoMessages.add(stringBuilder.toString());
}
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactoryFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactoryFactory.java
index bd5c244b3a..01d5894c79 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactoryFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactoryFactory.java
@@ -25,7 +25,7 @@ import java.util.Properties;
*
* @since 2.7.0
*/
-class ConnectionFactoryFactory {
+final class ConnectionFactoryFactory {
/**
* Creates a new {@link DriverConnectionFactory} allowing for an override through
@@ -46,14 +46,14 @@ class ConnectionFactoryFactory {
if (user != null) {
connectionProperties.put(Constants.KEY_USER, user);
} else {
- basicDataSource.log("DBCP DataSource configured without a 'username'");
+ basicDataSource.log(String.format("DBCP DataSource configured without a '%s'", Constants.KEY_USER));
}
final String pwd = basicDataSource.getPassword();
if (pwd != null) {
- connectionProperties.put("password", pwd);
+ connectionProperties.put(Constants.KEY_PASSWORD, pwd);
} else {
- basicDataSource.log("DBCP DataSource configured without a 'password'");
+ basicDataSource.log(String.format("DBCP DataSource configured without a '%s'", Constants.KEY_PASSWORD));
}
final String connectionFactoryClassName = basicDataSource.getConnectionFactoryClassName();
if (connectionFactoryClassName != null) {
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/DataSourceConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/DataSourceConnectionFactory.java
index 3ab0a7a4e6..334bfbf5b2 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DataSourceConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DataSourceConnectionFactory.java
@@ -106,6 +106,6 @@ public class DataSourceConnectionFactory implements ConnectionFactory {
* @since 2.6.0
*/
public char[] getUserPassword() {
- return userPassword == null ? null : userPassword.clone();
+ return Utils.clone(userPassword);
}
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java
index ebac9834cd..6394875366 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java
@@ -25,7 +25,6 @@ import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
-import java.sql.ResultSet;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
@@ -108,7 +107,7 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
String label = "";
try {
label = connection.toString();
- } catch (final Exception ex) {
+ } catch (final Exception ignored) {
// ignore, leave label empty
}
throw new SQLException("Connection " + label + " is closed.");
@@ -118,7 +117,7 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
}
/**
- * Can be used to clear cached state when it is known that the underlying connection may have been accessed
+ * Clears the cached state. Call when you known that the underlying connection may have been accessed
* directly.
*/
public void clearCachedState() {
@@ -145,9 +144,9 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
* Closes the underlying connection, and close any Statements that were not explicitly closed. Sub-classes that
* override this method must:
* <ol>
- * <li>Call passivate()</li>
+ * <li>Call {@link #passivate()}</li>
* <li>Call close (or the equivalent appropriate action) on the wrapped connection</li>
- * <li>Set _closed to <code>false</code></li>
+ * <li>Set {@code closed} to {@code false}</li>
* </ol>
*/
@Override
@@ -359,7 +358,7 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
/**
* Gets the default query timeout that will be used for {@link Statement}s created from this connection.
- * <code>null</code> means that the driver default will be used.
+ * {@code null} means that the driver default will be used.
*
* @return query timeout limit in seconds; zero means there is no limit.
* @deprecated Use {@link #getDefaultQueryTimeoutDuration()}.
@@ -371,7 +370,7 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
/**
* Gets the default query timeout that will be used for {@link Statement}s created from this connection.
- * <code>null</code> means that the driver default will be used.
+ * {@code null} means that the driver default will be used.
*
* @return query timeout limit; zero means there is no limit.
* @since 2.10.0
@@ -556,7 +555,7 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
*
* @param c
* connection to compare innermost delegate with
- * @return true if innermost delegate equals <code>c</code>
+ * @return true if innermost delegate equals {@code c}
*/
public boolean innermostDelegateEquals(final Connection c) {
final Connection innerCon = getInnermostDelegateInternal();
@@ -646,26 +645,10 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
// The JDBC specification requires that a Connection close any open
// Statement's when it is closed.
// DBCP-288. Not all the traced objects will be statements
- final List<AbandonedTrace> traces = getTrace();
- if (traces != null && !traces.isEmpty()) {
+ final List<AbandonedTrace> traceList = getTrace();
+ if (!Utils.isEmpty(traceList)) {
final List<Exception> thrownList = new ArrayList<>();
- for (final Object trace : traces) {
- if (trace instanceof Statement) {
- try {
- ((Statement) trace).close();
- } catch (final Exception e) {
- thrownList.add(e);
- }
- } else if (trace instanceof ResultSet) {
- // DBCP-265: Need to close the result sets that are
- // generated via DatabaseMetaData
- try {
- ((ResultSet) trace).close();
- } catch (final Exception e) {
- thrownList.add(e);
- }
- }
- }
+ traceList.forEach(trace -> trace.close(thrownList::add));
clearTrace();
if (!thrownList.isEmpty()) {
throw new SQLExceptionList(thrownList);
@@ -879,7 +862,7 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
/**
* Sets the default query timeout that will be used for {@link Statement}s created from this connection.
- * <code>null</code> means that the driver default will be used.
+ * {@code null} means that the driver default will be used.
*
* @param defaultQueryTimeoutDuration
* the new query timeout limit Duration; zero means there is no limit.
@@ -891,7 +874,7 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
/**
* Sets the default query timeout that will be used for {@link Statement}s created from this connection.
- * <code>null</code> means that the driver default will be used.
+ * {@code null} means that the driver default will be used.
*
* @param defaultQueryTimeoutSeconds
* the new query timeout limit in seconds; zero means there is no limit.
@@ -1026,7 +1009,7 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
str = sb.toString();
}
}
- } catch (final SQLException ex) {
+ } catch (final SQLException ignored) {
// Ignore
}
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingPreparedStatement.java b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingPreparedStatement.java
index 38502503fc..4ecf26f891 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingPreparedStatement.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingPreparedStatement.java
@@ -35,7 +35,9 @@ import java.sql.SQLXML;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
+import java.util.ArrayList;
import java.util.Calendar;
+import java.util.List;
/**
* A base delegating implementation of {@link PreparedStatement}.
@@ -690,4 +692,25 @@ public class DelegatingPreparedStatement extends DelegatingStatement implements
final Statement statement = getDelegate();
return statement == null ? "NULL" : statement.toString();
}
+
+ protected void prepareToReturn() throws SQLException {
+ setClosedInternal(true);
+ removeThisTrace(getConnectionInternal());
+
+ // The JDBC spec requires that a statement close any open
+ // ResultSet's when it is closed.
+ // FIXME The PreparedStatement we're wrapping should handle this for us.
+ // See DBCP-10 for what could happen when ResultSets are closed twice.
+ final List<AbandonedTrace> traceList = getTrace();
+ if (traceList != null) {
+ final List<Exception> thrownList = new ArrayList<>();
+ traceList.forEach(trace -> trace.close(thrownList::add));
+ clearTrace();
+ if (!thrownList.isEmpty()) {
+ throw new SQLExceptionList(thrownList);
+ }
+ }
+
+ super.passivate();
+ }
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java
index 3f3481ba68..642d633b2c 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java
@@ -137,35 +137,24 @@ public class DelegatingStatement extends AbandonedTrace implements Statement {
// ResultSet's when it is closed.
// FIXME The PreparedStatement we're wrapping should handle this for us.
// See bug 17301 for what could happen when ResultSets are closed twice.
- final List<AbandonedTrace> resultSetList = getTrace();
- if (resultSetList != null) {
- final ResultSet[] resultSets = resultSetList.toArray(Utils.EMPTY_RESULT_SET_ARRAY);
- for (final ResultSet resultSet : resultSets) {
- if (resultSet != null) {
- try {
- resultSet.close();
- } catch (final Exception e) {
- if (connection != null) {
- // Does not rethrow e.
- connection.handleExceptionNoThrow(e);
- }
- thrownList.add(e);
- }
- }
- }
- clearTrace();
- }
- if (statement != null) {
- try {
- statement.close();
- } catch (final Exception e) {
+ final List<AbandonedTrace> traceList = getTrace();
+ if (traceList != null) {
+ traceList.forEach(trace -> trace.close(e -> {
if (connection != null) {
// Does not rethrow e.
connection.handleExceptionNoThrow(e);
}
thrownList.add(e);
- }
+ }));
+ clearTrace();
}
+ Utils.close(statement, e -> {
+ if (connection != null) {
+ // Does not rethrow e.
+ connection.handleExceptionNoThrow(e);
+ }
+ thrownList.add(e);
+ });
} finally {
closed = true;
statement = null;
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java
index daea05de80..bacc31f41c 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java
@@ -25,7 +25,7 @@ import java.sql.SQLException;
*
* @since 2.7.0
*/
-class DriverFactory {
+final class DriverFactory {
static Driver createDriver(final BasicDataSource basicDataSource) throws SQLException {
// Load the JDBC driver class
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java
index 3f92125234..56075855f0 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java
@@ -49,7 +49,7 @@ public class DriverManagerConnectionFactory implements ConnectionFactory {
* Constructor for DriverManagerConnectionFactory.
*
* @param connectionUri
- * a database url of the form <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
+ * a database connection string of the form {@code jdbc:<em>subprotocol</em>:<em>subname</em>}
* @since 2.2
*/
public DriverManagerConnectionFactory(final String connectionUri) {
@@ -63,7 +63,7 @@ public class DriverManagerConnectionFactory implements ConnectionFactory {
* Constructor for DriverManagerConnectionFactory.
*
* @param connectionUri
- * a database url of the form <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
+ * a database connection string of the form {@code jdbc:<em>subprotocol</em>:<em>subname</em>}
* @param properties
* a list of arbitrary string tag/value pairs as connection arguments; normally at least a "user" and
* "password" property should be included.
@@ -79,7 +79,7 @@ public class DriverManagerConnectionFactory implements ConnectionFactory {
* Constructor for DriverManagerConnectionFactory.
*
* @param connectionUri
- * a database url of the form <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
+ * a database connection string of the form {@code jdbc:<em>subprotocol</em>:<em>subname</em>}
* @param userName
* the database user
* @param userPassword
@@ -97,7 +97,7 @@ public class DriverManagerConnectionFactory implements ConnectionFactory {
* Constructor for DriverManagerConnectionFactory.
*
* @param connectionUri
- * a database url of the form <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
+ * a database connection string of the form {@code jdbc:<em>subprotocol</em>:<em>subname</em>}
* @param userName
* the database user
* @param userPassword
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java b/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java
index 42f29c450d..baf1a2a596 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java
@@ -458,7 +458,7 @@ public class Jdbc41Bridge {
throws SQLException {
try {
connection.setNetworkTimeout(executor, milliseconds);
- } catch (final AbstractMethodError e) {
+ } catch (final AbstractMethodError ignored) {
// do nothing
}
}
@@ -480,7 +480,7 @@ public class Jdbc41Bridge {
public static void setSchema(final Connection connection, final String schema) throws SQLException {
try {
connection.setSchema(schema);
- } catch (final AbstractMethodError e) {
+ } catch (final AbstractMethodError ignored) {
// do nothing
}
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java b/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java
index dd2bbdd7e1..24c0e8ba1e 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java
@@ -16,28 +16,29 @@
*/
package org.apache.tomcat.dbcp.dbcp2;
+import java.sql.SQLException;
+
/**
* Exception thrown when a connection's maximum lifetime has been exceeded.
*
* @since 2.1
*/
-class LifetimeExceededException extends Exception {
+final class LifetimeExceededException extends SQLException {
private static final long serialVersionUID = -3783783104516492659L;
/**
- * Create a LifetimeExceededException.
+ * Constructs a new instance.
*/
public LifetimeExceededException() {
}
/**
- * Create a LifetimeExceededException with the given message.
+ * Constructs a new instance with the given message.
*
- * @param message
- * The message with which to create the exception
+ * @param reason a description of the exception
*/
- public LifetimeExceededException(final String message) {
- super(message);
+ public LifetimeExceededException(final String reason) {
+ super(reason);
}
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties b/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties
index 3aaa50bc31..cf0efed352 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties
+++ b/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties
@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-connectionFactory.lifetimeExceeded=The lifetime of the connection [{0}] milliseconds exceeds the maximum permitted value of [{1}] milliseconds
+connectionFactory.lifetimeExceeded=The lifetime of the connection [{0}] exceeds the maximum permitted value of [{1}].
pool.close.fail=Cannot close connection pool.
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java b/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java
index 340517d9bd..f882245fb7 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java
@@ -31,7 +31,7 @@ import org.apache.juli.logging.LogFactory;
*
* @since 2.2.1
*/
-class ObjectNameWrapper {
+final class ObjectNameWrapper {
private static final Log log = LogFactory.getLog(ObjectNameWrapper.class);
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java b/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java
index 87991e7e7c..64e261b7f0 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java
@@ -21,6 +21,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Objects;
+import java.util.function.Function;
import org.apache.tomcat.dbcp.dbcp2.PoolingConnection.StatementType;
@@ -31,101 +32,34 @@ import org.apache.tomcat.dbcp.dbcp2.PoolingConnection.StatementType;
*/
public class PStmtKey {
- /**
- * Builder for prepareCall(String sql).
- */
- private class PreparedCallSQL implements StatementBuilder {
- @Override
- public Statement createStatement(final Connection connection) throws SQLException {
- return connection.prepareCall(sql);
- }
- }
-
- /**
- * Builder for prepareCall(String sql, int resultSetType, int resultSetConcurrency).
- */
- private class PreparedCallWithResultSetConcurrency implements StatementBuilder {
- @Override
- public Statement createStatement(final Connection connection) throws SQLException {
- return connection.prepareCall(sql, resultSetType.intValue(), resultSetConcurrency.intValue());
- }
- }
-
- /**
- * Builder for prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability).
- */
- private class PreparedCallWithResultSetHoldability implements StatementBuilder {
- @Override
- public Statement createStatement(final Connection connection) throws SQLException {
- return connection.prepareCall(sql, resultSetType.intValue(), resultSetConcurrency.intValue(), resultSetHoldability.intValue());
- }
- }
-
- /**
- * Builder for prepareStatement(String sql).
- */
- private class PreparedStatementSQL implements StatementBuilder {
- @Override
- public Statement createStatement(final Connection connection) throws SQLException {
- return connection.prepareStatement(sql);
- }
- }
-
- /**
- * Builder for prepareStatement(String sql, int autoGeneratedKeys).
- */
- private class PreparedStatementWithAutoGeneratedKeys implements StatementBuilder {
- @Override
- public Statement createStatement(final Connection connection) throws SQLException {
- return connection.prepareStatement(sql, autoGeneratedKeys.intValue());
- }
- }
-
- /**
- * Builder for prepareStatement(String sql, int[] columnIndexes).
- */
- private class PreparedStatementWithColumnIndexes implements StatementBuilder {
- @Override
- public Statement createStatement(final Connection connection) throws SQLException {
- return connection.prepareStatement(sql, columnIndexes);
- }
- }
-
- /**
- * Builder for prepareStatement(String sql, String[] columnNames).
- */
- private class PreparedStatementWithColumnNames implements StatementBuilder {
- @Override
- public Statement createStatement(final Connection connection) throws SQLException {
- return connection.prepareStatement(sql, columnNames);
- }
- }
-
- /**
- * Builder for prepareStatement(String sql, int resultSetType, int resultSetConcurrency).
- */
- private class PreparedStatementWithResultSetConcurrency implements StatementBuilder {
- @Override
- public Statement createStatement(final Connection connection) throws SQLException {
- return connection.prepareStatement(sql, resultSetType.intValue(), resultSetConcurrency.intValue());
- }
- }
-
- /**
- * Builder for prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability).
- */
- private class PreparedStatementWithResultSetHoldability implements StatementBuilder {
- @Override
- public Statement createStatement(final Connection connection) throws SQLException {
- return connection.prepareStatement(sql, resultSetType.intValue(), resultSetConcurrency.intValue(), resultSetHoldability.intValue());
- }
- }
-
/**
* Interface for Prepared or Callable Statement.
*/
+ @FunctionalInterface
private interface StatementBuilder {
- Statement createStatement(Connection connection) throws SQLException;
+ Statement createStatement(Connection connection, PStmtKey key) throws SQLException;
+ }
+
+ private static final StatementBuilder CallConcurrency = (c, k) -> c.prepareCall(k.sql, k.resultSetType.intValue(), k.resultSetConcurrency.intValue());
+ private static final StatementBuilder CallHoldability = (c, k) -> c.prepareCall(k.sql, k.resultSetType.intValue(), k.resultSetConcurrency.intValue(), k.resultSetHoldability.intValue());
+ private static final StatementBuilder CallSQL = (c, k) -> c.prepareCall(k.sql);
+ private static final StatementBuilder StatementAutoGeneratedKeys = (c, k) -> c.prepareStatement(k.sql, k.autoGeneratedKeys.intValue());
+ private static final StatementBuilder StatementColumnIndexes = (c, k) -> c.prepareStatement(k.sql, k.columnIndexes);
+ private static final StatementBuilder StatementColumnNames = (c, k) -> c.prepareStatement(k.sql, k.columnNames);
+ private static final StatementBuilder StatementConcurrency = (c, k) -> c.prepareStatement(k.sql, k.resultSetType.intValue(), k.resultSetConcurrency.intValue());
+ private static final StatementBuilder StatementHoldability = (c, k) -> c.prepareStatement(k.sql, k.resultSetType.intValue(), k.resultSetConcurrency.intValue(),
+ k.resultSetHoldability.intValue());
+ private static final StatementBuilder StatementSQL = (c, k) -> c.prepareStatement(k.sql);
+
+ private static StatementBuilder match(final StatementType statementType, final StatementBuilder prep, final StatementBuilder call) {
+ switch (Objects.requireNonNull(statementType, "statementType")) {
+ case PREPARED_STATEMENT:
+ return prep;
+ case CALLABLE_STATEMENT:
+ return call;
+ default:
+ throw new IllegalArgumentException(statementType.toString());
+ }
}
/**
@@ -134,32 +68,36 @@ public class PStmtKey {
private final String sql;
/**
- * Result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>,
- * or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+ * Result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or
+ * {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
*/
private final Integer resultSetType;
/**
- * Result set concurrency. A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * Result set concurrency. A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
*/
private final Integer resultSetConcurrency;
/**
- * Result set holdability. One of the following <code>ResultSet</code> constants:
- * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
+ * Result set holdability. One of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT}
+ * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}.
*/
private final Integer resultSetHoldability;
- /** Database catalog. */
+ /**
+ * Database catalog.
+ */
private final String catalog;
- /** Database schema. */
+ /**
+ * Database schema.
+ */
private final String schema;
/**
- * 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>.
+ * A flag indicating whether auto-generated keys should be returned; one of {@code Statement.RETURN_GENERATED_KEYS} or
+ * {@code Statement.NO_GENERATED_KEYS}.
*/
private final Integer autoGeneratedKeys;
@@ -173,19 +111,20 @@ public class PStmtKey {
*/
private final String[] columnNames;
+ /**
+ * Statement builder.
+ */
+ private final transient StatementBuilder statementBuilder;
+
/**
* Statement type, prepared or callable.
*/
private final StatementType statementType;
- /** Statement builder */
- private transient StatementBuilder builder;
-
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
+ * @param sql The SQL statement.
* @deprecated Use {@link #PStmtKey(String, String, String)}.
*/
@Deprecated
@@ -196,14 +135,11 @@ public class PStmtKey {
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param resultSetType
- * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
- * @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * @param sql The SQL statement.
+ * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
+ * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
* @deprecated Use {@link #PStmtKey(String, String, String, int, int)}.
*/
@Deprecated
@@ -214,10 +150,8 @@ public class PStmtKey {
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
* @deprecated Use {@link #PStmtKey(String, String, String)}.
*/
@Deprecated
@@ -228,13 +162,10 @@ public class PStmtKey {
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param autoGeneratedKeys
- * 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>.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param autoGeneratedKeys A flag indicating whether auto-generated keys should be returned; one of
+ * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}.
* @deprecated Use {@link #PStmtKey(String, String, String, int)}.
*/
@Deprecated
@@ -245,16 +176,12 @@ public class PStmtKey {
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param resultSetType
- * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
- * @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
+ * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
* @deprecated Use @link {@link #PStmtKey(String, String, String, int, int)}.
*/
@Deprecated
@@ -265,209 +192,109 @@ public class PStmtKey {
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param resultSetType
- * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
- * @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>
- * @param resultSetHoldability
- * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
- * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param resultSetType a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
+ * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}
+ * @param resultSetHoldability One of the following {@code ResultSet} constants:
+ * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}.
* @deprecated Use {@link #PStmtKey(String, String, String, int, int, int)}.
*/
@Deprecated
- public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency,
- final int resultSetHoldability) {
+ public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) {
this(sql, catalog, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.PREPARED_STATEMENT);
}
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param resultSetType
- * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
- * @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
- * @param resultSetHoldability
- * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
- * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
- * @param statementType
- * The SQL statement type, prepared or callable.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param resultSetType a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}
+ * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
+ * @param resultSetHoldability One of the following {@code ResultSet} constants:
+ * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}.
+ * @param statementType The SQL statement type, prepared or callable.
* @deprecated Use {@link #PStmtKey(String, String, String, int, int, int, PoolingConnection.StatementType)}
*/
@Deprecated
- public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency,
- final int resultSetHoldability, final StatementType statementType) {
- this.sql = sql;
- this.catalog = catalog;
- this.schema = null;
- this.resultSetType = Integer.valueOf(resultSetType);
- this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency);
- this.resultSetHoldability = Integer.valueOf(resultSetHoldability);
- this.statementType = statementType;
- this.autoGeneratedKeys = null;
- this.columnIndexes = null;
- this.columnNames = null;
- // create builder
- if (statementType == StatementType.PREPARED_STATEMENT) {
- this.builder = new PreparedStatementWithResultSetHoldability();
- } else if (statementType == StatementType.CALLABLE_STATEMENT) {
- this.builder = new PreparedCallWithResultSetHoldability();
- }
+ public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability,
+ final StatementType statementType) {
+ this(sql, catalog, null, Integer.valueOf(resultSetType), Integer.valueOf(resultSetConcurrency), Integer.valueOf(resultSetHoldability), null, null, null, statementType,
+ k -> match(statementType, StatementHoldability, CallHoldability));
}
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param resultSetType
- * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
- * @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
- * @param statementType
- * The SQL statement type, prepared or callable.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
+ * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
+ * @param statementType The SQL statement type, prepared or callable.
* @deprecated Use {@link #PStmtKey(String, String, String, int, int, PoolingConnection.StatementType)}.
*/
@Deprecated
- public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency,
- final StatementType statementType) {
- this.sql = sql;
- this.catalog = catalog;
- this.schema = null;
- this.resultSetType = Integer.valueOf(resultSetType);
- this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency);
- this.resultSetHoldability = null;
- this.statementType = statementType;
- this.autoGeneratedKeys = null;
- this.columnIndexes = null;
- this.columnNames = null;
- // create builder
- if (statementType == StatementType.PREPARED_STATEMENT) {
- this.builder = new PreparedStatementWithResultSetConcurrency();
- } else if (statementType == StatementType.CALLABLE_STATEMENT) {
- this.builder = new PreparedCallWithResultSetConcurrency();
- }
+ public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, final StatementType statementType) {
+ this(sql, catalog, null, Integer.valueOf(resultSetType), Integer.valueOf(resultSetConcurrency), null, null, null, null, statementType,
+ k -> match(statementType, StatementConcurrency, CallConcurrency));
}
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param columnIndexes
- * An array of column indexes indicating the columns that should be returned from the inserted row or
- * rows.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param columnIndexes An array of column indexes indicating the columns that should be returned from the inserted row
+ * or rows.
* @deprecated Use {@link #PStmtKey(String, String, String, int[])}.
*/
@Deprecated
public PStmtKey(final String sql, final String catalog, final int[] columnIndexes) {
- this.sql = sql;
- this.catalog = catalog;
- this.schema = null;
- this.statementType = StatementType.PREPARED_STATEMENT;
- this.autoGeneratedKeys = null;
- this.columnIndexes = columnIndexes == null ? null : Arrays.copyOf(columnIndexes, columnIndexes.length);
- this.columnNames = null;
- this.resultSetType = null;
- this.resultSetConcurrency = null;
- this.resultSetHoldability = null;
- // create builder
- this.builder = new PreparedStatementWithColumnIndexes();
+ this(sql, catalog, null, null, null, null, null, columnIndexes, null, StatementType.PREPARED_STATEMENT, StatementColumnIndexes);
}
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param statementType
- * The SQL statement type, prepared or callable.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param statementType The SQL statement type, prepared or callable.
* @deprecated Use {@link #PStmtKey(String, String, String, PoolingConnection.StatementType)}.
*/
@Deprecated
public PStmtKey(final String sql, final String catalog, final StatementType statementType) {
- this.sql = sql;
- this.catalog = catalog;
- this.schema = null;
- this.statementType = statementType;
- this.autoGeneratedKeys = null;
- this.columnIndexes = null;
- this.columnNames = null;
- this.resultSetType = null;
- this.resultSetConcurrency = null;
- this.resultSetHoldability = null;
- // create builder
- if (statementType == StatementType.PREPARED_STATEMENT) {
- this.builder = new PreparedStatementSQL();
- } else if (statementType == StatementType.CALLABLE_STATEMENT) {
- this.builder = new PreparedCallSQL();
- }
+ this(sql, catalog, null, null, null, null, null, null, null, statementType, k -> match(statementType, StatementSQL, CallSQL));
}
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param statementType
- * The SQL statement type, prepared or callable.
- * @param autoGeneratedKeys
- * 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>.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param statementType The SQL statement type, prepared or callable.
+ * @param autoGeneratedKeys A flag indicating whether auto-generated keys should be returned; one of
+ * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}.
* @deprecated Use {@link #PStmtKey(String, String, String, PoolingConnection.StatementType, Integer)}
*/
@Deprecated
- public PStmtKey(final String sql, final String catalog, final StatementType statementType,
- final Integer autoGeneratedKeys) {
- this.sql = sql;
- this.catalog = catalog;
- this.schema = null;
- this.statementType = statementType;
- this.autoGeneratedKeys = autoGeneratedKeys;
- this.columnIndexes = null;
- this.columnNames = null;
- this.resultSetType = null;
- this.resultSetConcurrency = null;
- this.resultSetHoldability = null;
- // create builder
- if (statementType == StatementType.PREPARED_STATEMENT) {
- this.builder = new PreparedStatementWithAutoGeneratedKeys();
- } else if (statementType == StatementType.CALLABLE_STATEMENT) {
- this.builder = new PreparedCallSQL();
- }
+ public PStmtKey(final String sql, final String catalog, final StatementType statementType, final Integer autoGeneratedKeys) {
+ this(sql, catalog, null, null, null, null, autoGeneratedKeys, null, null, statementType,
+ k -> match(statementType, StatementAutoGeneratedKeys, CallSQL));
}
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param schema
- * The schema
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param schema The schema
* @since 2.5.0
*/
public PStmtKey(final String sql, final String catalog, final String schema) {
@@ -477,15 +304,11 @@ public class PStmtKey {
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param schema
- * The schema
- * @param autoGeneratedKeys
- * 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>.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param schema The schema
+ * @param autoGeneratedKeys A flag indicating whether auto-generated keys should be returned; one of
+ * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}.
* @since 2.5.0
*/
public PStmtKey(final String sql, final String catalog, final String schema, final int autoGeneratedKeys) {
@@ -495,18 +318,13 @@ public class PStmtKey {
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param schema
- * The schema
- * @param resultSetType
- * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
- * @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param schema The schema
+ * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
+ * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
*/
public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency) {
this(sql, catalog, schema, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT);
@@ -515,21 +333,15 @@ public class PStmtKey {
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param schema
- * The schema
- * @param resultSetType
- * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
- * @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>
- * @param resultSetHoldability
- * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
- * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param schema The schema
+ * @param resultSetType a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
+ * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}
+ * @param resultSetHoldability One of the following {@code ResultSet} constants:
+ * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}.
* @since 2.5.0
*/
public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency,
@@ -540,249 +352,163 @@ public class PStmtKey {
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param schema
- * The schema.
- * @param resultSetType
- * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
- * @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
- * @param resultSetHoldability
- * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
- * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
- * @param statementType
- * The SQL statement type, prepared or callable.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param schema The schema.
+ * @param resultSetType a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}
+ * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
+ * @param resultSetHoldability One of the following {@code ResultSet} constants:
+ * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}.
+ * @param statementType The SQL statement type, prepared or callable.
* @since 2.5.0
*/
public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency,
final int resultSetHoldability, final StatementType statementType) {
- this.sql = sql;
- this.catalog = catalog;
- this.schema = schema;
- this.resultSetType = Integer.valueOf(resultSetType);
- this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency);
- this.resultSetHoldability = Integer.valueOf(resultSetHoldability);
- this.statementType = statementType;
- this.autoGeneratedKeys = null;
- this.columnIndexes = null;
- this.columnNames = null;
- // create builder
- if (statementType == StatementType.PREPARED_STATEMENT) {
- this.builder = new PreparedStatementWithResultSetHoldability();
- } else if (statementType == StatementType.CALLABLE_STATEMENT) {
- this.builder = new PreparedCallWithResultSetHoldability();
- }
+ this(sql, catalog, schema, Integer.valueOf(resultSetType), Integer.valueOf(resultSetConcurrency), Integer.valueOf(resultSetHoldability), null, null, null, statementType,
+ k -> match(statementType, StatementHoldability, CallHoldability));
}
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param schema
- * The schema.
- * @param resultSetType
- * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
- * @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
- * @param statementType
- * The SQL statement type, prepared or callable.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param schema The schema.
+ * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
+ * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
+ * @param statementType The SQL statement type, prepared or callable.
* @since 2.5.0
*/
public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency,
final StatementType statementType) {
- this.sql = sql;
- this.catalog = catalog;
- this.schema = schema;
- this.resultSetType = Integer.valueOf(resultSetType);
- this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency);
- this.resultSetHoldability = null;
- this.statementType = statementType;
- this.autoGeneratedKeys = null;
- this.columnIndexes = null;
- this.columnNames = null;
- // create builder
- if (statementType == StatementType.PREPARED_STATEMENT) {
- this.builder = new PreparedStatementWithResultSetConcurrency();
- } else if (statementType == StatementType.CALLABLE_STATEMENT) {
- this.builder = new PreparedCallWithResultSetConcurrency();
- }
+ this(sql, catalog, schema, Integer.valueOf(resultSetType), Integer.valueOf(resultSetConcurrency), null, null, null, null, statementType,
+ k -> match(statementType, StatementConcurrency, CallConcurrency));
}
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param schema
- * The schema.
- * @param columnIndexes
- * An array of column indexes indicating the columns that should be returned from the inserted row or
- * rows.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param schema The schema.
+ * @param columnIndexes An array of column indexes indicating the columns that should be returned from the inserted row
+ * or rows.
*/
public PStmtKey(final String sql, final String catalog, final String schema, final int[] columnIndexes) {
+ this(sql, catalog, schema, null, null, null, null, columnIndexes, null, StatementType.PREPARED_STATEMENT, StatementColumnIndexes);
+ }
+
+ private PStmtKey(final String sql, final String catalog, final String schema, final Integer resultSetType, final Integer resultSetConcurrency,
+ final Integer resultSetHoldability, final Integer autoGeneratedKeys, final int[] columnIndexes, final String[] columnNames,
+ final StatementType statementType, final Function<PStmtKey, StatementBuilder> statementBuilder) {
+ this.sql = Objects.requireNonNull(sql, "sql").trim();
+ this.catalog = catalog;
+ this.schema = schema;
+ this.resultSetType = resultSetType;
+ this.resultSetConcurrency = resultSetConcurrency;
+ this.resultSetHoldability = resultSetHoldability;
+ this.autoGeneratedKeys = autoGeneratedKeys;
+ this.columnIndexes = clone(columnIndexes);
+ this.columnNames = clone(columnNames);
+ this.statementBuilder = Objects.requireNonNull(Objects.requireNonNull(statementBuilder, "statementBuilder").apply(this), "statementBuilder");
+ this.statementType = statementType;
+ }
+
+ // Root constructor.
+ private PStmtKey(final String sql, final String catalog, final String schema, final Integer resultSetType, final Integer resultSetConcurrency,
+ final Integer resultSetHoldability, final Integer autoGeneratedKeys, final int[] columnIndexes, final String[] columnNames,
+ final StatementType statementType, final StatementBuilder statementBuilder) {
this.sql = sql;
this.catalog = catalog;
this.schema = schema;
- this.statementType = StatementType.PREPARED_STATEMENT;
- this.autoGeneratedKeys = null;
- this.columnIndexes = columnIndexes == null ? null : Arrays.copyOf(columnIndexes, columnIndexes.length);
- this.columnNames = null;
- this.resultSetType = null;
- this.resultSetConcurrency = null;
- this.resultSetHoldability = null;
- // create builder
- this.builder = new PreparedStatementWithColumnIndexes();
+ this.resultSetType = resultSetType;
+ this.resultSetConcurrency = resultSetConcurrency;
+ this.resultSetHoldability = resultSetHoldability;
+ this.autoGeneratedKeys = autoGeneratedKeys;
+ this.columnIndexes = clone(columnIndexes);
+ this.columnNames = clone(columnNames);
+ this.statementBuilder = Objects.requireNonNull(statementBuilder, "statementBuilder");
+ this.statementType = statementType;
}
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param schema
- * The schema.
- * @param statementType
- * The SQL statement type, prepared or callable.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param schema The schema.
+ * @param statementType The SQL statement type, prepared or callable.
* @since 2.5.0
*/
public PStmtKey(final String sql, final String catalog, final String schema, final StatementType statementType) {
- this.sql = sql;
- this.catalog = catalog;
- this.schema = schema;
- this.statementType = statementType;
- this.autoGeneratedKeys = null;
- this.columnIndexes = null;
- this.columnNames = null;
- this.resultSetType = null;
- this.resultSetConcurrency = null;
- this.resultSetHoldability = null;
- // create builder
- if (statementType == StatementType.PREPARED_STATEMENT) {
- this.builder = new PreparedStatementSQL();
- } else if (statementType == StatementType.CALLABLE_STATEMENT) {
- this.builder = new PreparedCallSQL();
- }
+ this(sql, catalog, schema, null, null, null, null, null, null, statementType, k -> match(statementType, StatementSQL, CallSQL));
}
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param schema
- * The schema.
- * @param statementType
- * The SQL statement type, prepared or callable.
- * @param autoGeneratedKeys
- * 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>.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param schema The schema.
+ * @param statementType The SQL statement type, prepared or callable.
+ * @param autoGeneratedKeys A flag indicating whether auto-generated keys should be returned; one of
+ * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}.
* @since 2.5.0
*/
- public PStmtKey(final String sql, final String catalog, final String schema, final StatementType statementType,
- final Integer autoGeneratedKeys) {
- this.sql = sql;
- this.catalog = catalog;
- this.schema = schema;
- this.statementType = statementType;
- this.autoGeneratedKeys = autoGeneratedKeys;
- this.columnIndexes = null;
- this.columnNames = null;
- this.resultSetType = null;
- this.resultSetConcurrency = null;
- this.resultSetHoldability = null;
- // create builder
- if (statementType == StatementType.PREPARED_STATEMENT) {
- this.builder = new PreparedStatementWithAutoGeneratedKeys();
- } else if (statementType == StatementType.CALLABLE_STATEMENT) {
- this.builder = new PreparedCallSQL();
- }
+ public PStmtKey(final String sql, final String catalog, final String schema, final StatementType statementType, final Integer autoGeneratedKeys) {
+ this(sql, catalog, schema, null, null, null, autoGeneratedKeys, null, null, statementType,
+ k -> match(statementType, StatementAutoGeneratedKeys, CallSQL));
}
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param schema
- * The schema.
- * @param columnNames
- * An array of column names indicating the columns that should be returned from the inserted row or rows.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param schema The schema.
+ * @param columnNames An array of column names indicating the columns that should be returned from the inserted row or
+ * rows.
* @since 2.5.0
*/
public PStmtKey(final String sql, final String catalog, final String schema, final String[] columnNames) {
- this.sql = sql;
- this.catalog = catalog;
- this.schema = schema;
- this.statementType = StatementType.PREPARED_STATEMENT;
- this.autoGeneratedKeys = null;
- this.columnIndexes = null;
- this.columnNames = columnNames == null ? null : Arrays.copyOf(columnNames, columnNames.length);
- this.resultSetType = null;
- this.resultSetConcurrency = null;
- this.resultSetHoldability = null;
- // create builder
- builder = new PreparedStatementWithColumnNames();
+ this(sql, catalog, schema, null, null, null, null, null, columnNames, StatementType.PREPARED_STATEMENT, StatementColumnNames);
}
/**
* Constructs a key to uniquely identify a prepared statement.
*
- * @param sql
- * The SQL statement.
- * @param catalog
- * The catalog.
- * @param columnNames
- * An array of column names indicating the columns that should be returned from the inserted row or rows.
+ * @param sql The SQL statement.
+ * @param catalog The catalog.
+ * @param columnNames An array of column names indicating the columns that should be returned from the inserted row or
+ * rows.
* @deprecated Use {@link #PStmtKey(String, String, String, String[])}.
*/
@Deprecated
public PStmtKey(final String sql, final String catalog, final String[] columnNames) {
- this.sql = sql;
- this.catalog = catalog;
- this.schema = null;
- this.statementType = StatementType.PREPARED_STATEMENT;
- this.autoGeneratedKeys = null;
- this.columnIndexes = null;
- this.columnNames = columnNames == null ? null : Arrays.copyOf(columnNames, columnNames.length);
- this.resultSetType = null;
- this.resultSetConcurrency = null;
- this.resultSetHoldability = null;
- // create builder
- builder = new PreparedStatementWithColumnNames();
+ this(sql, catalog, null, null, null, null, null, null, columnNames, StatementType.PREPARED_STATEMENT, StatementColumnNames);
+ }
+
+ private int[] clone(final int[] array) {
+ return array == null ? null : array.clone();
+ }
+
+ private String[] clone(final String[] array) {
+ return array == null ? null : array.clone();
}
/**
* Creates a new Statement from the given Connection.
*
- * @param connection
- * The Connection to use to create the statement.
+ * @param connection The Connection to use to create the statement.
* @return The statement.
- * @throws SQLException
- * Thrown when there is a problem creating the statement.
+ * @throws SQLException Thrown when there is a problem creating the statement.
*/
public Statement createStatement(final Connection connection) throws SQLException {
- if (builder == null) {
- throw new IllegalStateException("Prepared statement key is invalid.");
- }
- return builder.createStatement(connection);
+ return statementBuilder.createStatement(connection, this);
}
@Override
@@ -828,8 +554,8 @@ public class PStmtKey {
}
/**
- * Gets 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>.
+ * Gets a flag indicating whether auto-generated keys should be returned; one of {@code Statement.RETURN_GENERATED_KEYS}
+ * or {@code Statement.NO_GENERATED_KEYS}.
*
* @return a flag indicating whether auto-generated keys should be returned.
*/
@@ -838,7 +564,7 @@ public class PStmtKey {
}
/**
- * The catalog.
+ * Gets the catalog.
*
* @return The catalog.
*/
@@ -852,7 +578,7 @@ public class PStmtKey {
* @return An array of column indexes.
*/
public int[] getColumnIndexes() {
- return columnIndexes == null ? null : columnIndexes.clone();
+ return clone(columnIndexes);
}
/**
@@ -861,12 +587,12 @@ public class PStmtKey {
* @return An array of column names.
*/
public String[] getColumnNames() {
- return columnNames == null ? null : columnNames.clone();
+ return clone(columnNames);
}
/**
- * Gets the result set concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * Gets the result set concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
*
* @return The result set concurrency type.
*/
@@ -875,8 +601,8 @@ public class PStmtKey {
}
/**
- * Gets the result set holdability, one of the following <code>ResultSet</code> constants:
- * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
+ * Gets the result set holdability, one of the following {@code ResultSet} constants:
+ * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}.
*
* @return The result set holdability.
*/
@@ -885,8 +611,8 @@ public class PStmtKey {
}
/**
- * Gets the result set type, one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+ * Gets the result set type, one of {@code ResultSet.TYPE_FORWARD_ONLY}, {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or
+ * {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
*
* @return the result set type.
*/
@@ -895,7 +621,7 @@ public class PStmtKey {
}
/**
- * The schema.
+ * Gets the schema.
*
* @return The catalog.
*/
@@ -913,7 +639,7 @@ public class PStmtKey {
}
/**
- * The SQL statement type.
+ * Gets the SQL statement type.
*
* @return The SQL statement type.
*/
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java
index 16e27a18c8..447aa22264 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java
@@ -18,10 +18,7 @@ package org.apache.tomcat.dbcp.dbcp2;
import java.sql.CallableStatement;
import java.sql.Connection;
-import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
@@ -67,7 +64,7 @@ public class PoolableCallableStatement extends DelegatingCallableStatement {
// Remove from trace now because this statement will be
// added by the activate method.
- removeThisTrace(getConnectionInternal());
+ removeThisTrace(connection);
}
/**
@@ -110,33 +107,7 @@ public class PoolableCallableStatement extends DelegatingCallableStatement {
*/
@Override
public void passivate() throws SQLException {
- setClosedInternal(true);
- removeThisTrace(getConnectionInternal());
-
- // The JDBC spec requires that a statement close any open
- // ResultSet's when it is closed.
- // FIXME The PreparedStatement we're wrapping should handle this for us.
- // See DBCP-10 for what could happen when ResultSets are closed twice.
- final List<AbandonedTrace> resultSetList = getTrace();
- if (resultSetList != null) {
- final List<Exception> thrownList = new ArrayList<>();
- final ResultSet[] resultSets = resultSetList.toArray(Utils.EMPTY_RESULT_SET_ARRAY);
- for (final ResultSet resultSet : resultSets) {
- if (resultSet != null) {
- try {
- resultSet.close();
- } catch (final Exception e) {
- thrownList.add(e);
- }
- }
- }
- clearTrace();
- if (!thrownList.isEmpty()) {
- throw new SQLExceptionList(thrownList);
- }
- }
-
- super.passivate();
+ prepareToReturn();
}
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java
index 52243c58c9..ee277db250 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java
@@ -46,7 +46,7 @@ public class PoolableConnection extends DelegatingConnection<Connection> impleme
static {
try {
MBEAN_SERVER = ManagementFactory.getPlatformMBeanServer();
- } catch (final NoClassDefFoundError | Exception ex) {
+ } catch (final NoClassDefFoundError | Exception ignored) {
// ignore - JMX not available
}
}
@@ -69,7 +69,7 @@ public class PoolableConnection extends DelegatingConnection<Connection> impleme
/**
* SQL_STATE codes considered to signal fatal conditions. Overrides the defaults in
- * {@link Utils#DISCONNECTION_SQL_CODES} (plus anything starting with {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}).
+ * {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}).
*/
private final Collection<String> disconnectionSqlCodes;
@@ -116,7 +116,7 @@ public class PoolableConnection extends DelegatingConnection<Connection> impleme
if (jmxObjectName != null) {
try {
MBEAN_SERVER.registerMBean(this, jmxObjectName);
- } catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
+ } catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException ignored) {
// For now, simply skip registration
}
}
@@ -155,7 +155,7 @@ public class PoolableConnection extends DelegatingConnection<Connection> impleme
// pool is closed, so close the connection
passivate();
getInnermostDelegate().close();
- } catch (final Exception ie) {
+ } catch (final Exception ignored) {
// DO NOTHING the original exception will be rethrown
}
throw new SQLException("Cannot close connection (isClosed check failed)", e);
@@ -246,7 +246,7 @@ public class PoolableConnection extends DelegatingConnection<Connection> impleme
* <p>
* If {@link #disconnectionSqlCodes} has been set, sql states are compared to those in the configured list of fatal
* exception codes. If this property is not set, codes are compared against the default codes in
- * {@link Utils#DISCONNECTION_SQL_CODES} and in this case anything starting with #{link
+ * {@link Utils#getDisconnectionSqlCodes()} and in this case anything starting with #{link
* Utils.DISCONNECTION_SQL_CODE_PREFIX} is considered a disconnection.
* </p>
*
@@ -258,7 +258,7 @@ public class PoolableConnection extends DelegatingConnection<Connection> impleme
final String sqlState = e.getSQLState();
if (sqlState != null) {
fatalException = disconnectionSqlCodes == null
- ? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX) || Utils.DISCONNECTION_SQL_CODES.contains(sqlState)
+ ? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX) || Utils.getDisconnectionSqlCodes().contains(sqlState)
: disconnectionSqlCodes.contains(sqlState);
}
return fatalException;
@@ -269,7 +269,7 @@ public class PoolableConnection extends DelegatingConnection<Connection> impleme
* <p>
* If {@link #disconnectionSqlCodes} has been set, sql states are compared to those in the
* configured list of fatal exception codes. If this property is not set, codes are compared against the default
- * codes in {@link Utils#DISCONNECTION_SQL_CODES} and in this case anything starting with #{link
+ * codes in {@link Utils#getDisconnectionSqlCodes()} and in this case anything starting with #{link
* Utils.DISCONNECTION_SQL_CODE_PREFIX} is considered a disconnection.
* </p>
*
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java
index f95c262f0a..b0c9ef9501 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java
@@ -20,11 +20,11 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Duration;
-import java.time.Instant;
import java.util.Collection;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
+import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.apache.juli.logging.Log;
@@ -110,7 +110,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
}
@Override
- public void activateObject(final PooledObject<PoolableConnection> p) throws Exception {
+ public void activateObject(final PooledObject<PoolableConnection> p) throws SQLException {
validateLifetime(p);
@@ -137,7 +137,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
}
@Override
- public void destroyObject(final PooledObject<PoolableConnection> p) throws Exception {
+ public void destroyObject(final PooledObject<PoolableConnection> p) throws SQLException {
p.getObject().reallyClose();
}
@@ -145,7 +145,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
* @since 2.9.0
*/
@Override
- public void destroyObject(final PooledObject<PoolableConnection> p, final DestroyMode mode) throws Exception {
+ public void destroyObject(final PooledObject<PoolableConnection> p, final DestroyMode mode) throws SQLException {
if (mode == DestroyMode.ABANDONED) {
p.getObject().getInnermostDelegate().abort(Runnable::run);
} else {
@@ -157,7 +157,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
* Gets the cache state.
*
* @return The cache state.
- * @since Made public in 2.6.0.
+ * @since 2.6.0.
*/
public boolean getCacheState() {
return cacheState;
@@ -167,7 +167,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
* Gets the connection factory.
*
* @return The connection factory.
- * @since Made public in 2.6.0.
+ * @since 2.6.0.
*/
public ConnectionFactory getConnectionFactory() {
return connectionFactory;
@@ -187,7 +187,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
/**
* @return The data source JMX ObjectName
- * @since Made public in 2.6.0.
+ * @since 2.6.0.
*/
public ObjectName getDataSourceJmxName() {
return dataSourceJmxObjectName;
@@ -273,7 +273,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
/**
* SQL_STATE codes considered to signal fatal conditions.
* <p>
- * Overrides the defaults in {@link Utils#DISCONNECTION_SQL_CODES} (plus anything starting with
+ * Overrides the defaults in {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with
* {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #isFastFailValidation()} is
* {@code true}, whenever connections created by this factory generate exceptions with SQL_STATE codes in this list,
* they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at isValid or
@@ -323,7 +323,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
}
/**
* @return Whether to pool statements.
- * @since Made public in 2.6.0.
+ * @since 2.6.0.
*/
public boolean getPoolStatements() {
return poolStatements;
@@ -363,11 +363,10 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
if (conn.isClosed()) {
throw new SQLException("initializeConnection: connection closed");
}
- if (null != sqls) {
- try (Statement stmt = conn.createStatement()) {
+ if (!Utils.isEmpty(sqls)) {
+ try (Statement statement = conn.createStatement()) {
for (final String sql : sqls) {
- Objects.requireNonNull(sql, "null connectionInitSqls element");
- stmt.execute(sql);
+ statement.execute(Objects.requireNonNull(sql, "null connectionInitSqls element"));
}
}
}
@@ -411,18 +410,18 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
}
@Override
- public PooledObject<PoolableConnection> makeObject() throws Exception {
+ public PooledObject<PoolableConnection> makeObject() throws SQLException {
Connection conn = connectionFactory.createConnection();
if (conn == null) {
throw new IllegalStateException("Connection factory returned null from createConnection");
}
try {
initializeConnection(conn);
- } catch (final SQLException sqle) {
+ } catch (final SQLException e) {
// Make sure the connection is closed
Utils.closeQuietly((AutoCloseable) conn);
// Rethrow original exception so it is visible to caller
- throw sqle;
+ throw e;
}
final long connIndex = connectionIndex.getAndIncrement();
@@ -445,8 +444,7 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
config.setJmxEnabled(false);
}
final PoolingConnection poolingConn = (PoolingConnection) conn;
- final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>(
- poolingConn, config);
+ final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>(poolingConn, config);
poolingConn.setStatementPool(stmtPool);
poolingConn.setClearStatementPoolOnReturn(clearStatementPoolOnReturn);
poolingConn.setCacheState(cacheState);
@@ -457,19 +455,23 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
if (dataSourceJmxObjectName == null) {
connJmxName = null;
} else {
- connJmxName = new ObjectName(
- dataSourceJmxObjectName.toString() + Constants.JMX_CONNECTION_BASE_EXT + connIndex);
+ final String name = dataSourceJmxObjectName.toString() + Constants.JMX_CONNECTION_BASE_EXT + connIndex;
+ try {
+ connJmxName = new ObjectName(name);
+ } catch (MalformedObjectNameException e) {
+ Utils.closeQuietly((AutoCloseable) conn);
+ throw new SQLException(name, e);
+ }
}
- final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, disconnectionSqlCodes,
- fastFailValidation);
+ final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, disconnectionSqlCodes, fastFailValidation);
pc.setCacheState(cacheState);
return new DefaultPooledObject<>(pc);
}
@Override
- public void passivateObject(final PooledObject<PoolableConnection> p) throws Exception {
+ public void passivateObject(final PooledObject<PoolableConnection> p) throws SQLException {
validateLifetime(p);
@@ -744,20 +746,14 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo
conn.validate(validationQuery, validationQueryTimeoutDuration);
}
- private void validateLifetime(final PooledObject<PoolableConnection> p) throws Exception {
- if (maxConnDuration.compareTo(Duration.ZERO) > 0) {
- final Duration lifetimeDuration = Duration.between(p.getCreateInstant(), Instant.now());
- if (lifetimeDuration.compareTo(maxConnDuration) > 0) {
- throw new LifetimeExceededException(Utils.getMessage("connectionFactory.lifetimeExceeded", lifetimeDuration, maxConnDuration));
- }
- }
+ private void validateLifetime(final PooledObject<PoolableConnection> p) throws LifetimeExceededException {
+ Utils.validateLifetime(p, maxConnDuration);
}
@Override
public boolean validateObject(final PooledObject<PoolableConnection> p) {
try {
validateLifetime(p);
-
validateConnection(p.getObject());
return true;
} catch (final Exception e) {
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionMXBean.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionMXBean.java
index 75db37ddd8..f72c565607 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionMXBean.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionMXBean.java
@@ -24,14 +24,13 @@ import java.sql.SQLException;
* @since 2.0
*/
public interface PoolableConnectionMXBean {
- // Methods
+
void clearCachedState();
void clearWarnings() throws SQLException;
void close() throws SQLException;
- // Read-write properties
boolean getAutoCommit() throws SQLException;
boolean getCacheState();
@@ -42,12 +41,10 @@ public interface PoolableConnectionMXBean {
String getSchema() throws SQLException;
- // SQLWarning getWarnings() throws SQLException;
String getToString();
int getTransactionIsolation() throws SQLException;
- // Read-only properties
boolean isClosed() throws SQLException;
boolean isReadOnly() throws SQLException;
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java
index 4cedf14dd8..1babf76d4d 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java
@@ -17,10 +17,7 @@
package org.apache.tomcat.dbcp.dbcp2;
import java.sql.PreparedStatement;
-import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
@@ -71,7 +68,7 @@ public class PoolablePreparedStatement<K> extends DelegatingPreparedStatement {
// Remove from trace now because this statement will be
// added by the activate method.
- removeThisTrace(getConnectionInternal());
+ removeThisTrace(conn);
}
@Override
@@ -125,32 +122,6 @@ public class PoolablePreparedStatement<K> extends DelegatingPreparedStatement {
if (batchAdded) {
clearBatch();
}
- setClosedInternal(true);
- removeThisTrace(getConnectionInternal());
-
- // The JDBC spec requires that a statement closes any open
- // ResultSet's when it is closed.
- // FIXME The PreparedStatement we're wrapping should handle this for us.
- // See bug 17301 for what could happen when ResultSets are closed twice.
- final List<AbandonedTrace> resultSetList = getTrace();
- if (resultSetList != null) {
- final List<Exception> thrownList = new ArrayList<>();
- final ResultSet[] resultSets = resultSetList.toArray(Utils.EMPTY_RESULT_SET_ARRAY);
- for (final ResultSet resultSet : resultSets) {
- if (resultSet != null) {
- try {
- resultSet.close();
- } catch (final Exception e) {
- thrownList.add(e);
- }
- }
- }
- clearTrace();
- if (!thrownList.isEmpty()) {
- throw new SQLExceptionList(thrownList);
- }
- }
-
- super.passivate();
+ prepareToReturn();
}
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java
index 6586a49dbd..b35e031833 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java
@@ -21,6 +21,7 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.NoSuchElementException;
+import java.util.Objects;
import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
import org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory;
@@ -62,7 +63,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
}
/** Pool of {@link PreparedStatement}s. and {@link CallableStatement}s */
- private KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pstmtPool;
+ private KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pStmtPool;
private boolean clearStatementPoolOnReturn;
@@ -86,7 +87,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
*/
@Override
public void activateObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject)
- throws Exception {
+ throws SQLException {
pooledObject.getObject().activate();
}
@@ -97,11 +98,11 @@ public class PoolingConnection extends DelegatingConnection<Connection>
@Override
public synchronized void close() throws SQLException {
try {
- if (null != pstmtPool) {
- final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> oldpool = pstmtPool;
- pstmtPool = null;
+ if (null != pStmtPool) {
+ final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> oldPool = pStmtPool;
+ pStmtPool = null;
try {
- oldpool.close();
+ oldPool.close();
} catch (final RuntimeException e) {
throw e;
} catch (final Exception e) {
@@ -120,14 +121,14 @@ public class PoolingConnection extends DelegatingConnection<Connection>
/**
* Notification from {@link PoolableConnection} that we returned to the pool.
*
- * @throws SQLException when <code>clearStatementPoolOnReturn</code> is true and the statement pool could not be
+ * @throws SQLException when {@code clearStatementPoolOnReturn} is true and the statement pool could not be
* cleared
* @since 2.8.0
*/
public void connectionReturnedToPool() throws SQLException {
- if (pstmtPool != null && clearStatementPoolOnReturn) {
+ if (pStmtPool != null && clearStatementPoolOnReturn) {
try {
- pstmtPool.clear();
+ pStmtPool.clear();
} catch (final Exception e) {
throw new SQLException("Error clearing statement pool", e);
}
@@ -153,7 +154,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
* the SQL string used to define the statement
* @param autoGeneratedKeys
* 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>.
+ * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}.
*
* @return the PStmtKey created for the given arguments.
*/
@@ -292,43 +293,39 @@ public class PoolingConnection extends DelegatingConnection<Connection>
*/
@Override
public void destroyObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject)
- throws Exception {
+ throws SQLException {
pooledObject.getObject().getInnermostDelegate().close();
}
private String getCatalogOrNull() {
- String catalog = null;
try {
- catalog = getCatalog();
- } catch (final SQLException e) {
- // Ignored
+ return getCatalog();
+ } catch (final SQLException ignored) {
+ return null;
}
- return catalog;
}
private String getSchemaOrNull() {
- String schema = null;
try {
- schema = getSchema();
- } catch (final SQLException e) {
- // Ignored
+ return getSchema();
+ } catch (final SQLException ignored) {
+ return null;
}
- return schema;
}
/**
- * Returns the prepared statement pool we're using.
+ * Gets the prepared statement pool.
*
* @return statement pool
* @since 2.8.0
*/
public KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> getStatementPool() {
- return pstmtPool;
+ return pStmtPool;
}
/**
* {@link KeyedPooledObjectFactory} method for creating {@link PoolablePreparedStatement}s or
- * {@link PoolableCallableStatement}s. The <code>stmtType</code> field in the key determines whether a
+ * {@link PoolableCallableStatement}s. The {@code stmtType} field in the key determines whether a
* PoolablePreparedStatement or PoolableCallableStatement is created.
*
* @param key
@@ -336,18 +333,18 @@ public class PoolingConnection extends DelegatingConnection<Connection>
* @see #createKey(String, int, int, StatementType)
*/
@Override
- public PooledObject<DelegatingPreparedStatement> makeObject(final PStmtKey key) throws Exception {
+ public PooledObject<DelegatingPreparedStatement> makeObject(final PStmtKey key) throws SQLException {
if (null == key) {
throw new IllegalArgumentException("Prepared statement key is null or invalid.");
}
if (key.getStmtType() == StatementType.PREPARED_STATEMENT) {
final PreparedStatement statement = (PreparedStatement) key.createStatement(getDelegate());
@SuppressWarnings({"rawtypes", "unchecked" }) // Unable to find way to avoid this
- final PoolablePreparedStatement pps = new PoolablePreparedStatement(statement, key, pstmtPool, this);
+ final PoolablePreparedStatement pps = new PoolablePreparedStatement(statement, key, pStmtPool, this);
return new DefaultPooledObject<>(pps);
}
final CallableStatement statement = (CallableStatement) key.createStatement(getDelegate());
- final PoolableCallableStatement pcs = new PoolableCallableStatement(statement, key, pstmtPool, this);
+ final PoolableCallableStatement pcs = new PoolableCallableStatement(statement, key, pStmtPool, this);
return new DefaultPooledObject<>(pcs);
}
@@ -373,7 +370,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
*/
@Override
public void passivateObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject)
- throws Exception {
+ throws SQLException {
final DelegatingPreparedStatement dps = pooledObject.getObject();
dps.clearParameters();
dps.passivate();
@@ -457,11 +454,11 @@ public class PoolingConnection extends DelegatingConnection<Connection>
* Wraps an underlying exception.
*/
private PreparedStatement prepareStatement(final PStmtKey key) throws SQLException {
- if (null == pstmtPool) {
+ if (null == pStmtPool) {
throw new SQLException("Statement pool is null - closed or invalid PoolingConnection.");
}
try {
- return pstmtPool.borrowObject(key);
+ return pStmtPool.borrowObject(key);
} catch (final NoSuchElementException e) {
throw new SQLException("MaxOpenPreparedStatements limit reached", e);
} catch (final RuntimeException e) {
@@ -492,7 +489,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
* the SQL string used to define the PreparedStatement
* @param autoGeneratedKeys
* 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>.
+ * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}.
* @return a {@link PoolablePreparedStatement}
* @throws SQLException
* Wraps an underlying exception.
@@ -594,15 +591,12 @@ public class PoolingConnection extends DelegatingConnection<Connection>
* the prepared statement pool.
*/
public void setStatementPool(final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pool) {
- pstmtPool = pool;
+ pStmtPool = pool;
}
@Override
public synchronized String toString() {
- if (pstmtPool != null) {
- return "PoolingConnection: " + pstmtPool.toString();
- }
- return "PoolingConnection: null";
+ return "PoolingConnection: " + Objects.toString(pStmtPool);
}
/**
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java b/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java
index 5f793f8fe1..9b4c878e6e 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java
@@ -79,8 +79,8 @@ public class PoolingDriver implements Driver {
static {
try {
DriverManager.registerDriver(new PoolingDriver());
- } catch (final Exception e) {
- // ignore
+ } catch (final Exception ignored) {
+ // Ignored
}
}
@@ -101,7 +101,7 @@ public class PoolingDriver implements Driver {
private final boolean accessToUnderlyingConnectionAllowed;
/**
- * Constructs a new driver with <code>accessToUnderlyingConnectionAllowed</code> enabled.
+ * Constructs a new driver with {@code accessToUnderlyingConnectionAllowed} enabled.
*/
public PoolingDriver() {
this(true);
@@ -215,7 +215,7 @@ public class PoolingDriver implements Driver {
* @param conn
* connection to invalidate
* @throws SQLException
- * if the connection is not a <code>PoolGuardConnectionWrapper</code> or an error occurs invalidating
+ * if the connection is not a {@code PoolGuardConnectionWrapper} or an error occurs invalidating
* the connection
*/
public void invalidateConnection(final Connection conn) throws SQLException {
@@ -227,8 +227,8 @@ public class PoolingDriver implements Driver {
final ObjectPool<Connection> pool = (ObjectPool<Connection>) pgconn.pool;
try {
pool.invalidateObject(pgconn.getDelegateInternal());
- } catch (final Exception e) {
- // Ignore.
+ } catch (final Exception ignored) {
+ // Ignored.
}
}
@@ -240,6 +240,7 @@ public class PoolingDriver implements Driver {
protected boolean isAccessToUnderlyingConnectionAllowed() {
return accessToUnderlyingConnectionAllowed;
}
+
@Override
public boolean jdbcCompliant() {
return true;
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/Utils.java b/java/org/apache/tomcat/dbcp/dbcp2/Utils.java
index d4c4aa79b2..7b44dcdcb0 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/Utils.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/Utils.java
@@ -21,10 +21,16 @@ import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.MessageFormat;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Collection;
import java.util.HashSet;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
+import java.util.function.Consumer;
+
+import org.apache.tomcat.dbcp.pool2.PooledObject;
/**
* Utility methods.
@@ -57,7 +63,9 @@ public final class Utils {
* <li>JZ0C0 (Sybase disconnect error)</li>
* <li>JZ0C1 (Sybase disconnect error)</li>
* </ul>
+ * @deprecated Use {@link #getDisconnectionSqlCodes()}.
*/
+ @Deprecated
public static final Set<String> DISCONNECTION_SQL_CODES;
static final ResultSet[] EMPTY_RESULT_SET_ARRAY = {};
@@ -101,21 +109,34 @@ public final class Utils {
}
/**
- * Closes the AutoCloseable (which may be null).
+ * Closes the given {@link AutoCloseable} and if an exception is caught, then calls {@code exceptionHandler}.
*
- * @param autoCloseable an AutoCloseable, may be {@code null}
- * @since 2.6.0
+ * @param autoCloseable The resource to close.
+ * @param exceptionHandler Consumes exception thrown closing this resource.
+ * @since 2.10.0
*/
- public static void closeQuietly(final AutoCloseable autoCloseable) {
+ public static void close(AutoCloseable autoCloseable, final Consumer<Exception> exceptionHandler) {
if (autoCloseable != null) {
try {
autoCloseable.close();
} catch (final Exception e) {
- // ignored
+ if (exceptionHandler != null) {
+ exceptionHandler.accept(e);
+ }
}
}
}
+ /**
+ * Closes the AutoCloseable (which may be null).
+ *
+ * @param autoCloseable an AutoCloseable, may be {@code null}
+ * @since 2.6.0
+ */
+ public static void closeQuietly(final AutoCloseable autoCloseable) {
+ close(autoCloseable, null);
+ }
+
/**
* Closes the Connection (which may be null).
*
@@ -149,6 +170,23 @@ public final class Utils {
closeQuietly((AutoCloseable) statement);
}
+ /**
+ * Gets a copy of SQL codes of fatal connection errors.
+ * <ul>
+ * <li>57P01 (Admin shutdown)</li>
+ * <li>57P02 (Crash shutdown)</li>
+ * <li>57P03 (Cannot connect now)</li>
+ * <li>01002 (SQL92 disconnect error)</li>
+ * <li>JZ0C0 (Sybase disconnect error)</li>
+ * <li>JZ0C1 (Sybase disconnect error)</li>
+ * </ul>
+ * @return SQL codes of fatal connection errors.
+ * @since 2.10.0
+ */
+ public static Set<String> getDisconnectionSqlCodes() {
+ return new HashSet<>(DISCONNECTION_SQL_CODES);
+ }
+
/**
* Gets the correct i18n message for the given key.
*
@@ -175,6 +213,10 @@ public final class Utils {
return mf.format(args, new StringBuffer(), null).toString();
}
+ static boolean isEmpty(final Collection<?> collection) {
+ return collection == null || collection.isEmpty();
+ }
+
static boolean isSecurityEnabled() {
return System.getSecurityManager() != null;
}
@@ -199,6 +241,15 @@ public final class Utils {
return value == null ? null : String.valueOf(value);
}
+ public static void validateLifetime(final PooledObject<?> p, final Duration maxDuration) throws LifetimeExceededException {
+ if (maxDuration.compareTo(Duration.ZERO) > 0) {
+ final Duration lifetimeDuration = Duration.between(p.getCreateInstant(), Instant.now());
+ if (lifetimeDuration.compareTo(maxDuration) > 0) {
+ throw new LifetimeExceededException(Utils.getMessage("connectionFactory.lifetimeExceeded", lifetimeDuration, maxDuration));
+ }
+ }
+ }
+
private Utils() {
// not instantiable
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java
index 9c820a3708..6b323dd6ec 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java
@@ -26,9 +26,9 @@ import org.apache.tomcat.dbcp.dbcp2.DelegatingConnection;
import org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement;
/**
- * This class is the <code>Connection</code> that will be returned from
- * <code>PooledConnectionImpl.getConnection()</code>. Most methods are wrappers around the JDBC 1.x
- * <code>Connection</code>. A few exceptions include preparedStatement and close. In accordance with the JDBC
+ * This class is the {@code Connection} that will be returned from
+ * {@code PooledConnectionImpl.getConnection()}. Most methods are wrappers around the JDBC 1.x
+ * {@code Connection}. A few exceptions include preparedStatement and close. In accordance with the JDBC
* specification this Connection cannot be used after closed() is called. Any further usage will result in an
* SQLException.
* <p>
@@ -37,7 +37,7 @@ import org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement;
*
* @since 2.0
*/
-class ConnectionImpl extends DelegatingConnection<Connection> {
+final class ConnectionImpl extends DelegatingConnection<Connection> {
private final boolean accessToUnderlyingConnectionAllowed;
@@ -45,7 +45,7 @@ class ConnectionImpl extends DelegatingConnection<Connection> {
private final PooledConnectionImpl pooledConnection;
/**
- * Creates a <code>ConnectionImpl</code>.
+ * Creates a {@code ConnectionImpl}.
*
* @param pooledConnection
* The PooledConnection that is calling the ctor.
@@ -122,14 +122,14 @@ class ConnectionImpl extends DelegatingConnection<Connection> {
}
/**
- * If pooling of <code>CallableStatement</code>s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
+ * If pooling of {@code CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
* be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}.
*
* @param sql
* an SQL statement that may contain one or more '?' parameter placeholders. Typically this statement is
* specified using JDBC call escape syntax.
- * @return a default <code>CallableStatement</code> object containing the pre-compiled SQL statement.
- * @exception SQLException
+ * @return a default {@code CallableStatement} object containing the pre-compiled SQL statement.
+ * @throws SQLException
* Thrown if a database access error occurs or this method is called on a closed connection.
* @since 2.4.0
*/
@@ -145,23 +145,23 @@ class ConnectionImpl extends DelegatingConnection<Connection> {
}
/**
- * If pooling of <code>CallableStatement</code>s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
+ * If pooling of {@code CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
* be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}.
*
* @param sql
- * a <code>String</code> object that is the SQL statement to be sent to the database; may contain on or
+ * a {@code String} object that is the SQL statement to be sent to the database; may contain on or
* more '?' parameters.
* @param resultSetType
- * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+ * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
* @param resultSetConcurrency
- * a concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
- * @return a <code>CallableStatement</code> object containing the pre-compiled SQL statement that will produce
- * <code>ResultSet</code> objects with the given type and concurrency.
+ * a concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
+ * @return a {@code CallableStatement} object containing the pre-compiled SQL statement that will produce
+ * {@code ResultSet} objects with the given type and concurrency.
* @throws SQLException
* Thrown if a database access error occurs, this method is called on a closed connection or the given
- * parameters are not <code>ResultSet</code> constants indicating type and concurrency.
+ * parameters are not {@code ResultSet} constants indicating type and concurrency.
* @since 2.4.0
*/
@Override
@@ -178,26 +178,26 @@ class ConnectionImpl extends DelegatingConnection<Connection> {
}
/**
- * If pooling of <code>CallableStatement</code>s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
+ * If pooling of {@code CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
* be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}.
*
* @param sql
- * a <code>String</code> object that is the SQL statement to be sent to the database; may contain on or
+ * a {@code String} object that is the SQL statement to be sent to the database; may contain on or
* more '?' parameters.
* @param resultSetType
- * one of the following <code>ResultSet</code> constants: <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+ * one of the following {@code ResultSet} constants: {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
* @param resultSetConcurrency
- * one of the following <code>ResultSet</code> constants: <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * one of the following {@code ResultSet} constants: {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
* @param resultSetHoldability
- * one of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
- * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
- * @return a new <code>CallableStatement</code> object, containing the pre-compiled SQL statement, that will
- * generate <code>ResultSet</code> objects with the given type, concurrency, and holdability.
+ * one of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT}
+ * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}.
+ * @return a new {@code CallableStatement} object, containing the pre-compiled SQL statement, that will
+ * generate {@code ResultSet} objects with the given type, concurrency, and holdability.
* @throws SQLException
* Thrown if a database access error occurs, this method is called on a closed connection or the given
- * parameters are not <code>ResultSet</code> constants indicating type, concurrency, and holdability.
+ * parameters are not {@code ResultSet} constants indicating type, concurrency, and holdability.
* @since 2.4.0
*/
@Override
@@ -214,7 +214,7 @@ class ConnectionImpl extends DelegatingConnection<Connection> {
}
/**
- * If pooling of <code>PreparedStatement</code>s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
+ * If pooling of {@code PreparedStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
* be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}.
*
* @param sql
@@ -246,7 +246,7 @@ class ConnectionImpl extends DelegatingConnection<Connection> {
}
/**
- * If pooling of <code>PreparedStatement</code>s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
+ * If pooling of {@code PreparedStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may
* be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}.
*
* @throws SQLException
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java
index ff50366fae..642ced624e 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java
@@ -37,7 +37,6 @@ import javax.naming.spi.ObjectFactory;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
-import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.apache.tomcat.dbcp.dbcp2.Constants;
import org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement;
import org.apache.tomcat.dbcp.dbcp2.PStmtKey;
@@ -50,29 +49,29 @@ import org.apache.tomcat.dbcp.pool2.impl.GenericKeyedObjectPoolConfig;
/**
* <p>
* An adapter for JDBC drivers that do not include an implementation of {@link javax.sql.ConnectionPoolDataSource}, but
- * still include a {@link java.sql.DriverManager} implementation. <code>ConnectionPoolDataSource</code>s are not used
- * within general applications. They are used by <code>DataSource</code> implementations that pool
- * <code>Connection</code>s, such as {@link org.apache.tomcat.dbcp.dbcp2.datasources.SharedPoolDataSource}. A J2EE container
- * will normally provide some method of initializing the <code>ConnectionPoolDataSource</code> whose attributes are
+ * still include a {@link java.sql.DriverManager} implementation. {@code ConnectionPoolDataSource}s are not used
+ * within general applications. They are used by {@code DataSource} implementations that pool
+ * {@code Connection}s, such as {@link org.apache.tomcat.dbcp.dbcp2.datasources.SharedPoolDataSource}. A J2EE container
+ * will normally provide some method of initializing the {@code ConnectionPoolDataSource} whose attributes are
* presented as bean getters/setters and then deploying it via JNDI. It is then available as a source of physical
- * connections to the database, when the pooling <code>DataSource</code> needs to create a new physical connection.
+ * connections to the database, when the pooling {@code DataSource} needs to create a new physical connection.
* </p>
* <p>
* Although normally used within a JNDI environment, the DriverAdapterCPDS can be instantiated and initialized as any
- * bean and then attached directly to a pooling <code>DataSource</code>. <code>Jdbc2PoolDataSource</code> can use the
- * <code>ConnectionPoolDataSource</code> with or without the use of JNDI.
+ * bean and then attached directly to a pooling {@code DataSource}. {@code Jdbc2PoolDataSource} can use the
+ * {@code ConnectionPoolDataSource} with or without the use of JNDI.
* </p>
* <p>
- * The DriverAdapterCPDS also provides <code>PreparedStatement</code> pooling which is not generally available in jdbc2
- * <code>ConnectionPoolDataSource</code> implementation, but is addressed within the jdbc3 specification. The
- * <code>PreparedStatement</code> pool in DriverAdapterCPDS has been in the dbcp package for some time, but it has not
+ * The DriverAdapterCPDS also provides {@code PreparedStatement} pooling which is not generally available in jdbc2
+ * {@code ConnectionPoolDataSource} implementation, but is addressed within the jdbc3 specification. The
+ * {@code PreparedStatement} pool in DriverAdapterCPDS has been in the dbcp package for some time, but it has not
* undergone extensive testing in the configuration used here. It should be considered experimental and can be toggled
* with the poolPreparedStatements attribute.
* </p>
* <p>
* The <a href="package-summary.html">package documentation</a> contains an example using catalina and JNDI. The
* <a href="../datasources/package-summary.html">datasources package documentation</a> shows how to use
- * <code>DriverAdapterCPDS</code> as a source for <code>Jdbc2PoolDataSource</code> without the use of JNDI.
+ * {@code DriverAdapterCPDS} as a source for {@code Jdbc2PoolDataSource} without the use of JNDI.
* </p>
*
* @since 2.0
@@ -92,8 +91,8 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
/** Description */
private String description;
- /** Url name */
- private String url;
+ /** Connection string */
+ private String connectionString;
/** User name */
private String userName;
@@ -273,7 +272,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 ClassNotFoundException {
// The spec says to return null if we can't create an instance
// of the reference
DriverAdapterCPDS cpds = null;
@@ -289,7 +288,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
if (isNotEmpty(ra)) {
setDriver(getStringContent(ra));
}
- ra = ref.get("url");
+ ra = ref.get("connectionString");
if (isNotEmpty(ra)) {
setUrl(getStringContent(ra));
}
@@ -363,7 +362,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
* @since 2.4.0
*/
public char[] getPasswordCharArray() {
- return userPassword == null ? null : userPassword.clone();
+ return Utils.clone(userPassword);
}
/**
@@ -450,7 +449,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
ref.add(new StringRefAddr("loginTimeout", String.valueOf(getLoginTimeout())));
ref.add(new StringRefAddr(Constants.KEY_PASSWORD, getPassword()));
ref.add(new StringRefAddr(Constants.KEY_USER, getUser()));
- ref.add(new StringRefAddr("url", getUrl()));
+ ref.add(new StringRefAddr("connectionString", getUrl()));
ref.add(new StringRefAddr("poolPreparedStatements", String.valueOf(isPoolPreparedStatements())));
ref.add(new StringRefAddr("maxIdle", String.valueOf(getMaxIdle())));
@@ -486,12 +485,12 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
}
/**
- * Gets the value of url used to locate the database for this datasource.
+ * Gets the value of connection string used to locate the database for this data source.
*
- * @return value of url.
+ * @return value of connection string.
*/
public String getUrl() {
- return url;
+ return connectionString;
}
/**
@@ -517,7 +516,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
}
/**
- * Whether to toggle the pooling of <code>PreparedStatement</code>s
+ * Whether to toggle the pooling of {@code PreparedStatement}s
*
* @return value of poolPreparedStatements.
*/
@@ -538,11 +537,11 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
/**
* Sets the connection properties passed to the JDBC driver.
* <p>
- * If <code>props</code> contains "user" and/or "password" properties, the corresponding instance properties are
+ * If {@code props} contains "user" and/or "password" properties, the corresponding instance properties are
* set. If these properties are not present, they are filled in using {@link #getUser()}, {@link #getPassword()}
* when {@link #getPooledConnection()} is called, or using the actual parameters to the method call when
* {@link #getPooledConnection(String, String)} is called. Calls to {@link #setUser(String)} or
- * {@link #setPassword(String)} overwrite the values of these properties if <code>connectionProperties</code> is not
+ * {@link #setPassword(String)} overwrite the values of these properties if {@code connectionProperties} is not
* null.
* </p>
*
@@ -675,7 +674,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
* Sets the number of statements to examine during each run of the idle object evictor thread (if any).
* <p>
* When a negative value is supplied,
- * <code>ceil({@link BasicDataSource#getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</code> tests will be run.
+ * {@code ceil({@link BasicDataSource#getNumIdle})/abs({@link #getNumTestsPerEvictionRun})} tests will be run.
* I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the idle objects will be tested per run.
* </p>
*
@@ -714,7 +713,7 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
}
/**
- * Whether to toggle the pooling of <code>PreparedStatement</code>s
+ * Whether to toggle the pooling of {@code PreparedStatement}s
*
* @param poolPreparedStatements true to pool statements.
* @throws IllegalStateException if {@link #getPooledConnection()} has been called
@@ -741,14 +740,14 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
}
/**
- * Sets the value of URL string used to locate the database for this datasource.
+ * Sets the value of URL string used to locate the database for this data source.
*
- * @param url Value to assign to url.
+ * @param connectionString Value to assign to connection string.
* @throws IllegalStateException if {@link #getPooledConnection()} has been called
*/
- public void setUrl(final String url) {
+ public void setUrl(final String connectionString) {
assertInitializationAllowed();
- this.url = url;
+ this.connectionString = connectionString;
}
/**
@@ -773,10 +772,10 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
final StringBuilder builder = new StringBuilder(super.toString());
builder.append("[description=");
builder.append(description);
- builder.append(", url=");
+ builder.append(", connectionString=");
// 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(connectionString);
builder.append(", driver=");
builder.append(driver);
builder.append(", loginTimeout=");
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java
index 083f3ba2eb..68e871ea14 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java
@@ -44,7 +44,7 @@ public class PStmtKeyCPDS extends PStmtKey {
* The SQL statement.
* @param autoGeneratedKeys
* 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>.
+ * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}.
*/
public PStmtKeyCPDS(final String sql, final int autoGeneratedKeys) {
super(sql, null, autoGeneratedKeys);
@@ -56,11 +56,11 @@ public class PStmtKeyCPDS extends PStmtKey {
* @param sql
* The SQL statement.
* @param resultSetType
- * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+ * A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
* @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
*/
public PStmtKeyCPDS(final String sql, final int resultSetType, final int resultSetConcurrency) {
super(sql, resultSetType, resultSetConcurrency);
@@ -72,14 +72,14 @@ public class PStmtKeyCPDS extends PStmtKey {
* @param sql
* The SQL statement.
* @param resultSetType
- * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+ * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
* @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>
+ * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}
* @param resultSetHoldability
- * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
- * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
+ * One of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT}
+ * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}.
*/
public PStmtKeyCPDS(final String sql, final int resultSetType, final int resultSetConcurrency,
final int resultSetHoldability) {
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java
index 60dcc758c3..c247cfd4cc 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java
@@ -36,17 +36,18 @@ import org.apache.tomcat.dbcp.dbcp2.PStmtKey;
import org.apache.tomcat.dbcp.dbcp2.PoolableCallableStatement;
import org.apache.tomcat.dbcp.dbcp2.PoolablePreparedStatement;
import org.apache.tomcat.dbcp.dbcp2.PoolingConnection.StatementType;
+import org.apache.tomcat.dbcp.dbcp2.Utils;
import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
import org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory;
import org.apache.tomcat.dbcp.pool2.PooledObject;
import org.apache.tomcat.dbcp.pool2.impl.DefaultPooledObject;
/**
- * Implementation of PooledConnection that is returned by PooledConnectionDataSource.
+ * Implementation of {@link PooledConnection} that is returned by {@link DriverAdapterCPDS}.
*
* @since 2.0
*/
-class PooledConnectionImpl
+final class PooledConnectionImpl
implements PooledConnection, KeyedPooledObjectFactory<PStmtKey, DelegatingPreparedStatement> {
private static final String CLOSED = "Attempted to use PooledConnection after closed() was called.";
@@ -113,7 +114,7 @@ class PooledConnectionImpl
*/
@Override
public void activateObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject)
- throws Exception {
+ throws SQLException {
pooledObject.getObject().activate();
}
@@ -145,8 +146,8 @@ class PooledConnectionImpl
}
/**
- * Closes the physical connection and marks this <code>PooledConnection</code> so that it may not be used to
- * generate any more logical <code>Connection</code>s.
+ * Closes the physical connection and marks this {@code PooledConnection} so that it may not be used to
+ * generate any more logical {@code Connection}s.
*
* @throws SQLException
* Thrown when an error occurs or the connection is already closed.
@@ -184,7 +185,7 @@ class PooledConnectionImpl
* @return a {@link PStmtKey} for the given arguments.
*/
protected PStmtKey createKey(final String sql) {
- return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull());
+ return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull());
}
/**
@@ -194,11 +195,11 @@ class PooledConnectionImpl
* The SQL statement.
* @param autoGeneratedKeys
* 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>.
+ * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}.
* @return a key to uniquely identify a prepared statement.
*/
protected PStmtKey createKey(final String sql, final int autoGeneratedKeys) {
- return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), autoGeneratedKeys);
+ return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), autoGeneratedKeys);
}
/**
@@ -207,16 +208,15 @@ class PooledConnectionImpl
* @param sql
* The SQL statement.
* @param resultSetType
- * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+ * A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
* @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
* @return a key to uniquely identify a prepared statement.
*/
protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency) {
- return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType,
- resultSetConcurrency);
+ return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency);
}
/**
@@ -225,20 +225,18 @@ class PooledConnectionImpl
* @param sql
* The SQL statement.
* @param resultSetType
- * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+ * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
* @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>
+ * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}
* @param resultSetHoldability
- * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
- * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
+ * One of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT}
+ * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}.
* @return a key to uniquely identify a prepared statement.
*/
- protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency,
- final int resultSetHoldability) {
- return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType,
- resultSetConcurrency, resultSetHoldability);
+ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) {
+ return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency, resultSetHoldability);
}
/**
@@ -247,23 +245,22 @@ class PooledConnectionImpl
* @param sql
* The SQL statement.
* @param resultSetType
- * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
+ * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}
* @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
* @param resultSetHoldability
- * One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
- * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
+ * One of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT}
+ * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}.
* @param statementType
* The SQL statement type, prepared or callable.
* @return a key to uniquely identify a prepared statement.
* @since 2.4.0
*/
- protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency,
- final int resultSetHoldability, final StatementType statementType) {
- return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType,
- resultSetConcurrency, resultSetHoldability, statementType);
+ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability,
+ final StatementType statementType) {
+ return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency, resultSetHoldability, statementType);
}
/**
@@ -272,20 +269,18 @@ class PooledConnectionImpl
* @param sql
* The SQL statement.
* @param resultSetType
- * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+ * A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
* @param resultSetConcurrency
- * A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
* @param statementType
* The SQL statement type, prepared or callable.
* @return a key to uniquely identify a prepared statement.
* @since 2.4.0
*/
- protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency,
- final StatementType statementType) {
- return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType,
- resultSetConcurrency, statementType);
+ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency, final StatementType statementType) {
+ return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency, statementType);
}
/**
@@ -299,7 +294,7 @@ class PooledConnectionImpl
* @return a key to uniquely identify a prepared statement.
*/
protected PStmtKey createKey(final String sql, final int[] columnIndexes) {
- return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), columnIndexes);
+ return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), columnIndexes);
}
/**
@@ -312,7 +307,7 @@ class PooledConnectionImpl
* @return a key to uniquely identify a prepared statement.
*/
protected PStmtKey createKey(final String sql, final StatementType statementType) {
- return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), statementType);
+ return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), statementType);
}
/**
@@ -325,7 +320,7 @@ class PooledConnectionImpl
* @return a key to uniquely identify a prepared statement.
*/
protected PStmtKey createKey(final String sql, final String[] columnNames) {
- return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), columnNames);
+ return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), columnNames);
}
/**
@@ -338,7 +333,7 @@ class PooledConnectionImpl
*/
@Override
public void destroyObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject)
- throws Exception {
+ throws SQLException {
pooledObject.getObject().getInnermostDelegate().close();
}
@@ -349,12 +344,7 @@ class PooledConnectionImpl
protected void finalize() throws Throwable {
// Closing the Connection ensures that if anyone tries to use it,
// an error will occur.
- try {
- connection.close();
- } catch (final Exception ignored) {
- // ignore
- }
-
+ Utils.close(connection, null);
// make sure the last connection is marked as closed
if (logicalConnection != null && !logicalConnection.isClosed()) {
throw new SQLException("PooledConnection was gc'ed, without its last Connection being closed.");
@@ -415,7 +405,7 @@ class PooledConnectionImpl
* The key for the {@link PreparedStatement} to be created.
*/
@Override
- public PooledObject<DelegatingPreparedStatement> makeObject(final PStmtKey key) throws Exception {
+ public PooledObject<DelegatingPreparedStatement> makeObject(final PStmtKey key) throws SQLException {
if (null == key) {
throw new IllegalArgumentException("Prepared statement key is null or invalid.");
}
@@ -433,25 +423,12 @@ class PooledConnectionImpl
return new DefaultPooledObject<>(pcs);
}
- /**
- * Normalizes the given SQL statement, producing a canonical form that is semantically equivalent to the original.
- * @param sql
- * The SQL statement.
- * @return the normalized SQL statement.
- */
- protected String normalizeSQL(final String sql) {
- return sql.trim();
- }
-
/**
* Sends a connectionClosed event.
*/
void notifyListeners() {
final ConnectionEvent event = new ConnectionEvent(this);
- final Object[] listeners = eventListeners.toArray();
- for (final Object listener : listeners) {
- ((ConnectionEventListener) listener).connectionClosed(event);
- }
+ new ArrayList<>(eventListeners).forEach(listener -> listener.connectionClosed(event));
}
/**
@@ -465,7 +442,7 @@ class PooledConnectionImpl
*/
@Override
public void passivateObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject)
- throws Exception {
+ throws SQLException {
final DelegatingPreparedStatement dps = pooledObject.getObject();
dps.clearParameters();
dps.passivate();
@@ -477,8 +454,8 @@ class PooledConnectionImpl
* @param sql
* an SQL statement that may contain one or more '?' parameter placeholders. Typically this statement is
* specified using JDBC call escape syntax.
- * @return a default <code>CallableStatement</code> object containing the pre-compiled SQL statement.
- * @exception SQLException
+ * @return a default {@code CallableStatement} object containing the pre-compiled SQL statement.
+ * @throws SQLException
* Thrown if a database access error occurs or this method is called on a closed connection.
* @since 2.4.0
*/
@@ -499,19 +476,19 @@ class PooledConnectionImpl
* Creates or obtains a {@link CallableStatement} from my pool.
*
* @param sql
- * a <code>String</code> object that is the SQL statement to be sent to the database; may contain on or
+ * a {@code String} object that is the SQL statement to be sent to the database; may contain on or
* more '?' parameters.
* @param resultSetType
- * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+ * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
* @param resultSetConcurrency
- * a concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
- * @return a <code>CallableStatement</code> object containing the pre-compiled SQL statement that will produce
- * <code>ResultSet</code> objects with the given type and concurrency.
+ * a concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
+ * @return a {@code CallableStatement} object containing the pre-compiled SQL statement that will produce
+ * {@code ResultSet} objects with the given type and concurrency.
* @throws SQLException
* Thrown if a database access error occurs, this method is called on a closed connection or the given
- * parameters are not <code>ResultSet</code> constants indicating type and concurrency.
+ * parameters are not {@code ResultSet} constants indicating type and concurrency.
* @since 2.4.0
*/
CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency)
@@ -533,22 +510,22 @@ class PooledConnectionImpl
* Creates or obtains a {@link CallableStatement} from my pool.
*
* @param sql
- * a <code>String</code> object that is the SQL statement to be sent to the database; may contain on or
+ * a {@code String} object that is the SQL statement to be sent to the database; may contain on or
* more '?' parameters.
* @param resultSetType
- * one of the following <code>ResultSet</code> constants: <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+ * one of the following {@code ResultSet} constants: {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
* @param resultSetConcurrency
- * one of the following <code>ResultSet</code> constants: <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * one of the following {@code ResultSet} constants: {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
* @param resultSetHoldability
- * one of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
- * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
- * @return a new <code>CallableStatement</code> object, containing the pre-compiled SQL statement, that will
- * generate <code>ResultSet</code> objects with the given type, concurrency, and holdability.
+ * one of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT}
+ * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}.
+ * @return a new {@code CallableStatement} object, containing the pre-compiled SQL statement, that will
+ * generate {@code ResultSet} objects with the given type, concurrency, and holdability.
* @throws SQLException
* Thrown if a database access error occurs, this method is called on a closed connection or the given
- * parameters are not <code>ResultSet</code> constants indicating type, concurrency, and holdability.
+ * parameters are not {@code ResultSet} constants indicating type, concurrency, and holdability.
* @since 2.4.0
*/
CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency,
@@ -594,7 +571,7 @@ class PooledConnectionImpl
* an SQL statement that may contain one or more '?' IN parameter placeholders.
* @param autoGeneratedKeys
* 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>.
+ * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}.
* @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.
@@ -617,14 +594,14 @@ class PooledConnectionImpl
* Creates or obtains a {@link PreparedStatement} from my pool.
*
* @param sql
- * a <code>String</code> object that is the SQL statement to be sent to the database; may contain one or
+ * a {@code String} object that is the SQL statement to be sent to the database; may contain one or
* more '?' IN parameters.
* @param resultSetType
- * a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
- * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+ * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}.
* @param resultSetConcurrency
- * a concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
- * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * a concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or
+ * {@code ResultSet.CONCUR_UPDATABLE}.
*
* @return a {@link PoolablePreparedStatement}.
* @throws SQLException Thrown if a database access error occurs, this method is called on a closed connection, or
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/package-info.java b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/package-info.java
index c36512bdca..e5496f3bfd 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/package-info.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/package-info.java
@@ -18,8 +18,8 @@
/**
* <p>
* This package contains one public class which is a
- * <code>ConnectionPoolDataSource</code> (CPDS) implementation that can be used to
- * adapt older <code>Driver</code> based JDBC implementations. Below is an
+ * {@code ConnectionPoolDataSource} (CPDS) implementation that can be used to
+ * adapt older {@code Driver} based JDBC implementations. Below is an
* example of setting up the CPDS to be available via JNDI in the
* catalina servlet container.
* </p>
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java
index 7ee9031fd2..ec67369a94 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java
@@ -21,7 +21,6 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Duration;
-import java.time.Instant;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -43,7 +42,7 @@ import org.apache.tomcat.dbcp.pool2.impl.DefaultPooledObject;
*
* @since 2.0
*/
-class CPDSConnectionFactory
+final class CPDSConnectionFactory
implements PooledObjectFactory<PooledConnectionAndInfo>, ConnectionEventListener, PooledConnectionManager {
private static final String NO_KEY_MESSAGE = "close() was called on a Connection, but I have no record of the underlying PooledConnection.";
@@ -176,7 +175,7 @@ class CPDSConnectionFactory
}
@Override
- public void activateObject(final PooledObject<PooledConnectionAndInfo> p) throws Exception {
+ public void activateObject(final PooledObject<PooledConnectionAndInfo> p) throws SQLException {
validateLifetime(p);
}
@@ -256,11 +255,11 @@ class CPDSConnectionFactory
* Closes the PooledConnection and stops listening for events from it.
*/
@Override
- public void destroyObject(final PooledObject<PooledConnectionAndInfo> p) throws Exception {
+ public void destroyObject(final PooledObject<PooledConnectionAndInfo> p) throws SQLException {
doDestroyObject(p.getObject());
}
- private void doDestroyObject(final PooledConnectionAndInfo pci) throws Exception {
+ private void doDestroyObject(final PooledConnectionAndInfo pci) throws SQLException {
final PooledConnection pc = pci.getPooledConnection();
pc.removeConnectionEventListener(this);
pcMap.remove(pc);
@@ -304,13 +303,8 @@ class CPDSConnectionFactory
}
}
- // ***********************************************************************
- // java.sql.ConnectionEventListener implementation
- // ***********************************************************************
-
@Override
public synchronized PooledObject<PooledConnectionAndInfo> makeObject() {
- final PooledConnectionAndInfo pci;
try {
PooledConnection pc = null;
if (userPassKey.getUserName() == null) {
@@ -318,24 +312,22 @@ class CPDSConnectionFactory
} else {
pc = cpds.getPooledConnection(userPassKey.getUserName(), userPassKey.getPassword());
}
-
if (pc == null) {
throw new IllegalStateException("Connection pool data source returned null from getPooledConnection");
}
-
// should we add this object as a listener or the pool.
// consider the validateObject method in decision
pc.addConnectionEventListener(this);
- pci = new PooledConnectionAndInfo(pc, userPassKey);
+ final PooledConnectionAndInfo pci = new PooledConnectionAndInfo(pc, userPassKey);
pcMap.put(pc, pci);
+ return new DefaultPooledObject<>(pci);
} catch (final SQLException e) {
throw new RuntimeException(e.getMessage());
}
- return new DefaultPooledObject<>(pci);
}
@Override
- public void passivateObject(final PooledObject<PooledConnectionAndInfo> p) throws Exception {
+ public void passivateObject(final PooledObject<PooledConnectionAndInfo> p) throws SQLException {
validateLifetime(p);
}
@@ -434,13 +426,8 @@ class CPDSConnectionFactory
return builder.toString();
}
- private void validateLifetime(final PooledObject<PooledConnectionAndInfo> pooledObject) throws Exception {
- if (maxConnDuration.compareTo(Duration.ZERO) > 0) {
- final Duration lifetimeDuration = Duration.between(pooledObject.getCreateInstant(), Instant.now());
- if (lifetimeDuration.compareTo(maxConnDuration) > 0) {
- throw new Exception(Utils.getMessage("connectionFactory.lifetimeExceeded", lifetimeDuration, maxConnDuration));
- }
- }
+ private void validateLifetime(final PooledObject<PooledConnectionAndInfo> p) throws SQLException {
+ Utils.validateLifetime(p, maxConnDuration);
}
@Override
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/CharArray.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/CharArray.java
index 58b4d9a2de..e257bda71a 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/CharArray.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/CharArray.java
@@ -17,6 +17,7 @@
package org.apache.tomcat.dbcp.dbcp2.datasources;
+import java.io.Serializable;
import java.util.Arrays;
import org.apache.tomcat.dbcp.dbcp2.Utils;
@@ -29,7 +30,9 @@ import org.apache.tomcat.dbcp.dbcp2.Utils;
*
* @since 2.9.0
*/
-final class CharArray {
+final class CharArray implements Serializable {
+
+ private static final long serialVersionUID = 1L;
static final CharArray NULL = new CharArray((char[]) null);
@@ -70,7 +73,7 @@ final class CharArray {
* @return value, may be null.
*/
char[] get() {
- return chars == null ? null : chars.clone();
+ return Utils.clone(chars);
}
@Override
@@ -78,11 +81,4 @@ final class CharArray {
return Arrays.hashCode(chars);
}
- /**
- * Calls {@code super.toString()} and does not reveal its contents inadvertently.
- */
- @Override
- public String toString() {
- return super.toString();
- }
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java
index 43cd8ba601..2fbfb18a24 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java
@@ -34,36 +34,37 @@ import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import javax.sql.PooledConnection;
+import org.apache.tomcat.dbcp.dbcp2.Utils;
import org.apache.tomcat.dbcp.pool2.impl.BaseObjectPoolConfig;
import org.apache.tomcat.dbcp.pool2.impl.GenericKeyedObjectPoolConfig;
import org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool;
/**
* <p>
- * The base class for <code>SharedPoolDataSource</code> and <code>PerUserPoolDataSource</code>. Many of the
+ * The base class for {@code SharedPoolDataSource} and {@code PerUserPoolDataSource}. Many of the
* configuration properties are shared and defined here. This class is declared public in order to allow particular
* usage with commons-beanutils; do not make direct use of it outside of <em>commons-dbcp2</em>.
* </p>
*
* <p>
- * A J2EE container will normally provide some method of initializing the <code>DataSource</code> whose attributes are
+ * A J2EE container will normally provide some method of initializing the {@code DataSource} whose attributes are
* presented as bean getters/setters and then deploying it via JNDI. It is then available to an application as a source
* of pooled logical connections to the database. The pool needs a source of physical connections. This source is in the
- * form of a <code>ConnectionPoolDataSource</code> that can be specified via the {@link #setDataSourceName(String)} used
+ * form of a {@code ConnectionPoolDataSource} that can be specified via the {@link #setDataSourceName(String)} used
* to lookup the source via JNDI.
* </p>
*
* <p>
* Although normally used within a JNDI environment, A DataSource can be instantiated and initialized as any bean. In
- * this case the <code>ConnectionPoolDataSource</code> will likely be instantiated in a similar manner. This class
+ * this case the {@code ConnectionPoolDataSource} will likely be instantiated in a similar manner. This class
* allows the physical source of connections to be attached directly to this pool using the
* {@link #setConnectionPoolDataSource(ConnectionPoolDataSource)} method.
* </p>
*
* <p>
* The dbcp package contains an adapter, {@link org.apache.tomcat.dbcp.dbcp2.cpdsadapter.DriverAdapterCPDS}, that can be
- * used to allow the use of <code>DataSource</code>'s based on this class with JDBC driver implementations that do not
- * supply a <code>ConnectionPoolDataSource</code>, but still provide a {@link java.sql.Driver} implementation.
+ * used to allow the use of {@code DataSource}'s based on this class with JDBC driver implementations that do not
+ * supply a {@code ConnectionPoolDataSource}, but still provide a {@link java.sql.Driver} implementation.
* </p>
*
* <p>
@@ -159,7 +160,7 @@ public abstract class InstanceKeyDataSource implements DataSource, Referenceable
* Closes the connection pool being maintained by this datasource.
*/
@Override
- public abstract void close() throws Exception;
+ public abstract void close() throws SQLException;
private void closeDueToException(final PooledConnectionAndInfo info) {
if (info != null) {
@@ -185,13 +186,13 @@ public abstract class InstanceKeyDataSource implements DataSource, Referenceable
/**
* Attempts to retrieve a database connection using {@link #getPooledConnectionAndInfo(String, String)} with the
* provided user name and password. The password on the {@code PooledConnectionAndInfo} instance returned by
- * <code>getPooledConnectionAndInfo</code> is compared to the <code>password</code> parameter. If the comparison
+ * {@code getPooledConnectionAndInfo} is compared to the {@code password} parameter. If the comparison
* fails, a database connection using the supplied user name and password is attempted. If the connection attempt
* fails, an SQLException is thrown, indicating that the given password did not match the password used to create
* the pooled connection. If the connection attempt succeeds, this means that the database password has been
- * changed. In this case, the <code>PooledConnectionAndInfo</code> instance retrieved with the old password is
- * destroyed and the <code>getPooledConnectionAndInfo</code> is repeatedly invoked until a
- * <code>PooledConnectionAndInfo</code> instance with the new password is returned.
+ * changed. In this case, the {@code PooledConnectionAndInfo} instance retrieved with the old password is
+ * destroyed and the {@code getPooledConnectionAndInfo} is repeatedly invoked until a
+ * {@code PooledConnectionAndInfo} instance with the new password is returned.
*/
@Override
public Connection getConnection(final String userName, final String userPassword) throws SQLException {
@@ -263,11 +264,7 @@ public abstract class InstanceKeyDataSource implements DataSource, Referenceable
connection.clearWarnings();
return connection;
} catch (final SQLException ex) {
- try {
- connection.close();
- } catch (final Exception exc) {
- getLogWriter().println("ignoring exception during close: " + exc);
- }
+ Utils.close(connection, e -> getLogWriter().println("ignoring exception during close: " + e));
throw ex;
}
}
@@ -668,7 +665,7 @@ public abstract class InstanceKeyDataSource implements DataSource, Referenceable
/**
* Gets the value of defaultAutoCommit, which defines the state of connections handed out from this pool. The value
- * can be changed on the Connection using Connection.setAutoCommit(boolean). The default is <code>null</code> which
+ * can be changed on the Connection using Connection.setAutoCommit(boolean). The default is {@code null} which
* will use the default value for the drive.
*
* @return value of defaultAutoCommit.
@@ -679,7 +676,7 @@ public abstract class InstanceKeyDataSource implements DataSource, Referenceable
/**
* Gets the value of defaultReadOnly, which defines the state of connections handed out from this pool. The value
- * can be changed on the Connection using Connection.setReadOnly(boolean). The default is <code>null</code> which
+ * can be changed on the Connection using Connection.setReadOnly(boolean). The default is {@code null} which
* will use the default value for the drive.
*
* @return value of defaultReadOnly.
@@ -744,7 +741,7 @@ public abstract class InstanceKeyDataSource implements DataSource, Referenceable
/**
* Sets the value of defaultAutoCommit, which defines the state of connections handed out from this pool. The value
- * can be changed on the Connection using Connection.setAutoCommit(boolean). The default is <code>null</code> which
+ * can be changed on the Connection using Connection.setAutoCommit(boolean). The default is {@code null} which
* will use the default value for the drive.
*
* @param defaultAutoCommit
@@ -904,7 +901,7 @@ public abstract class InstanceKeyDataSource implements DataSource, Referenceable
/**
* Sets the value of defaultReadOnly, which defines the state of connections handed out from this pool. The value
- * can be changed on the Connection using Connection.setReadOnly(boolean). The default is <code>null</code> which
+ * can be changed on the Connection using Connection.setReadOnly(boolean). The default is {@code null} which
* will use the default value for the drive.
*
* @param defaultReadOnly
@@ -1236,7 +1233,7 @@ public abstract class InstanceKeyDataSource implements DataSource, Referenceable
if (conn != null) {
try {
conn.close();
- } catch (final SQLException e) {
+ } catch (final SQLException ignored) {
// at least we could connect
}
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java
index ad01b8abb1..325fad1b78 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java
@@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
@@ -38,7 +37,7 @@ import org.apache.tomcat.dbcp.dbcp2.ListException;
import org.apache.tomcat.dbcp.dbcp2.Utils;
/**
- * A JNDI ObjectFactory which creates <code>SharedPoolDataSource</code>s or <code>PerUserPoolDataSource</code>s
+ * A JNDI ObjectFactory which creates {@code SharedPoolDataSource}s or {@code PerUserPoolDataSource}s
*
* @since 2.0
*/
@@ -49,29 +48,22 @@ abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
/**
* Closes all pools associated with this class.
*
- * @throws Exception
+ * @throws ListException
* a {@link ListException} containing all exceptions thrown by {@link InstanceKeyDataSource#close()}
* @see InstanceKeyDataSource#close()
- * @see ListException
* @since 2.4.0 throws a {@link ListException} instead of, in 2.3.0 and before, the first exception thrown by
* {@link InstanceKeyDataSource#close()}.
*/
- public static void closeAll() throws Exception {
+ public static void closeAll() throws ListException {
// Get iterator to loop over all instances of this data source.
final List<Throwable> exceptionList = new ArrayList<>(INSTANCE_MAP.size());
- for (final Entry<String, InstanceKeyDataSource> next : INSTANCE_MAP.entrySet()) {
+ INSTANCE_MAP.entrySet().forEach(entry -> {
// Bullet-proof to avoid anything else but problems from InstanceKeyDataSource#close().
- if (next != null) {
- final InstanceKeyDataSource value = next.getValue();
- if (value != null) {
- try {
- value.close();
- } catch (final Exception e) {
- exceptionList.add(e);
- }
- }
+ if (entry != null) {
+ final InstanceKeyDataSource value = entry.getValue();
+ Utils.close(value, exceptionList::add);
}
- }
+ });
INSTANCE_MAP.clear();
if (!exceptionList.isEmpty()) {
throw new ListException("Could not close all InstanceKeyDataSource instances.", exceptionList);
@@ -107,7 +99,7 @@ abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
if (s != null) {
try {
max = Math.max(max, Integer.parseInt(s));
- } catch (final NumberFormatException e) {
+ } catch (final NumberFormatException ignored) {
// no sweat, ignore those keys
}
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java
index 10595ff52d..a67d4a4dd8 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java
@@ -21,7 +21,6 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Duration;
-import java.time.Instant;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -44,7 +43,7 @@ import org.apache.tomcat.dbcp.pool2.impl.DefaultPooledObject;
*
* @since 2.0
*/
-class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey, PooledConnectionAndInfo>,
+final class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey, PooledConnectionAndInfo>,
ConnectionEventListener, PooledConnectionManager {
private static final String NO_KEY_MESSAGE = "close() was called on a Connection, but "
@@ -112,7 +111,7 @@ class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey
}
@Override
- public void activateObject(final UserPassKey key, final PooledObject<PooledConnectionAndInfo> p) throws Exception {
+ public void activateObject(final UserPassKey key, final PooledObject<PooledConnectionAndInfo> p) throws SQLException {
validateLifetime(p);
}
@@ -187,7 +186,7 @@ class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey
* Closes the PooledConnection and stops listening for events from it.
*/
@Override
- public void destroyObject(final UserPassKey key, final PooledObject<PooledConnectionAndInfo> p) throws Exception {
+ public void destroyObject(final UserPassKey key, final PooledObject<PooledConnectionAndInfo> p) throws SQLException {
final PooledConnection pooledConnection = p.getObject().getPooledConnection();
pooledConnection.removeConnectionEventListener(this);
pcMap.remove(pooledConnection);
@@ -224,10 +223,6 @@ class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey
}
}
- // ***********************************************************************
- // java.sql.ConnectionEventListener implementation
- // ***********************************************************************
-
/**
* Creates a new {@code PooledConnectionAndInfo} from the given {@code UserPassKey}.
*
@@ -235,10 +230,10 @@ class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey
* {@code UserPassKey} containing user credentials
* @throws SQLException
* if the connection could not be created.
- * @see org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory#makeObject(java.lang.Object)
+ * @see org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory#makeObject(Object)
*/
@Override
- public synchronized PooledObject<PooledConnectionAndInfo> makeObject(final UserPassKey userPassKey) throws Exception {
+ public synchronized PooledObject<PooledConnectionAndInfo> makeObject(final UserPassKey userPassKey) throws SQLException {
PooledConnection pooledConnection = null;
final String userName = userPassKey.getUserName();
final String password = userPassKey.getPassword();
@@ -262,7 +257,7 @@ class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey
}
@Override
- public void passivateObject(final UserPassKey key, final PooledObject<PooledConnectionAndInfo> p) throws Exception {
+ public void passivateObject(final UserPassKey key, final PooledObject<PooledConnectionAndInfo> p) throws SQLException {
validateLifetime(p);
}
@@ -317,13 +312,8 @@ class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey
this.pool = pool;
}
- private void validateLifetime(final PooledObject<PooledConnectionAndInfo> p) throws Exception {
- if (maxConnLifetime.compareTo(Duration.ZERO) > 0) {
- final Duration lifetimeDuration = Duration.between(p.getCreateInstant(), Instant.now());
- if (lifetimeDuration.compareTo(maxConnLifetime) > 0) {
- throw new Exception(Utils.getMessage("connectionFactory.lifetimeExceeded", lifetimeDuration, maxConnLifetime));
- }
- }
+ private void validateLifetime(final PooledObject<PooledConnectionAndInfo> pooledObject) throws SQLException {
+ Utils.validateLifetime(pooledObject, maxConnLifetime);
}
/**
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSource.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSource.java
index 02331d7fa5..6fe183f903 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSource.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSource.java
@@ -39,7 +39,7 @@ import org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool;
/**
* <p>
- * A pooling <code>DataSource</code> appropriate for deployment within J2EE environment. There are many configuration
+ * A pooling {@code DataSource} appropriate for deployment within J2EE environment. There are many configuration
* options, most of which are defined in the parent class. This datasource uses individual pools per user, and some
* properties can be set specifically for a given user, if the deployment environment can support initialization of
* mapped properties. So for example, a pool of admin or write-access Connections can be guaranteed a certain number of
@@ -48,8 +48,8 @@ import org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool;
*
* <p>
* User passwords can be changed without re-initializing the datasource. When a
- * <code>getConnection(userName, password)</code> request is processed with a password that is different from those used
- * to create connections in the pool associated with <code>userName</code>, an attempt is made to create a new
+ * {@code getConnection(userName, password)} request is processed with a password that is different from those used
+ * to create connections in the pool associated with {@code userName}, an attempt is made to create a new
* connection using the supplied password and if this succeeds, the existing pool is cleared and a new pool is created
* for connections using the new password.
* </p>
@@ -62,7 +62,11 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
private static final Log log = LogFactory.getLog(PerUserPoolDataSource.class);
- // Per user pool properties
+ private static <K, V> HashMap<K, V> createMap() {
+ // Should there be a default size different than what this ctor provides?
+ return new HashMap<>();
+ }
+
private Map<String, Boolean> perUserBlockWhenExhausted;
private Map<String, String> perUserEvictionPolicyClassName;
private Map<String, Boolean> perUserLifo;
@@ -78,8 +82,6 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
private Map<String, Boolean> perUserTestOnReturn;
private Map<String, Boolean> perUserTestWhileIdle;
private Map<String, Duration> perUserDurationBetweenEvictionRuns;
-
- // Per user connection properties
private Map<String, Boolean> perUserDefaultAutoCommit;
private Map<String, Integer> perUserDefaultTransactionIsolation;
private Map<String, Boolean> perUserDefaultReadOnly;
@@ -87,7 +89,7 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
/**
* Map to keep track of Pools for a given user.
*/
- private transient Map<PoolKey, PooledConnectionManager> managers = new HashMap<>();
+ private transient Map<PoolKey, PooledConnectionManager> managers = createMap();
/**
* Default no-arg constructor for Serialization.
@@ -102,13 +104,13 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
* @since 2.3.0
*/
public void clear() {
- for (final PooledConnectionManager manager : managers.values()) {
+ managers.values().forEach(manager -> {
try {
getCPDSConnectionFactoryPool(manager).clear();
- } catch (final Exception closePoolException) {
+ } catch (final Exception ignored) {
// ignore and try to close others.
}
- }
+ });
InstanceKeyDataSourceFactory.removeInstance(getInstanceKey());
}
@@ -119,9 +121,7 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
@Override
public void close() {
- for (final PooledConnectionManager manager : managers.values()) {
- Utils.closeQuietly(getCPDSConnectionFactoryPool(manager));
- }
+ managers.values().forEach(manager -> Utils.closeQuietly(getCPDSConnectionFactoryPool(manager)));
InstanceKeyDataSourceFactory.removeInstance(getInstanceKey());
}
@@ -129,7 +129,7 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
* Converts a map with Long milliseconds values to another map with Duration values.
*/
private Map<String, Duration> convertMap(final Map<String, Duration> currentMap, final Map<String, Long> longMap) {
- final Map<String, Duration> durationMap = new HashMap<>();
+ final Map<String, Duration> durationMap = createMap();
longMap.forEach((k, v) -> durationMap.put(k, toDurationOrNull(v)));
if (currentMap == null) {
return durationMap;
@@ -140,11 +140,6 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
}
- private HashMap<String, Boolean> createMap() {
- // Should there be a default size different than what this ctor provides?
- return new HashMap<>();
- }
-
@Override
protected PooledConnectionManager getConnectionManager(final UserPassKey upKey) {
return managers.get(getPoolKey(upKey.getUserName()));
@@ -669,7 +664,7 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
}
/**
- * Returns a <code>PerUserPoolDataSource</code> {@link Reference}.
+ * Returns a {@code PerUserPoolDataSource} {@link Reference}.
*/
@Override
public Reference getReference() throws NamingException {
@@ -678,21 +673,19 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
return ref;
}
- private Map<String, Duration> makeMap(final Map<String, Duration> currentMap, final Map<String, Duration> newMap) {
- if (currentMap == null) {
- return new HashMap<>(newMap);
+ <K, V> Map<K, V> put(Map<K, V> map, final K key, final V value) {
+ if (map == null) {
+ map = createMap();
}
- currentMap.clear();
- currentMap.putAll(newMap);
- return currentMap;
-
+ map.put(key, value);
+ return map;
}
/**
* Supports Serialization interface.
*
* @param in
- * a <code>java.io.ObjectInputStream</code> value
+ * a {@code java.io.ObjectInputStream} value
* @throws IOException
* if an error occurs
* @throws ClassNotFoundException
@@ -748,14 +741,18 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
}
}
- void setPerUserBlockWhenExhausted(final Map<String, Boolean> userDefaultBlockWhenExhausted) {
- assertInitializationAllowed();
- if (perUserBlockWhenExhausted == null) {
- perUserBlockWhenExhausted = createMap();
- } else {
- perUserBlockWhenExhausted.clear();
+ private <K, V> Map<K, V> replaceAll(final Map<K, V> currentMap, final Map<K, V> newMap) {
+ if (currentMap == null) {
+ return new HashMap<>(newMap);
}
- perUserBlockWhenExhausted.putAll(userDefaultBlockWhenExhausted);
+ currentMap.clear();
+ currentMap.putAll(newMap);
+ return currentMap;
+ }
+
+ void setPerUserBlockWhenExhausted(final Map<String, Boolean> newMap) {
+ assertInitializationAllowed();
+ perUserBlockWhenExhausted = replaceAll(perUserBlockWhenExhausted, newMap);
}
/**
@@ -768,20 +765,12 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserBlockWhenExhausted(final String userName, final Boolean value) {
assertInitializationAllowed();
- if (perUserBlockWhenExhausted == null) {
- perUserBlockWhenExhausted = createMap();
- }
- perUserBlockWhenExhausted.put(userName, value);
+ perUserBlockWhenExhausted = put(perUserBlockWhenExhausted, userName, value);
}
- void setPerUserDefaultAutoCommit(final Map<String, Boolean> userDefaultAutoCommit) {
+ void setPerUserDefaultAutoCommit(final Map<String, Boolean> newMap) {
assertInitializationAllowed();
- if (perUserDefaultAutoCommit == null) {
- perUserDefaultAutoCommit = createMap();
- } else {
- perUserDefaultAutoCommit.clear();
- }
- perUserDefaultAutoCommit.putAll(userDefaultAutoCommit);
+ perUserDefaultAutoCommit = replaceAll(perUserDefaultAutoCommit, newMap);
}
/**
@@ -794,20 +783,13 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserDefaultAutoCommit(final String userName, final Boolean value) {
assertInitializationAllowed();
- if (perUserDefaultAutoCommit == null) {
- perUserDefaultAutoCommit = createMap();
- }
- perUserDefaultAutoCommit.put(userName, value);
+ perUserDefaultAutoCommit = put(perUserDefaultAutoCommit, userName, value);
+
}
- void setPerUserDefaultReadOnly(final Map<String, Boolean> userDefaultReadOnly) {
+ void setPerUserDefaultReadOnly(final Map<String, Boolean> newMap) {
assertInitializationAllowed();
- if (perUserDefaultReadOnly == null) {
- perUserDefaultReadOnly = createMap();
- } else {
- perUserDefaultReadOnly.clear();
- }
- perUserDefaultReadOnly.putAll(userDefaultReadOnly);
+ perUserDefaultReadOnly = replaceAll(perUserDefaultReadOnly, newMap);
}
/**
@@ -820,20 +802,13 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserDefaultReadOnly(final String userName, final Boolean value) {
assertInitializationAllowed();
- if (perUserDefaultReadOnly == null) {
- perUserDefaultReadOnly = createMap();
- }
- perUserDefaultReadOnly.put(userName, value);
+ perUserDefaultReadOnly = put(perUserDefaultReadOnly, userName, value);
+
}
- void setPerUserDefaultTransactionIsolation(final Map<String, Integer> userDefaultTransactionIsolation) {
+ void setPerUserDefaultTransactionIsolation(final Map<String, Integer> newMap) {
assertInitializationAllowed();
- if (perUserDefaultTransactionIsolation == null) {
- perUserDefaultTransactionIsolation = new HashMap<>();
- } else {
- perUserDefaultTransactionIsolation.clear();
- }
- perUserDefaultTransactionIsolation.putAll(userDefaultTransactionIsolation);
+ perUserDefaultTransactionIsolation = replaceAll(perUserDefaultTransactionIsolation, newMap);
}
/**
@@ -847,15 +822,13 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserDefaultTransactionIsolation(final String userName, final Integer value) {
assertInitializationAllowed();
- if (perUserDefaultTransactionIsolation == null) {
- perUserDefaultTransactionIsolation = new HashMap<>();
- }
- perUserDefaultTransactionIsolation.put(userName, value);
+ perUserDefaultTransactionIsolation = put(perUserDefaultTransactionIsolation, userName, value);
+
}
void setPerUserDurationBetweenEvictionRuns(final Map<String, Duration> newMap) {
assertInitializationAllowed();
- perUserDurationBetweenEvictionRuns = makeMap(perUserDurationBetweenEvictionRuns, newMap);
+ perUserDurationBetweenEvictionRuns = replaceAll(perUserDurationBetweenEvictionRuns, newMap);
}
/**
@@ -870,20 +843,13 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserDurationBetweenEvictionRuns(final String userName, final Duration value) {
assertInitializationAllowed();
- if (perUserDurationBetweenEvictionRuns == null) {
- perUserDurationBetweenEvictionRuns = new HashMap<>();
- }
- perUserDurationBetweenEvictionRuns.put(userName, value);
+ perUserDurationBetweenEvictionRuns = put(perUserDurationBetweenEvictionRuns, userName, value);
+
}
- void setPerUserEvictionPolicyClassName(final Map<String, String> userDefaultEvictionPolicyClassName) {
+ void setPerUserEvictionPolicyClassName(final Map<String, String> newMap) {
assertInitializationAllowed();
- if (perUserEvictionPolicyClassName == null) {
- perUserEvictionPolicyClassName = new HashMap<>();
- } else {
- perUserEvictionPolicyClassName.clear();
- }
- perUserEvictionPolicyClassName.putAll(userDefaultEvictionPolicyClassName);
+ perUserEvictionPolicyClassName = replaceAll(perUserEvictionPolicyClassName, newMap);
}
/**
@@ -897,20 +863,12 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserEvictionPolicyClassName(final String userName, final String value) {
assertInitializationAllowed();
- if (perUserEvictionPolicyClassName == null) {
- perUserEvictionPolicyClassName = new HashMap<>();
- }
- perUserEvictionPolicyClassName.put(userName, value);
+ perUserEvictionPolicyClassName = put(perUserEvictionPolicyClassName, userName, value);
}
- void setPerUserLifo(final Map<String, Boolean> userDefaultLifo) {
+ void setPerUserLifo(final Map<String, Boolean> newMap) {
assertInitializationAllowed();
- if (perUserLifo == null) {
- perUserLifo = createMap();
- } else {
- perUserLifo.clear();
- }
- perUserLifo.putAll(userDefaultLifo);
+ perUserLifo = replaceAll(perUserLifo, newMap);
}
/**
@@ -923,20 +881,12 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserLifo(final String userName, final Boolean value) {
assertInitializationAllowed();
- if (perUserLifo == null) {
- perUserLifo = createMap();
- }
- perUserLifo.put(userName, value);
+ perUserLifo = put(perUserLifo, userName, value);
}
- void setPerUserMaxIdle(final Map<String, Integer> userDefaultMaxIdle) {
+ void setPerUserMaxIdle(final Map<String, Integer> newMap) {
assertInitializationAllowed();
- if (perUserMaxIdle == null) {
- perUserMaxIdle = new HashMap<>();
- } else {
- perUserMaxIdle.clear();
- }
- perUserMaxIdle.putAll(userDefaultMaxIdle);
+ perUserMaxIdle = replaceAll(perUserMaxIdle, newMap);
}
/**
@@ -949,20 +899,12 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserMaxIdle(final String userName, final Integer value) {
assertInitializationAllowed();
- if (perUserMaxIdle == null) {
- perUserMaxIdle = new HashMap<>();
- }
- perUserMaxIdle.put(userName, value);
+ perUserMaxIdle = put(perUserMaxIdle, userName, value);
}
- void setPerUserMaxTotal(final Map<String, Integer> userDefaultMaxTotal) {
+ void setPerUserMaxTotal(final Map<String, Integer> newMap) {
assertInitializationAllowed();
- if (perUserMaxTotal == null) {
- perUserMaxTotal = new HashMap<>();
- } else {
- perUserMaxTotal.clear();
- }
- perUserMaxTotal.putAll(userDefaultMaxTotal);
+ perUserMaxTotal = replaceAll(perUserMaxTotal, newMap);
}
/**
@@ -975,15 +917,7 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserMaxTotal(final String userName, final Integer value) {
assertInitializationAllowed();
- if (perUserMaxTotal == null) {
- perUserMaxTotal = new HashMap<>();
- }
- perUserMaxTotal.put(userName, value);
- }
-
- void setPerUserMaxWaitDuration(final Map<String, Duration> newMap) {
- assertInitializationAllowed();
- perUserMaxWaitDuration = makeMap(perUserMaxWaitDuration, newMap);
+ perUserMaxTotal = put(perUserMaxTotal, userName, value);
}
/**
@@ -997,10 +931,12 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserMaxWait(final String userName, final Duration value) {
assertInitializationAllowed();
- if (perUserMaxWaitDuration == null) {
- perUserMaxWaitDuration = new HashMap<>();
- }
- perUserMaxWaitDuration.put(userName, value);
+ perUserMaxWaitDuration = put(perUserMaxWaitDuration, userName, value);
+ }
+
+ void setPerUserMaxWaitDuration(final Map<String, Duration> newMap) {
+ assertInitializationAllowed();
+ perUserMaxWaitDuration = replaceAll(perUserMaxWaitDuration, newMap);
}
void setPerUserMaxWaitMillis(final Map<String, Long> newMap) {
@@ -1024,7 +960,7 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
void setPerUserMinEvictableIdle(final Map<String, Duration> newMap) {
assertInitializationAllowed();
- perUserMinEvictableIdleDuration = makeMap(perUserMinEvictableIdleDuration, newMap);
+ perUserMinEvictableIdleDuration = replaceAll(perUserMinEvictableIdleDuration, newMap);
}
/**
@@ -1039,10 +975,7 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserMinEvictableIdle(final String userName, final Duration value) {
assertInitializationAllowed();
- if (perUserMinEvictableIdleDuration == null) {
- perUserMinEvictableIdleDuration = new HashMap<>();
- }
- perUserMinEvictableIdleDuration.put(userName, value);
+ perUserMinEvictableIdleDuration = put(perUserMinEvictableIdleDuration, userName, value);
}
/**
@@ -1060,14 +993,9 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
setPerUserMinEvictableIdle(userName, toDurationOrNull(value));
}
- void setPerUserMinIdle(final Map<String, Integer> userDefaultMinIdle) {
+ void setPerUserMinIdle(final Map<String, Integer> newMap) {
assertInitializationAllowed();
- if (perUserMinIdle == null) {
- perUserMinIdle = new HashMap<>();
- } else {
- perUserMinIdle.clear();
- }
- perUserMinIdle.putAll(userDefaultMinIdle);
+ perUserMinIdle = replaceAll(perUserMinIdle, newMap);
}
/**
@@ -1080,20 +1008,12 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserMinIdle(final String userName, final Integer value) {
assertInitializationAllowed();
- if (perUserMinIdle == null) {
- perUserMinIdle = new HashMap<>();
- }
- perUserMinIdle.put(userName, value);
+ perUserMinIdle = put(perUserMinIdle, userName, value);
}
- void setPerUserNumTestsPerEvictionRun(final Map<String, Integer> userDefaultNumTestsPerEvictionRun) {
+ void setPerUserNumTestsPerEvictionRun(final Map<String, Integer> newMap) {
assertInitializationAllowed();
- if (perUserNumTestsPerEvictionRun == null) {
- perUserNumTestsPerEvictionRun = new HashMap<>();
- } else {
- perUserNumTestsPerEvictionRun.clear();
- }
- perUserNumTestsPerEvictionRun.putAll(userDefaultNumTestsPerEvictionRun);
+ perUserNumTestsPerEvictionRun = replaceAll(perUserNumTestsPerEvictionRun, newMap);
}
/**
@@ -1107,15 +1027,12 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserNumTestsPerEvictionRun(final String userName, final Integer value) {
assertInitializationAllowed();
- if (perUserNumTestsPerEvictionRun == null) {
- perUserNumTestsPerEvictionRun = new HashMap<>();
- }
- perUserNumTestsPerEvictionRun.put(userName, value);
+ perUserNumTestsPerEvictionRun = put(perUserNumTestsPerEvictionRun, userName, value);
}
void setPerUserSoftMinEvictableIdle(final Map<String, Duration> newMap) {
assertInitializationAllowed();
- perUserSoftMinEvictableIdleDuration = makeMap(perUserSoftMinEvictableIdleDuration, newMap);
+ perUserSoftMinEvictableIdleDuration = replaceAll(perUserSoftMinEvictableIdleDuration, newMap);
}
/**
@@ -1130,10 +1047,7 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserSoftMinEvictableIdle(final String userName, final Duration value) {
assertInitializationAllowed();
- if (perUserSoftMinEvictableIdleDuration == null) {
- perUserSoftMinEvictableIdleDuration = new HashMap<>();
- }
- perUserSoftMinEvictableIdleDuration.put(userName, value);
+ perUserSoftMinEvictableIdleDuration = put(perUserSoftMinEvictableIdleDuration, userName, value);
}
/**
@@ -1151,14 +1065,9 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
setPerUserSoftMinEvictableIdle(userName, toDurationOrNull(value));
}
- void setPerUserTestOnBorrow(final Map<String, Boolean> userDefaultTestOnBorrow) {
+ void setPerUserTestOnBorrow(final Map<String, Boolean> newMap) {
assertInitializationAllowed();
- if (perUserTestOnBorrow == null) {
- perUserTestOnBorrow = createMap();
- } else {
- perUserTestOnBorrow.clear();
- }
- perUserTestOnBorrow.putAll(userDefaultTestOnBorrow);
+ perUserTestOnBorrow = replaceAll(perUserTestOnBorrow, newMap);
}
/**
@@ -1171,20 +1080,12 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserTestOnBorrow(final String userName, final Boolean value) {
assertInitializationAllowed();
- if (perUserTestOnBorrow == null) {
- perUserTestOnBorrow = createMap();
- }
- perUserTestOnBorrow.put(userName, value);
+ perUserTestOnBorrow = put(perUserTestOnBorrow, userName, value);
}
- void setPerUserTestOnCreate(final Map<String, Boolean> userDefaultTestOnCreate) {
+ void setPerUserTestOnCreate(final Map<String, Boolean> newMap) {
assertInitializationAllowed();
- if (perUserTestOnCreate == null) {
- perUserTestOnCreate = createMap();
- } else {
- perUserTestOnCreate.clear();
- }
- perUserTestOnCreate.putAll(userDefaultTestOnCreate);
+ perUserTestOnCreate = replaceAll(perUserTestOnCreate, newMap);
}
/**
@@ -1197,20 +1098,12 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserTestOnCreate(final String userName, final Boolean value) {
assertInitializationAllowed();
- if (perUserTestOnCreate == null) {
- perUserTestOnCreate = createMap();
- }
- perUserTestOnCreate.put(userName, value);
+ perUserTestOnCreate = put(perUserTestOnCreate, userName, value);
}
- void setPerUserTestOnReturn(final Map<String, Boolean> userDefaultTestOnReturn) {
+ void setPerUserTestOnReturn(final Map<String, Boolean> newMap) {
assertInitializationAllowed();
- if (perUserTestOnReturn == null) {
- perUserTestOnReturn = createMap();
- } else {
- perUserTestOnReturn.clear();
- }
- perUserTestOnReturn.putAll(userDefaultTestOnReturn);
+ perUserTestOnReturn = replaceAll(perUserTestOnReturn, newMap);
}
/**
@@ -1223,20 +1116,12 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserTestOnReturn(final String userName, final Boolean value) {
assertInitializationAllowed();
- if (perUserTestOnReturn == null) {
- perUserTestOnReturn = createMap();
- }
- perUserTestOnReturn.put(userName, value);
+ perUserTestOnReturn = put(perUserTestOnReturn, userName, value);
}
- void setPerUserTestWhileIdle(final Map<String, Boolean> userDefaultTestWhileIdle) {
+ void setPerUserTestWhileIdle(final Map<String, Boolean> newMap) {
assertInitializationAllowed();
- if (perUserTestWhileIdle == null) {
- perUserTestWhileIdle = createMap();
- } else {
- perUserTestWhileIdle.clear();
- }
- perUserTestWhileIdle.putAll(userDefaultTestWhileIdle);
+ perUserTestWhileIdle = replaceAll(perUserTestWhileIdle, newMap);
}
/**
@@ -1249,10 +1134,7 @@ public class PerUserPoolDataSource extends InstanceKeyDataSource {
*/
public void setPerUserTestWhileIdle(final String userName, final Boolean value) {
assertInitializationAllowed();
- if (perUserTestWhileIdle == null) {
- perUserTestWhileIdle = createMap();
- }
- perUserTestWhileIdle.put(userName, value);
+ perUserTestWhileIdle = put(perUserTestWhileIdle, userName, value);
}
/**
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSourceFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSourceFactory.java
index 3a2bcf7524..df53faa0b9 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSourceFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSourceFactory.java
@@ -24,7 +24,7 @@ import javax.naming.RefAddr;
import javax.naming.Reference;
/**
- * A JNDI ObjectFactory which creates <code>SharedPoolDataSource</code>s
+ * A JNDI ObjectFactory which creates {@code SharedPoolDataSource}s
*
* @since 2.0
*/
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java
index 06c0fe3e6a..9cc08ab23b 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java
@@ -22,7 +22,7 @@ import java.util.Objects;
/**
* @since 2.0
*/
-class PoolKey implements Serializable {
+final class PoolKey implements Serializable {
private static final long serialVersionUID = 2252771047542484533L;
private final String dataSourceName;
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java
index 0c1d2c6af8..f72eaa264a 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java
@@ -37,15 +37,7 @@ interface PooledConnectionManager {
*/
void closePool(String userName) throws SQLException;
- // /**
- // * Sets the database password used when creating connections.
- // *
- // * @param password password used when authenticating to the database
- // * @since 3.0.0
- // */
- // void setPassword(char[] password);
-
- /**
+ /**
* Closes the PooledConnection and remove it from the connection pool to which it belongs, adjusting pool counters.
*
* @param pc
@@ -55,6 +47,16 @@ interface PooledConnectionManager {
*/
void invalidate(PooledConnection pc) throws SQLException;
+// /**
+// * Sets the database password used when creating connections.
+// *
+// * @param password password used when authenticating to the database
+// * @since 2.10.0
+// */
+// default void setPassword(char[] password) {
+// setPassword(String.copyValueOf(password));
+// }
+
/**
* Sets the database password used when creating connections.
*
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSource.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSource.java
index 6073fec07a..029868a377 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSource.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSource.java
@@ -32,15 +32,15 @@ import org.apache.tomcat.dbcp.pool2.impl.GenericKeyedObjectPoolConfig;
/**
* <p>
- * A pooling <code>DataSource</code> appropriate for deployment within J2EE environment. There are many configuration
+ * A pooling {@code DataSource} appropriate for deployment within J2EE environment. There are many configuration
* options, most of which are defined in the parent class. All users (based on user name) share a single maximum number
* of Connections in this data source.
* </p>
*
* <p>
* User passwords can be changed without re-initializing the data source. When a
- * <code>getConnection(user name, password)</code> request is processed with a password that is different from those
- * used to create connections in the pool associated with <code>user name</code>, an attempt is made to create a new
+ * {@code getConnection(user name, password)} request is processed with a password that is different from those
+ * used to create connections in the pool associated with {@code user name}, an attempt is made to create a new
* connection using the supplied password and if this succeeds, idle connections created using the old password are
* destroyed and new connections are created using the new password.
* </p>
@@ -68,7 +68,7 @@ public class SharedPoolDataSource extends InstanceKeyDataSource {
* Closes pool being maintained by this data source.
*/
@Override
- public void close() throws Exception {
+ public void close() throws SQLException {
if (pool != null) {
pool.close();
}
@@ -145,7 +145,7 @@ public class SharedPoolDataSource extends InstanceKeyDataSource {
* Supports Serialization interface.
*
* @param in
- * a <code>java.io.ObjectInputStream</code> value
+ * a {@code java.io.ObjectInputStream} value
* @throws IOException
* if an error occurs
* @throws ClassNotFoundException
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java b/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java
index e763f1192b..02ed24bbcd 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java
@@ -36,7 +36,7 @@ import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
*
* @since 2.0
*/
-class UserPassKey implements Serializable {
+final class UserPassKey implements Serializable {
private static final long serialVersionUID = 5142970911626584817L;
private final CharArray name;
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 5b243607b5..25a762d52a 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java
@@ -17,8 +17,8 @@
/**
* <p>
- * This package contains two DataSources: <code>PerUserPoolDataSource</code> and
- * <code>SharedPoolDataSource</code> which provide a database connection pool.
+ * This package contains two DataSources: {@code PerUserPoolDataSource} and
+ * {@code SharedPoolDataSource} which provide a database connection pool.
* Below are a couple of usage examples. One shows deployment into a JNDI system.
* The other is a simple example initializing the pool using standard java code.
* </p>
@@ -81,12 +81,12 @@
* Apache Tomcat deploys all objects configured similarly to above within the
* <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
+ * {@code ConnectionPoolDataSource} that is deployed as given in the
* <a href="../cpdsadapter/package-summary.html">cpdsadapter example</a>
* </p>
*
* <p>
- * The <code>DataSource</code> is now available to the application as shown
+ * The {@code DataSource} is now available to the application as shown
* below:
* </p>
*
@@ -112,11 +112,11 @@
* </code>
*
* <p>
- * The reference to the <code>DataSource</code> could be maintained, for
- * multiple getConnection() requests. Or the <code>DataSource</code> can be
+ * The reference to the {@code DataSource} could be maintained, for
+ * multiple getConnection() requests. Or the {@code DataSource} can be
* looked up in different parts of the application code.
- * <code>PerUserPoolDataSourceFactory</code> and
- * <code>SharedPoolDataSourceFactory</code> will maintain the state of the pool
+ * {@code PerUserPoolDataSourceFactory} and
+ * {@code SharedPoolDataSourceFactory} will maintain the state of the pool
* between different lookups. This behavior may be different in other
* implementations.
* </p>
@@ -125,7 +125,7 @@
*
* <p>
* Connection pooling is useful in applications regardless of whether they run
- * in a J2EE environment and a <code>DataSource</code> can be used within a
+ * in a J2EE environment and a {@code DataSource} can be used within a
* simpler environment. The example below shows SharedPoolDataSource using
* DriverAdapterCPDS as the back end source, though any CPDS is applicable.
* </p>
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java
index 01ac1fbe66..267c866722 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java
@@ -38,6 +38,26 @@ import org.apache.tomcat.dbcp.dbcp2.Utils;
* @since 2.0
*/
public class DataSourceXAConnectionFactory implements XAConnectionFactory {
+
+ private static final class XAConnectionEventListener implements ConnectionEventListener {
+ @Override
+ public void connectionClosed(final ConnectionEvent event) {
+ final PooledConnection pc = (PooledConnection) event.getSource();
+ pc.removeConnectionEventListener(this);
+ try {
+ pc.close();
+ } catch (final SQLException e) {
+ System.err.println("Failed to close XAConnection");
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void connectionErrorOccurred(final ConnectionEvent event) {
+ connectionClosed(event);
+ }
+ }
+
private final TransactionRegistry transactionRegistry;
private final XADataSource xaDataSource;
private String userName;
@@ -93,15 +113,15 @@ public class DataSourceXAConnectionFactory implements XAConnectionFactory {
*/
public DataSourceXAConnectionFactory(final TransactionManager transactionManager, final XADataSource xaDataSource,
final String userName, final char[] userPassword, final TransactionSynchronizationRegistry transactionSynchronizationRegistry) {
- Objects.requireNonNull(transactionManager, "transactionManager is null");
- Objects.requireNonNull(xaDataSource, "xaDataSource is null");
+ Objects.requireNonNull(transactionManager, "transactionManager");
+ Objects.requireNonNull(xaDataSource, "xaDataSource");
// We do allow the transactionSynchronizationRegistry to be null for non-app server environments
this.transactionRegistry = new TransactionRegistry(transactionManager, transactionSynchronizationRegistry);
this.xaDataSource = xaDataSource;
this.userName = userName;
- this.userPassword = userPassword == null ? null : userPassword.clone();
+ this.userPassword = Utils.clone(userPassword);
}
/**
@@ -157,25 +177,7 @@ public class DataSourceXAConnectionFactory implements XAConnectionFactory {
// The Connection we're returning is a handle on the XAConnection.
// When the pool calling us closes the Connection, we need to
// also close the XAConnection that holds the physical connection.
- xaConnection.addConnectionEventListener(new ConnectionEventListener() {
-
- @Override
- public void connectionClosed(final ConnectionEvent event) {
- final PooledConnection pc = (PooledConnection) event.getSource();
- pc.removeConnectionEventListener(this);
- try {
- pc.close();
- } catch (final SQLException e) {
- System.err.println("Failed to close XAConnection");
- e.printStackTrace();
- }
- }
-
- @Override
- public void connectionErrorOccurred(final ConnectionEvent event) {
- connectionClosed(event);
- }
- });
+ xaConnection.addConnectionEventListener(new XAConnectionEventListener());
return connection;
}
@@ -212,7 +214,7 @@ public class DataSourceXAConnectionFactory implements XAConnectionFactory {
* @return the user password.
*/
public char[] getUserPassword() {
- return userPassword == null ? null : userPassword.clone();
+ return Utils.clone(userPassword);
}
/**
@@ -232,7 +234,7 @@ public class DataSourceXAConnectionFactory implements XAConnectionFactory {
* @since 2.4.0
*/
public void setPassword(final char[] userPassword) {
- this.userPassword = userPassword == null ? null : userPassword.clone();
+ this.userPassword = Utils.clone(userPassword);
}
/**
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java
index 494b90ad72..8906330837 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java
@@ -68,6 +68,13 @@ public class LocalXAConnectionFactory implements XAConnectionFactory {
this.connection = localTransaction;
}
+ private Xid checkCurrentXid() throws XAException {
+ if (this.currentXid == null) {
+ throw new XAException("There is no current transaction");
+ }
+ return currentXid;
+ }
+
/**
* Commits the transaction and restores the original auto commit setting.
*
@@ -80,11 +87,8 @@ public class LocalXAConnectionFactory implements XAConnectionFactory {
*/
@Override
public synchronized void commit(final Xid xid, final boolean flag) throws XAException {
- Objects.requireNonNull(xid, "xid is null");
- if (this.currentXid == null) {
- throw new XAException("There is no current transaction");
- }
- if (!this.currentXid.equals(xid)) {
+ Objects.requireNonNull(xid, "xid");
+ if (!checkCurrentXid().equals(xid)) {
throw new XAException("Invalid Xid: expected " + this.currentXid + ", but was " + xid);
}
@@ -103,8 +107,8 @@ public class LocalXAConnectionFactory implements XAConnectionFactory {
} finally {
try {
connection.setAutoCommit(originalAutoCommit);
- } catch (final SQLException e) {
- // ignore
+ } catch (final SQLException ignored) {
+ // ignored
}
this.currentXid = null;
}
@@ -122,8 +126,8 @@ public class LocalXAConnectionFactory implements XAConnectionFactory {
*/
@Override
public synchronized void end(final Xid xid, final int flag) throws XAException {
- Objects.requireNonNull(xid, "xid is null");
- if (!this.currentXid.equals(xid)) {
+ Objects.requireNonNull(xid, "xid");
+ if (!checkCurrentXid().equals(xid)) {
throw new XAException("Invalid Xid: expected " + this.currentXid + ", but was " + xid);
}
@@ -230,8 +234,8 @@ public class LocalXAConnectionFactory implements XAConnectionFactory {
*/
@Override
public synchronized void rollback(final Xid xid) throws XAException {
- Objects.requireNonNull(xid, "xid is null");
- if (!this.currentXid.equals(xid)) {
+ Objects.requireNonNull(xid, "xid");
+ if (!checkCurrentXid().equals(xid)) {
throw new XAException("Invalid Xid: expected " + this.currentXid + ", but was " + xid);
}
@@ -242,8 +246,8 @@ public class LocalXAConnectionFactory implements XAConnectionFactory {
} finally {
try {
connection.setAutoCommit(originalAutoCommit);
- } catch (final SQLException e) {
- // Ignore.
+ } catch (final SQLException ignored) {
+ // Ignored.
}
this.currentXid = null;
}
@@ -344,8 +348,8 @@ public class LocalXAConnectionFactory implements XAConnectionFactory {
public LocalXAConnectionFactory(final TransactionManager transactionManager,
final TransactionSynchronizationRegistry transactionSynchronizationRegistry,
final ConnectionFactory connectionFactory) {
- Objects.requireNonNull(transactionManager, "transactionManager is null");
- Objects.requireNonNull(connectionFactory, "connectionFactory is null");
+ Objects.requireNonNull(transactionManager, "transactionManager");
+ Objects.requireNonNull(connectionFactory, "connectionFactory");
this.transactionRegistry = new TransactionRegistry(transactionManager, transactionSynchronizationRegistry);
this.connectionFactory = connectionFactory;
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java
index aeba61d798..81d370e5c9 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java
@@ -58,12 +58,12 @@ public class ManagedConnection<C extends Connection> extends DelegatingConnectio
}
}
}
+
private final ObjectPool<C> pool;
private final TransactionRegistry transactionRegistry;
private final boolean accessToUnderlyingConnectionAllowed;
private TransactionContext transactionContext;
private boolean isSharedConnection;
-
private final Lock lock;
/**
@@ -264,11 +264,11 @@ public class ManagedConnection<C extends Connection> extends DelegatingConnectio
if (connection != null && transactionContext.getSharedConnection() != connection) {
try {
pool.returnObject(connection);
- } catch (final Exception ignored) {
+ } catch (final Exception e) {
// whatever... try to invalidate the connection
try {
pool.invalidateObject(connection);
- } catch (final Exception ignore) {
+ } catch (final Exception ignored) {
// no big deal
}
}
@@ -313,7 +313,7 @@ public class ManagedConnection<C extends Connection> extends DelegatingConnectio
transactionContext = null;
try {
pool.invalidateObject(connection);
- } catch (final Exception e1) {
+ } catch (final Exception ignored) {
// we are try but no luck
}
throw e;
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java
index ea2ad35859..802b0362a9 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java
@@ -85,7 +85,7 @@ public class ManagedDataSource<C extends Connection> extends PoolingDataSource<C
if (this.transactionRegistry != null) {
throw new IllegalStateException("TransactionRegistry already set");
}
- Objects.requireNonNull(transactionRegistry, "transactionRegistry is null");
+ Objects.requireNonNull(transactionRegistry, "transactionRegistry");
this.transactionRegistry = transactionRegistry;
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java
index b7adcc0122..28c2046cd1 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java
@@ -17,6 +17,7 @@
package org.apache.tomcat.dbcp.dbcp2.managed;
import java.sql.Connection;
+import java.sql.SQLException;
import java.time.Duration;
import javax.management.ObjectName;
@@ -66,12 +67,12 @@ public class PoolableManagedConnectionFactory extends PoolableConnectionFactory
/**
* Uses the configured XAConnectionFactory to create a {@link PoolableManagedConnection}. Throws
- * <code>IllegalStateException</code> if the connection factory returns null. Also initializes the connection using
+ * {@code IllegalStateException} if the connection factory returns null. Also initializes the connection using
* configured initialization SQL (if provided) and sets up a prepared statement pool associated with the
* PoolableManagedConnection if statement pooling is enabled.
*/
@Override
- public synchronized PooledObject<PoolableConnection> makeObject() throws Exception {
+ public synchronized PooledObject<PoolableConnection> makeObject() throws SQLException {
Connection conn = getConnectionFactory().createConnection();
if (conn == null) {
throw new IllegalStateException("Connection factory returned null from createConnection");
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/SynchronizationAdapter.java
similarity index 57%
copy from java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java
copy to java/org/apache/tomcat/dbcp/dbcp2/managed/SynchronizationAdapter.java
index dd2bbdd7e1..c7969d242e 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/SynchronizationAdapter.java
@@ -14,30 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tomcat.dbcp.dbcp2;
+package org.apache.tomcat.dbcp.dbcp2.managed;
+
+import jakarta.transaction.Synchronization;
/**
- * Exception thrown when a connection's maximum lifetime has been exceeded.
- *
- * @since 2.1
+ * Implements {@link Synchronization} for subclasses.
*/
-class LifetimeExceededException extends Exception {
+class SynchronizationAdapter implements Synchronization {
- private static final long serialVersionUID = -3783783104516492659L;
-
- /**
- * Create a LifetimeExceededException.
- */
- public LifetimeExceededException() {
+ @Override
+ public void afterCompletion(final int status) {
+ // Noop
}
- /**
- * Create a LifetimeExceededException with the given message.
- *
- * @param message
- * The message with which to create the exception
- */
- public LifetimeExceededException(final String message) {
- super(message);
+ @Override
+ public void beforeCompletion() {
+ // Noop
}
+
}
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java
index 975fa88a7c..1a8823483f 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java
@@ -69,8 +69,8 @@ public class TransactionContext {
*/
public TransactionContext(final TransactionRegistry transactionRegistry, final Transaction transaction,
final TransactionSynchronizationRegistry transactionSynchronizationRegistry) {
- Objects.requireNonNull(transactionRegistry, "transactionRegistry is null");
- Objects.requireNonNull(transaction, "transaction is null");
+ Objects.requireNonNull(transactionRegistry, "transactionRegistry");
+ Objects.requireNonNull(transaction, "transaction");
this.transactionRegistry = transactionRegistry;
this.transactionRef = new WeakReference<>(transaction);
this.transactionComplete = false;
@@ -89,27 +89,21 @@ public class TransactionContext {
try {
if (!isActive()) {
final Transaction transaction = this.transactionRef.get();
- listener.afterCompletion(TransactionContext.this,
- transaction != null && transaction.getStatus() == Status.STATUS_COMMITTED);
+ listener.afterCompletion(this, transaction != null && transaction.getStatus() == Status.STATUS_COMMITTED);
return;
}
- final Synchronization s = new Synchronization() {
+ final Synchronization s = new SynchronizationAdapter() {
@Override
public void afterCompletion(final int status) {
listener.afterCompletion(TransactionContext.this, status == Status.STATUS_COMMITTED);
}
-
- @Override
- public void beforeCompletion() {
- // empty
- }
};
if (transactionSynchronizationRegistry != null) {
transactionSynchronizationRegistry.registerInterposedSynchronization(s);
} else {
getTransaction().registerSynchronization(s);
}
- } catch (final RollbackException e) {
+ } catch (final RollbackException ignored) {
// JTA spec doesn't let us register with a transaction marked rollback only
// just ignore this and the tx state will be cleared another way.
} catch (final Exception e) {
@@ -200,7 +194,7 @@ public class TransactionContext {
} catch (final IllegalStateException e) {
// This can happen if the transaction is already timed out
throw new SQLException("Unable to enlist connection in the transaction", e);
- } catch (final RollbackException e) {
+ } catch (final RollbackException ignored) {
// transaction was rolled back... proceed as if there never was a transaction
} catch (final SystemException e) {
throw new SQLException("Unable to enlist connection the transaction", e);
diff --git a/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java b/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java
index 8a33f27d5d..1d0d163d31 100644
--- a/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java
+++ b/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java
@@ -93,12 +93,7 @@ public class TransactionRegistry {
// register the context (or create a new one)
synchronized (this) {
- TransactionContext cache = caches.get(transaction);
- if (cache == null) {
- cache = new TransactionContext(this, transaction, transactionSynchronizationRegistry);
- caches.put(transaction, cache);
- }
- return cache;
+ return caches.computeIfAbsent(transaction, k -> new TransactionContext(this, k, transactionSynchronizationRegistry));
}
}
@@ -122,7 +117,7 @@ public class TransactionRegistry {
* Thrown when the connection does not have a registered XAResource.
*/
public synchronized XAResource getXAResource(final Connection connection) throws SQLException {
- Objects.requireNonNull(connection, "connection is null");
+ Objects.requireNonNull(connection, "connection");
final Connection key = getConnectionKey(connection);
final XAResource xaResource = xaResources.get(key);
if (xaResource == null) {
@@ -141,8 +136,8 @@ public class TransactionRegistry {
* The XAResource which managed the connection within a transaction.
*/
public synchronized void registerConnection(final Connection connection, final XAResource xaResource) {
- Objects.requireNonNull(connection, "connection is null");
- Objects.requireNonNull(xaResource, "xaResource is null");
+ Objects.requireNonNull(connection, "connection");
+ Objects.requireNonNull(xaResource, "xaResource");
xaResources.put(connection, xaResource);
}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index b80ff1a41d..3bb40c0352 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -175,6 +175,10 @@
Update the internal fork of Apache Commons FileUpload to 34eb241
(2023-01-03, 2.0-SNAPSHOT). (markt)
</update>
+ <update>
+ Update the internal fork of Apache Commons DBCP to f131286 (2023-01-03,
+ 2.10.0-SNAPSHOT). (markt)
+ </update>
</changelog>
</subsection>
</section>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org