You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/07/02 16:59:57 UTC
[commons-dbcp] 02/02: Add Utils.getDisconnectionSqlCodes() and Utils.DISCONNECTION_SQL_CODES.
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-dbcp.git
commit 2fe86559b5df58a6907903e70a0814943f675850
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sat Jul 2 12:59:49 2022 -0400
Add Utils.getDisconnectionSqlCodes() and Utils.DISCONNECTION_SQL_CODES.
---
src/changes/changes.xml | 3 +
src/conf/findbugs-exclude-filter.xml | 6 +
.../org/apache/commons/dbcp2/BasicDataSource.java | 2 +-
.../apache/commons/dbcp2/PoolableConnection.java | 8 +-
.../commons/dbcp2/PoolableConnectionFactory.java | 1540 ++++++++++----------
src/main/java/org/apache/commons/dbcp2/Utils.java | 20 +
6 files changed, 804 insertions(+), 775 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index d3971a98..0233572f 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -101,6 +101,9 @@ The <action> type attribute can be add,update,fix,remove.
<action dev="ggregory" type="add" due-to="Gary Gregory">
Add PMD check to default Maven goal.
</action>
+ <action dev="ggregory" type="add" due-to="Gary Gregory">
+ Add Utils.getDisconnectionSqlCodes() and Utils.DISCONNECTION_SQL_CODES.
+ </action>
<!-- UPDATE -->
<action dev="ggregory" type="update" due-to="Dependabot, Gary Gregory">
Bump actions/cache from 2.1.6 to 3.0.4 #147, #176.
diff --git a/src/conf/findbugs-exclude-filter.xml b/src/conf/findbugs-exclude-filter.xml
index 89ba4256..1d06564d 100644
--- a/src/conf/findbugs-exclude-filter.xml
+++ b/src/conf/findbugs-exclude-filter.xml
@@ -70,4 +70,10 @@
<Field name="pools" />
<Bug pattern="MS_MUTABLE_COLLECTION_PKGPROTECT" />
</Match>
+ <Match>
+ <!-- Depreacted -->
+ <Class name="org.apache.commons.dbcp2.Utils" />
+ <Field name="DISCONNECTION_SQL_CODES" />
+ <Bug pattern="MS_MUTABLE_COLLECTION_PKGPROTECT" />
+ </Match>
</FindBugsFilter>
diff --git a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
index 9878ff9b..3763d1d1 100644
--- a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
+++ b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
@@ -1961,7 +1961,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
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java
index ed5a2a3d..411f19f2 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java
@@ -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;
@@ -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/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
index 46355e89..dd2234ca 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
@@ -1,770 +1,770 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.dbcp2;
-
-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.ObjectName;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.commons.pool2.DestroyMode;
-import org.apache.commons.pool2.KeyedObjectPool;
-import org.apache.commons.pool2.ObjectPool;
-import org.apache.commons.pool2.PooledObject;
-import org.apache.commons.pool2.PooledObjectFactory;
-import org.apache.commons.pool2.impl.DefaultPooledObject;
-import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
-import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
-
-/**
- * A {@link PooledObjectFactory} that creates {@link PoolableConnection}s.
- *
- * @since 2.0
- */
-public class PoolableConnectionFactory implements PooledObjectFactory<PoolableConnection> {
-
- private static final Log log = LogFactory.getLog(PoolableConnectionFactory.class);
-
- /**
- * Internal constant to indicate the level is not set.
- */
- static final int UNKNOWN_TRANSACTION_ISOLATION = -1;
-
- private final ConnectionFactory connectionFactory;
-
- private final ObjectName dataSourceJmxObjectName;
-
- private volatile String validationQuery;
-
- private volatile Duration validationQueryTimeoutDuration = Duration.ofSeconds(-1);
-
- private Collection<String> connectionInitSqls;
-
- private Collection<String> disconnectionSqlCodes;
-
- private boolean fastFailValidation = true;
-
- private volatile ObjectPool<PoolableConnection> pool;
-
- private Boolean defaultReadOnly;
-
- private Boolean defaultAutoCommit;
-
- private boolean autoCommitOnReturn = true;
-
- private boolean rollbackOnReturn = true;
-
- private int defaultTransactionIsolation = UNKNOWN_TRANSACTION_ISOLATION;
-
- private String defaultCatalog;
-
- private String defaultSchema;
-
- private boolean cacheState;
-
- private boolean poolStatements;
-
- private boolean clearStatementPoolOnReturn;
-
- private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY;
-
- private Duration maxConnDuration = Duration.ofMillis(-1);
-
- private final AtomicLong connectionIndex = new AtomicLong();
-
- private Duration defaultQueryTimeoutDuration;
-
- /**
- * Creates a new {@code PoolableConnectionFactory}.
- *
- * @param connFactory
- * the {@link ConnectionFactory} from which to obtain base {@link Connection}s
- * @param dataSourceJmxObjectName
- * The JMX object name, may be null.
- */
- public PoolableConnectionFactory(final ConnectionFactory connFactory, final ObjectName dataSourceJmxObjectName) {
- this.connectionFactory = connFactory;
- this.dataSourceJmxObjectName = dataSourceJmxObjectName;
- }
-
- @Override
- public void activateObject(final PooledObject<PoolableConnection> p) throws Exception {
-
- validateLifetime(p);
-
- final PoolableConnection pConnection = p.getObject();
- pConnection.activate();
-
- if (defaultAutoCommit != null && pConnection.getAutoCommit() != defaultAutoCommit) {
- pConnection.setAutoCommit(defaultAutoCommit);
- }
- if (defaultTransactionIsolation != UNKNOWN_TRANSACTION_ISOLATION
- && pConnection.getTransactionIsolation() != defaultTransactionIsolation) {
- pConnection.setTransactionIsolation(defaultTransactionIsolation);
- }
- if (defaultReadOnly != null && pConnection.isReadOnly() != defaultReadOnly) {
- pConnection.setReadOnly(defaultReadOnly);
- }
- if (defaultCatalog != null && !defaultCatalog.equals(pConnection.getCatalog())) {
- pConnection.setCatalog(defaultCatalog);
- }
- if (defaultSchema != null && !defaultSchema.equals(Jdbc41Bridge.getSchema(pConnection))) {
- Jdbc41Bridge.setSchema(pConnection, defaultSchema);
- }
- pConnection.setDefaultQueryTimeout(defaultQueryTimeoutDuration);
- }
-
- @Override
- public void destroyObject(final PooledObject<PoolableConnection> p) throws Exception {
- p.getObject().reallyClose();
- }
-
- /**
- * @since 2.9.0
- */
- @Override
- public void destroyObject(final PooledObject<PoolableConnection> p, final DestroyMode mode) throws Exception {
- if (mode == DestroyMode.ABANDONED) {
- p.getObject().getInnermostDelegate().abort(Runnable::run);
- } else {
- p.getObject().reallyClose();
- }
- }
-
- /**
- * Gets the cache state.
- *
- * @return The cache state.
- * @since Made public in 2.6.0.
- */
- public boolean getCacheState() {
- return cacheState;
- }
-
- /**
- * Gets the connection factory.
- *
- * @return The connection factory.
- * @since Made public in 2.6.0.
- */
- public ConnectionFactory getConnectionFactory() {
- return connectionFactory;
- }
-
- protected AtomicLong getConnectionIndex() {
- return connectionIndex;
- }
-
- /**
- * @return The collection of initialization SQL statements.
- * @since 2.6.0
- */
- public Collection<String> getConnectionInitSqls() {
- return connectionInitSqls;
- }
-
- /**
- * @return The data source JMX ObjectName
- * @since Made public in 2.6.0.
- */
- public ObjectName getDataSourceJmxName() {
- return dataSourceJmxObjectName;
- }
-
- /**
- * @return The data source JMS ObjectName.
- * @since 2.6.0
- */
- public ObjectName getDataSourceJmxObjectName() {
- return dataSourceJmxObjectName;
- }
-
- /**
- * @return Default auto-commit value.
- * @since 2.6.0
- */
- public Boolean getDefaultAutoCommit() {
- return defaultAutoCommit;
- }
-
- /**
- * @return Default catalog.
- * @since 2.6.0
- */
- public String getDefaultCatalog() {
- return defaultCatalog;
- }
-
- /**
- * @return Default query timeout in seconds.
- * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}.
- */
- @Deprecated
- public Integer getDefaultQueryTimeout() {
- return getDefaultQueryTimeoutSeconds();
- }
-
- /**
- * Gets the default query timeout Duration.
- *
- * @return Default query timeout Duration.
- * @since 2.10.0
- */
- public Duration getDefaultQueryTimeoutDuration() {
- return defaultQueryTimeoutDuration;
- }
-
- /**
- * @return Default query timeout in seconds.
- * @since 2.6.0
- * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}.
- */
- @Deprecated
- public Integer getDefaultQueryTimeoutSeconds() {
- return defaultQueryTimeoutDuration == null ? null : (int) defaultQueryTimeoutDuration.getSeconds();
- }
-
- /**
- * @return Default read-only-value.
- * @since 2.6.0
- */
- public Boolean getDefaultReadOnly() {
- return defaultReadOnly;
- }
-
- /**
- * @return Default schema.
- * @since 2.6.0
- */
- public String getDefaultSchema() {
- return defaultSchema;
- }
-
- /**
- * @return Default transaction isolation.
- * @since 2.6.0
- */
- public int getDefaultTransactionIsolation() {
- return defaultTransactionIsolation;
- }
-
- /**
- * SQL_STATE codes considered to signal fatal conditions.
- * <p>
- * Overrides the defaults in {@link Utils#DISCONNECTION_SQL_CODES} (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
- * validation query).
- * </p>
- * <p>
- * If {@link #isFastFailValidation()} is {@code false} setting this property has no effect.
- * </p>
- *
- * @return SQL_STATE codes overriding defaults
- * @since 2.1
- */
- public Collection<String> getDisconnectionSqlCodes() {
- return disconnectionSqlCodes;
- }
-
- /**
- * Gets the Maximum connection duration.
- *
- * @return Maximum connection duration.
- * @since 2.10.0
- */
- public Duration getMaxConnDuration() {
- return maxConnDuration;
- }
-
- /**
- * Gets the Maximum connection lifetime in milliseconds.
- *
- * @return Maximum connection lifetime in milliseconds.
- * @since 2.6.0
- */
- public long getMaxConnLifetimeMillis() {
- return maxConnDuration.toMillis();
- }
-
- protected int getMaxOpenPreparedStatements() {
- return maxOpenPreparedStatements;
- }
- /**
- * Returns the {@link ObjectPool} in which {@link Connection}s are pooled.
- *
- * @return the connection pool
- */
- public synchronized ObjectPool<PoolableConnection> getPool() {
- return pool;
- }
- /**
- * @return Whether to pool statements.
- * @since Made public in 2.6.0.
- */
- public boolean getPoolStatements() {
- return poolStatements;
- }
- /**
- * @return Validation query.
- * @since 2.6.0
- */
- public String getValidationQuery() {
- return validationQuery;
- }
-
- /**
- * Gets the query timeout in seconds.
- *
- * @return Validation query timeout in seconds.
- * @since 2.10.0
- */
- public Duration getValidationQueryTimeoutDuration() {
- return validationQueryTimeoutDuration;
- }
-
- /**
- * Gets the query timeout in seconds.
- *
- * @return Validation query timeout in seconds.
- * @since 2.6.0
- * @deprecated Use {@link #getValidationQueryTimeoutDuration()}.
- */
- @Deprecated
- public int getValidationQueryTimeoutSeconds() {
- return (int) validationQueryTimeoutDuration.getSeconds();
- }
-
- protected void initializeConnection(final Connection conn) throws SQLException {
- final Collection<String> sqls = connectionInitSqls;
- if (conn.isClosed()) {
- throw new SQLException("initializeConnection: connection closed");
- }
- if (null != sqls) {
- try (Statement stmt = conn.createStatement()) {
- for (final String sql : sqls) {
- Objects.requireNonNull(sql, "null connectionInitSqls element");
- stmt.execute(sql);
- }
- }
- }
- }
-
- /**
- * @return Whether to auto-commit on return.
- * @since 2.6.0
- */
- public boolean isAutoCommitOnReturn() {
- return autoCommitOnReturn;
- }
-
- /**
- * @return Whether to auto-commit on return.
- * @deprecated Use {@link #isAutoCommitOnReturn()}.
- */
- @Deprecated
- public boolean isEnableAutoCommitOnReturn() {
- return autoCommitOnReturn;
- }
-
- /**
- * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with
- * SQL_STATE indicating fatal disconnection errors.
- *
- * @return true if connections created by this factory will fast fail validation.
- * @see #setDisconnectionSqlCodes(Collection)
- * @since 2.1
- * @since 2.5.0 Defaults to true, previous versions defaulted to false.
- */
- public boolean isFastFailValidation() {
- return fastFailValidation;
- }
-
- /**
- * @return Whether to rollback on return.
- */
- public boolean isRollbackOnReturn() {
- return rollbackOnReturn;
- }
-
- @Override
- public PooledObject<PoolableConnection> makeObject() throws Exception {
- Connection conn = connectionFactory.createConnection();
- if (conn == null) {
- throw new IllegalStateException("Connection factory returned null from createConnection");
- }
- try {
- initializeConnection(conn);
- } catch (final SQLException sqle) {
- // Make sure the connection is closed
- Utils.closeQuietly((AutoCloseable) conn);
- // Rethrow original exception so it is visible to caller
- throw sqle;
- }
-
- final long connIndex = connectionIndex.getAndIncrement();
-
- if (poolStatements) {
- conn = new PoolingConnection(conn);
- final GenericKeyedObjectPoolConfig<DelegatingPreparedStatement> config = new GenericKeyedObjectPoolConfig<>();
- config.setMaxTotalPerKey(-1);
- config.setBlockWhenExhausted(false);
- config.setMaxWait(Duration.ZERO);
- config.setMaxIdlePerKey(1);
- config.setMaxTotal(maxOpenPreparedStatements);
- if (dataSourceJmxObjectName != null) {
- final StringBuilder base = new StringBuilder(dataSourceJmxObjectName.toString());
- base.append(Constants.JMX_CONNECTION_BASE_EXT);
- base.append(connIndex);
- config.setJmxNameBase(base.toString());
- config.setJmxNamePrefix(Constants.JMX_STATEMENT_POOL_PREFIX);
- } else {
- config.setJmxEnabled(false);
- }
- final PoolingConnection poolingConn = (PoolingConnection) conn;
- final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>(
- poolingConn, config);
- poolingConn.setStatementPool(stmtPool);
- poolingConn.setClearStatementPoolOnReturn(clearStatementPoolOnReturn);
- poolingConn.setCacheState(cacheState);
- }
-
- // Register this connection with JMX
- final ObjectName connJmxName;
- if (dataSourceJmxObjectName == null) {
- connJmxName = null;
- } else {
- connJmxName = new ObjectName(
- dataSourceJmxObjectName.toString() + Constants.JMX_CONNECTION_BASE_EXT + connIndex);
- }
-
- 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 {
-
- validateLifetime(p);
-
- final PoolableConnection conn = p.getObject();
- Boolean connAutoCommit = null;
- if (rollbackOnReturn) {
- connAutoCommit = conn.getAutoCommit();
- if (!connAutoCommit && !conn.isReadOnly()) {
- conn.rollback();
- }
- }
-
- conn.clearWarnings();
-
- // DBCP-97 / DBCP-399 / DBCP-351 Idle connections in the pool should
- // have autoCommit enabled
- if (autoCommitOnReturn) {
- if (connAutoCommit == null) {
- connAutoCommit = conn.getAutoCommit();
- }
- if (!connAutoCommit) {
- conn.setAutoCommit(true);
- }
- }
-
- conn.passivate();
- }
-
- public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) {
- this.autoCommitOnReturn = autoCommitOnReturn;
- }
-
- public void setCacheState(final boolean cacheState) {
- this.cacheState = cacheState;
- }
-
- /**
- * Sets whether the pool of statements (which was enabled with {@link #setPoolStatements(boolean)}) should
- * be cleared when the connection is returned to its pool. Default is false.
- *
- * @param clearStatementPoolOnReturn clear or not
- * @since 2.8.0
- */
- public void setClearStatementPoolOnReturn(final boolean clearStatementPoolOnReturn) {
- this.clearStatementPoolOnReturn = clearStatementPoolOnReturn;
- }
-
- /**
- * Sets the SQL statements I use to initialize newly created {@link Connection}s. Using {@code null} turns off
- * connection initialization.
- *
- * @param connectionInitSqls
- * SQL statement to initialize {@link Connection}s.
- */
- public void setConnectionInitSql(final Collection<String> connectionInitSqls) {
- this.connectionInitSqls = connectionInitSqls;
- }
- /**
- * Sets the default "auto commit" setting for borrowed {@link Connection}s
- *
- * @param defaultAutoCommit
- * the default "auto commit" setting for borrowed {@link Connection}s
- */
- public void setDefaultAutoCommit(final Boolean defaultAutoCommit) {
- this.defaultAutoCommit = defaultAutoCommit;
- }
-
- /**
- * Sets the default "catalog" setting for borrowed {@link Connection}s
- *
- * @param defaultCatalog
- * the default "catalog" setting for borrowed {@link Connection}s
- */
- public void setDefaultCatalog(final String defaultCatalog) {
- this.defaultCatalog = defaultCatalog;
- }
-
- /**
- * Sets the query timeout Duration.
- *
- * @param defaultQueryTimeoutDuration the query timeout Duration.
- * @since 2.10.0
- */
- public void setDefaultQueryTimeout(final Duration defaultQueryTimeoutDuration) {
- this.defaultQueryTimeoutDuration = defaultQueryTimeoutDuration;
- }
-
- /**
- * Sets the query timeout in seconds.
- *
- * @param defaultQueryTimeoutSeconds the query timeout in seconds.
- * @deprecated Use {@link #setDefaultQueryTimeout(Duration)}.
- */
- @Deprecated
- public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) {
- this.defaultQueryTimeoutDuration = defaultQueryTimeoutSeconds == null ? null : Duration.ofSeconds(defaultQueryTimeoutSeconds);
- }
-
- /**
- * Sets the default "read only" setting for borrowed {@link Connection}s
- *
- * @param defaultReadOnly
- * the default "read only" setting for borrowed {@link Connection}s
- */
- public void setDefaultReadOnly(final Boolean defaultReadOnly) {
- this.defaultReadOnly = defaultReadOnly;
- }
-
- /**
- * Sets the default "schema" setting for borrowed {@link Connection}s
- *
- * @param defaultSchema
- * the default "schema" setting for borrowed {@link Connection}s
- * @since 2.5.0
- */
- public void setDefaultSchema(final String defaultSchema) {
- this.defaultSchema = defaultSchema;
- }
-
- /**
- * Sets the default "Transaction Isolation" setting for borrowed {@link Connection}s
- *
- * @param defaultTransactionIsolation
- * the default "Transaction Isolation" setting for returned {@link Connection}s
- */
- public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) {
- this.defaultTransactionIsolation = defaultTransactionIsolation;
- }
-
- /**
- * @param disconnectionSqlCodes
- * The disconnection SQL codes.
- * @see #getDisconnectionSqlCodes()
- * @since 2.1
- */
- public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) {
- this.disconnectionSqlCodes = disconnectionSqlCodes;
- }
-
- /**
- * @param autoCommitOnReturn Whether to auto-commit on return.
- * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}.
- */
- @Deprecated
- public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) {
- this.autoCommitOnReturn = autoCommitOnReturn;
- }
-
- /**
- * @see #isFastFailValidation()
- * @param fastFailValidation
- * true means connections created by this factory will fast fail validation
- * @since 2.1
- */
- public void setFastFailValidation(final boolean fastFailValidation) {
- this.fastFailValidation = fastFailValidation;
- }
-
- /**
- * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation,
- * passivation and validation. A value of zero or less indicates an infinite lifetime. The default value is -1.
- *
- * @param maxConnDuration
- * The maximum lifetime in milliseconds.
- * @since 2.10.0
- */
- public void setMaxConn(final Duration maxConnDuration) {
- this.maxConnDuration = maxConnDuration;
- }
-
- /**
- * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation,
- * passivation and validation. A value of zero or less indicates an infinite lifetime. The default value is -1.
- *
- * @param maxConnLifetimeMillis
- * The maximum lifetime in milliseconds.
- * @deprecated Use {@link #setMaxConn(Duration)}.
- */
- @Deprecated
- public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) {
- this.maxConnDuration = Duration.ofMillis(maxConnLifetimeMillis);
- }
-
- /**
- * Sets the maximum number of open prepared statements.
- *
- * @param maxOpenPreparedStatements
- * The maximum number of open prepared statements.
- */
- public void setMaxOpenPreparedStatements(final int maxOpenPreparedStatements) {
- this.maxOpenPreparedStatements = maxOpenPreparedStatements;
- }
-
- /**
- * Deprecated due to typo in method name.
- *
- * @param maxOpenPreparedStatements
- * The maximum number of open prepared statements.
- * @deprecated Use {@link #setMaxOpenPreparedStatements(int)}.
- */
- @Deprecated // Due to typo in method name.
- public void setMaxOpenPrepatedStatements(final int maxOpenPreparedStatements) {
- setMaxOpenPreparedStatements(maxOpenPreparedStatements);
- }
-
- /**
- * Sets the {@link ObjectPool} in which to pool {@link Connection}s.
- *
- * @param pool
- * the {@link ObjectPool} in which to pool those {@link Connection}s
- */
- public synchronized void setPool(final ObjectPool<PoolableConnection> pool) {
- if (null != this.pool && pool != this.pool) {
- Utils.closeQuietly(this.pool);
- }
- this.pool = pool;
- }
-
- public void setPoolStatements(final boolean poolStatements) {
- this.poolStatements = poolStatements;
- }
-
- public void setRollbackOnReturn(final boolean rollbackOnReturn) {
- this.rollbackOnReturn = rollbackOnReturn;
- }
-
- /**
- * Sets the query I use to {@link #validateObject validate} {@link Connection}s. Should return at least one row. If
- * not specified, {@link Connection#isValid(int)} will be used to validate connections.
- *
- * @param validationQuery
- * a query to use to {@link #validateObject validate} {@link Connection}s.
- */
- public void setValidationQuery(final String validationQuery) {
- this.validationQuery = validationQuery;
- }
-
- /**
- * Sets the validation query timeout, the amount of time, that connection validation will wait for a response from the
- * database when executing a validation query. Use a value less than or equal to 0 for no timeout.
- *
- * @param validationQueryTimeoutDuration new validation query timeout duration.
- * @since 2.10.0
- */
- public void setValidationQueryTimeout(final Duration validationQueryTimeoutDuration) {
- this.validationQueryTimeoutDuration = validationQueryTimeoutDuration;
- }
-
- /**
- * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a
- * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout.
- *
- * @param validationQueryTimeoutSeconds
- * new validation query timeout value in seconds
- * @deprecated {@link #setValidationQueryTimeout(Duration)}.
- */
- @Deprecated
- public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) {
- this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds);
- }
-
- /**
- * Validates the given connection if it is open.
- *
- * @param conn the connection to validate.
- * @throws SQLException if the connection is closed or validate fails.
- */
- public void validateConnection(final PoolableConnection conn) throws SQLException {
- if (conn.isClosed()) {
- throw new SQLException("validateConnection: connection closed");
- }
- 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));
- }
- }
- }
-
- @Override
- public boolean validateObject(final PooledObject<PoolableConnection> p) {
- try {
- validateLifetime(p);
-
- validateConnection(p.getObject());
- return true;
- } catch (final Exception e) {
- if (log.isDebugEnabled()) {
- log.debug(Utils.getMessage("poolableConnectionFactory.validateObject.fail"), e);
- }
- return false;
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.dbcp2;
+
+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.ObjectName;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.pool2.DestroyMode;
+import org.apache.commons.pool2.KeyedObjectPool;
+import org.apache.commons.pool2.ObjectPool;
+import org.apache.commons.pool2.PooledObject;
+import org.apache.commons.pool2.PooledObjectFactory;
+import org.apache.commons.pool2.impl.DefaultPooledObject;
+import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
+import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
+
+/**
+ * A {@link PooledObjectFactory} that creates {@link PoolableConnection}s.
+ *
+ * @since 2.0
+ */
+public class PoolableConnectionFactory implements PooledObjectFactory<PoolableConnection> {
+
+ private static final Log log = LogFactory.getLog(PoolableConnectionFactory.class);
+
+ /**
+ * Internal constant to indicate the level is not set.
+ */
+ static final int UNKNOWN_TRANSACTION_ISOLATION = -1;
+
+ private final ConnectionFactory connectionFactory;
+
+ private final ObjectName dataSourceJmxObjectName;
+
+ private volatile String validationQuery;
+
+ private volatile Duration validationQueryTimeoutDuration = Duration.ofSeconds(-1);
+
+ private Collection<String> connectionInitSqls;
+
+ private Collection<String> disconnectionSqlCodes;
+
+ private boolean fastFailValidation = true;
+
+ private volatile ObjectPool<PoolableConnection> pool;
+
+ private Boolean defaultReadOnly;
+
+ private Boolean defaultAutoCommit;
+
+ private boolean autoCommitOnReturn = true;
+
+ private boolean rollbackOnReturn = true;
+
+ private int defaultTransactionIsolation = UNKNOWN_TRANSACTION_ISOLATION;
+
+ private String defaultCatalog;
+
+ private String defaultSchema;
+
+ private boolean cacheState;
+
+ private boolean poolStatements;
+
+ private boolean clearStatementPoolOnReturn;
+
+ private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY;
+
+ private Duration maxConnDuration = Duration.ofMillis(-1);
+
+ private final AtomicLong connectionIndex = new AtomicLong();
+
+ private Duration defaultQueryTimeoutDuration;
+
+ /**
+ * Creates a new {@code PoolableConnectionFactory}.
+ *
+ * @param connFactory
+ * the {@link ConnectionFactory} from which to obtain base {@link Connection}s
+ * @param dataSourceJmxObjectName
+ * The JMX object name, may be null.
+ */
+ public PoolableConnectionFactory(final ConnectionFactory connFactory, final ObjectName dataSourceJmxObjectName) {
+ this.connectionFactory = connFactory;
+ this.dataSourceJmxObjectName = dataSourceJmxObjectName;
+ }
+
+ @Override
+ public void activateObject(final PooledObject<PoolableConnection> p) throws Exception {
+
+ validateLifetime(p);
+
+ final PoolableConnection pConnection = p.getObject();
+ pConnection.activate();
+
+ if (defaultAutoCommit != null && pConnection.getAutoCommit() != defaultAutoCommit) {
+ pConnection.setAutoCommit(defaultAutoCommit);
+ }
+ if (defaultTransactionIsolation != UNKNOWN_TRANSACTION_ISOLATION
+ && pConnection.getTransactionIsolation() != defaultTransactionIsolation) {
+ pConnection.setTransactionIsolation(defaultTransactionIsolation);
+ }
+ if (defaultReadOnly != null && pConnection.isReadOnly() != defaultReadOnly) {
+ pConnection.setReadOnly(defaultReadOnly);
+ }
+ if (defaultCatalog != null && !defaultCatalog.equals(pConnection.getCatalog())) {
+ pConnection.setCatalog(defaultCatalog);
+ }
+ if (defaultSchema != null && !defaultSchema.equals(Jdbc41Bridge.getSchema(pConnection))) {
+ Jdbc41Bridge.setSchema(pConnection, defaultSchema);
+ }
+ pConnection.setDefaultQueryTimeout(defaultQueryTimeoutDuration);
+ }
+
+ @Override
+ public void destroyObject(final PooledObject<PoolableConnection> p) throws Exception {
+ p.getObject().reallyClose();
+ }
+
+ /**
+ * @since 2.9.0
+ */
+ @Override
+ public void destroyObject(final PooledObject<PoolableConnection> p, final DestroyMode mode) throws Exception {
+ if (mode == DestroyMode.ABANDONED) {
+ p.getObject().getInnermostDelegate().abort(Runnable::run);
+ } else {
+ p.getObject().reallyClose();
+ }
+ }
+
+ /**
+ * Gets the cache state.
+ *
+ * @return The cache state.
+ * @since Made public in 2.6.0.
+ */
+ public boolean getCacheState() {
+ return cacheState;
+ }
+
+ /**
+ * Gets the connection factory.
+ *
+ * @return The connection factory.
+ * @since Made public in 2.6.0.
+ */
+ public ConnectionFactory getConnectionFactory() {
+ return connectionFactory;
+ }
+
+ protected AtomicLong getConnectionIndex() {
+ return connectionIndex;
+ }
+
+ /**
+ * @return The collection of initialization SQL statements.
+ * @since 2.6.0
+ */
+ public Collection<String> getConnectionInitSqls() {
+ return connectionInitSqls;
+ }
+
+ /**
+ * @return The data source JMX ObjectName
+ * @since Made public in 2.6.0.
+ */
+ public ObjectName getDataSourceJmxName() {
+ return dataSourceJmxObjectName;
+ }
+
+ /**
+ * @return The data source JMS ObjectName.
+ * @since 2.6.0
+ */
+ public ObjectName getDataSourceJmxObjectName() {
+ return dataSourceJmxObjectName;
+ }
+
+ /**
+ * @return Default auto-commit value.
+ * @since 2.6.0
+ */
+ public Boolean getDefaultAutoCommit() {
+ return defaultAutoCommit;
+ }
+
+ /**
+ * @return Default catalog.
+ * @since 2.6.0
+ */
+ public String getDefaultCatalog() {
+ return defaultCatalog;
+ }
+
+ /**
+ * @return Default query timeout in seconds.
+ * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}.
+ */
+ @Deprecated
+ public Integer getDefaultQueryTimeout() {
+ return getDefaultQueryTimeoutSeconds();
+ }
+
+ /**
+ * Gets the default query timeout Duration.
+ *
+ * @return Default query timeout Duration.
+ * @since 2.10.0
+ */
+ public Duration getDefaultQueryTimeoutDuration() {
+ return defaultQueryTimeoutDuration;
+ }
+
+ /**
+ * @return Default query timeout in seconds.
+ * @since 2.6.0
+ * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}.
+ */
+ @Deprecated
+ public Integer getDefaultQueryTimeoutSeconds() {
+ return defaultQueryTimeoutDuration == null ? null : (int) defaultQueryTimeoutDuration.getSeconds();
+ }
+
+ /**
+ * @return Default read-only-value.
+ * @since 2.6.0
+ */
+ public Boolean getDefaultReadOnly() {
+ return defaultReadOnly;
+ }
+
+ /**
+ * @return Default schema.
+ * @since 2.6.0
+ */
+ public String getDefaultSchema() {
+ return defaultSchema;
+ }
+
+ /**
+ * @return Default transaction isolation.
+ * @since 2.6.0
+ */
+ public int getDefaultTransactionIsolation() {
+ return defaultTransactionIsolation;
+ }
+
+ /**
+ * SQL_STATE codes considered to signal fatal conditions.
+ * <p>
+ * 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
+ * validation query).
+ * </p>
+ * <p>
+ * If {@link #isFastFailValidation()} is {@code false} setting this property has no effect.
+ * </p>
+ *
+ * @return SQL_STATE codes overriding defaults
+ * @since 2.1
+ */
+ public Collection<String> getDisconnectionSqlCodes() {
+ return disconnectionSqlCodes;
+ }
+
+ /**
+ * Gets the Maximum connection duration.
+ *
+ * @return Maximum connection duration.
+ * @since 2.10.0
+ */
+ public Duration getMaxConnDuration() {
+ return maxConnDuration;
+ }
+
+ /**
+ * Gets the Maximum connection lifetime in milliseconds.
+ *
+ * @return Maximum connection lifetime in milliseconds.
+ * @since 2.6.0
+ */
+ public long getMaxConnLifetimeMillis() {
+ return maxConnDuration.toMillis();
+ }
+
+ protected int getMaxOpenPreparedStatements() {
+ return maxOpenPreparedStatements;
+ }
+ /**
+ * Returns the {@link ObjectPool} in which {@link Connection}s are pooled.
+ *
+ * @return the connection pool
+ */
+ public synchronized ObjectPool<PoolableConnection> getPool() {
+ return pool;
+ }
+ /**
+ * @return Whether to pool statements.
+ * @since Made public in 2.6.0.
+ */
+ public boolean getPoolStatements() {
+ return poolStatements;
+ }
+ /**
+ * @return Validation query.
+ * @since 2.6.0
+ */
+ public String getValidationQuery() {
+ return validationQuery;
+ }
+
+ /**
+ * Gets the query timeout in seconds.
+ *
+ * @return Validation query timeout in seconds.
+ * @since 2.10.0
+ */
+ public Duration getValidationQueryTimeoutDuration() {
+ return validationQueryTimeoutDuration;
+ }
+
+ /**
+ * Gets the query timeout in seconds.
+ *
+ * @return Validation query timeout in seconds.
+ * @since 2.6.0
+ * @deprecated Use {@link #getValidationQueryTimeoutDuration()}.
+ */
+ @Deprecated
+ public int getValidationQueryTimeoutSeconds() {
+ return (int) validationQueryTimeoutDuration.getSeconds();
+ }
+
+ protected void initializeConnection(final Connection conn) throws SQLException {
+ final Collection<String> sqls = connectionInitSqls;
+ if (conn.isClosed()) {
+ throw new SQLException("initializeConnection: connection closed");
+ }
+ if (null != sqls) {
+ try (Statement stmt = conn.createStatement()) {
+ for (final String sql : sqls) {
+ Objects.requireNonNull(sql, "null connectionInitSqls element");
+ stmt.execute(sql);
+ }
+ }
+ }
+ }
+
+ /**
+ * @return Whether to auto-commit on return.
+ * @since 2.6.0
+ */
+ public boolean isAutoCommitOnReturn() {
+ return autoCommitOnReturn;
+ }
+
+ /**
+ * @return Whether to auto-commit on return.
+ * @deprecated Use {@link #isAutoCommitOnReturn()}.
+ */
+ @Deprecated
+ public boolean isEnableAutoCommitOnReturn() {
+ return autoCommitOnReturn;
+ }
+
+ /**
+ * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with
+ * SQL_STATE indicating fatal disconnection errors.
+ *
+ * @return true if connections created by this factory will fast fail validation.
+ * @see #setDisconnectionSqlCodes(Collection)
+ * @since 2.1
+ * @since 2.5.0 Defaults to true, previous versions defaulted to false.
+ */
+ public boolean isFastFailValidation() {
+ return fastFailValidation;
+ }
+
+ /**
+ * @return Whether to rollback on return.
+ */
+ public boolean isRollbackOnReturn() {
+ return rollbackOnReturn;
+ }
+
+ @Override
+ public PooledObject<PoolableConnection> makeObject() throws Exception {
+ Connection conn = connectionFactory.createConnection();
+ if (conn == null) {
+ throw new IllegalStateException("Connection factory returned null from createConnection");
+ }
+ try {
+ initializeConnection(conn);
+ } catch (final SQLException sqle) {
+ // Make sure the connection is closed
+ Utils.closeQuietly((AutoCloseable) conn);
+ // Rethrow original exception so it is visible to caller
+ throw sqle;
+ }
+
+ final long connIndex = connectionIndex.getAndIncrement();
+
+ if (poolStatements) {
+ conn = new PoolingConnection(conn);
+ final GenericKeyedObjectPoolConfig<DelegatingPreparedStatement> config = new GenericKeyedObjectPoolConfig<>();
+ config.setMaxTotalPerKey(-1);
+ config.setBlockWhenExhausted(false);
+ config.setMaxWait(Duration.ZERO);
+ config.setMaxIdlePerKey(1);
+ config.setMaxTotal(maxOpenPreparedStatements);
+ if (dataSourceJmxObjectName != null) {
+ final StringBuilder base = new StringBuilder(dataSourceJmxObjectName.toString());
+ base.append(Constants.JMX_CONNECTION_BASE_EXT);
+ base.append(connIndex);
+ config.setJmxNameBase(base.toString());
+ config.setJmxNamePrefix(Constants.JMX_STATEMENT_POOL_PREFIX);
+ } else {
+ config.setJmxEnabled(false);
+ }
+ final PoolingConnection poolingConn = (PoolingConnection) conn;
+ final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>(
+ poolingConn, config);
+ poolingConn.setStatementPool(stmtPool);
+ poolingConn.setClearStatementPoolOnReturn(clearStatementPoolOnReturn);
+ poolingConn.setCacheState(cacheState);
+ }
+
+ // Register this connection with JMX
+ final ObjectName connJmxName;
+ if (dataSourceJmxObjectName == null) {
+ connJmxName = null;
+ } else {
+ connJmxName = new ObjectName(
+ dataSourceJmxObjectName.toString() + Constants.JMX_CONNECTION_BASE_EXT + connIndex);
+ }
+
+ 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 {
+
+ validateLifetime(p);
+
+ final PoolableConnection conn = p.getObject();
+ Boolean connAutoCommit = null;
+ if (rollbackOnReturn) {
+ connAutoCommit = conn.getAutoCommit();
+ if (!connAutoCommit && !conn.isReadOnly()) {
+ conn.rollback();
+ }
+ }
+
+ conn.clearWarnings();
+
+ // DBCP-97 / DBCP-399 / DBCP-351 Idle connections in the pool should
+ // have autoCommit enabled
+ if (autoCommitOnReturn) {
+ if (connAutoCommit == null) {
+ connAutoCommit = conn.getAutoCommit();
+ }
+ if (!connAutoCommit) {
+ conn.setAutoCommit(true);
+ }
+ }
+
+ conn.passivate();
+ }
+
+ public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) {
+ this.autoCommitOnReturn = autoCommitOnReturn;
+ }
+
+ public void setCacheState(final boolean cacheState) {
+ this.cacheState = cacheState;
+ }
+
+ /**
+ * Sets whether the pool of statements (which was enabled with {@link #setPoolStatements(boolean)}) should
+ * be cleared when the connection is returned to its pool. Default is false.
+ *
+ * @param clearStatementPoolOnReturn clear or not
+ * @since 2.8.0
+ */
+ public void setClearStatementPoolOnReturn(final boolean clearStatementPoolOnReturn) {
+ this.clearStatementPoolOnReturn = clearStatementPoolOnReturn;
+ }
+
+ /**
+ * Sets the SQL statements I use to initialize newly created {@link Connection}s. Using {@code null} turns off
+ * connection initialization.
+ *
+ * @param connectionInitSqls
+ * SQL statement to initialize {@link Connection}s.
+ */
+ public void setConnectionInitSql(final Collection<String> connectionInitSqls) {
+ this.connectionInitSqls = connectionInitSqls;
+ }
+ /**
+ * Sets the default "auto commit" setting for borrowed {@link Connection}s
+ *
+ * @param defaultAutoCommit
+ * the default "auto commit" setting for borrowed {@link Connection}s
+ */
+ public void setDefaultAutoCommit(final Boolean defaultAutoCommit) {
+ this.defaultAutoCommit = defaultAutoCommit;
+ }
+
+ /**
+ * Sets the default "catalog" setting for borrowed {@link Connection}s
+ *
+ * @param defaultCatalog
+ * the default "catalog" setting for borrowed {@link Connection}s
+ */
+ public void setDefaultCatalog(final String defaultCatalog) {
+ this.defaultCatalog = defaultCatalog;
+ }
+
+ /**
+ * Sets the query timeout Duration.
+ *
+ * @param defaultQueryTimeoutDuration the query timeout Duration.
+ * @since 2.10.0
+ */
+ public void setDefaultQueryTimeout(final Duration defaultQueryTimeoutDuration) {
+ this.defaultQueryTimeoutDuration = defaultQueryTimeoutDuration;
+ }
+
+ /**
+ * Sets the query timeout in seconds.
+ *
+ * @param defaultQueryTimeoutSeconds the query timeout in seconds.
+ * @deprecated Use {@link #setDefaultQueryTimeout(Duration)}.
+ */
+ @Deprecated
+ public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) {
+ this.defaultQueryTimeoutDuration = defaultQueryTimeoutSeconds == null ? null : Duration.ofSeconds(defaultQueryTimeoutSeconds);
+ }
+
+ /**
+ * Sets the default "read only" setting for borrowed {@link Connection}s
+ *
+ * @param defaultReadOnly
+ * the default "read only" setting for borrowed {@link Connection}s
+ */
+ public void setDefaultReadOnly(final Boolean defaultReadOnly) {
+ this.defaultReadOnly = defaultReadOnly;
+ }
+
+ /**
+ * Sets the default "schema" setting for borrowed {@link Connection}s
+ *
+ * @param defaultSchema
+ * the default "schema" setting for borrowed {@link Connection}s
+ * @since 2.5.0
+ */
+ public void setDefaultSchema(final String defaultSchema) {
+ this.defaultSchema = defaultSchema;
+ }
+
+ /**
+ * Sets the default "Transaction Isolation" setting for borrowed {@link Connection}s
+ *
+ * @param defaultTransactionIsolation
+ * the default "Transaction Isolation" setting for returned {@link Connection}s
+ */
+ public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) {
+ this.defaultTransactionIsolation = defaultTransactionIsolation;
+ }
+
+ /**
+ * @param disconnectionSqlCodes
+ * The disconnection SQL codes.
+ * @see #getDisconnectionSqlCodes()
+ * @since 2.1
+ */
+ public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) {
+ this.disconnectionSqlCodes = disconnectionSqlCodes;
+ }
+
+ /**
+ * @param autoCommitOnReturn Whether to auto-commit on return.
+ * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}.
+ */
+ @Deprecated
+ public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) {
+ this.autoCommitOnReturn = autoCommitOnReturn;
+ }
+
+ /**
+ * @see #isFastFailValidation()
+ * @param fastFailValidation
+ * true means connections created by this factory will fast fail validation
+ * @since 2.1
+ */
+ public void setFastFailValidation(final boolean fastFailValidation) {
+ this.fastFailValidation = fastFailValidation;
+ }
+
+ /**
+ * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation,
+ * passivation and validation. A value of zero or less indicates an infinite lifetime. The default value is -1.
+ *
+ * @param maxConnDuration
+ * The maximum lifetime in milliseconds.
+ * @since 2.10.0
+ */
+ public void setMaxConn(final Duration maxConnDuration) {
+ this.maxConnDuration = maxConnDuration;
+ }
+
+ /**
+ * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation,
+ * passivation and validation. A value of zero or less indicates an infinite lifetime. The default value is -1.
+ *
+ * @param maxConnLifetimeMillis
+ * The maximum lifetime in milliseconds.
+ * @deprecated Use {@link #setMaxConn(Duration)}.
+ */
+ @Deprecated
+ public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) {
+ this.maxConnDuration = Duration.ofMillis(maxConnLifetimeMillis);
+ }
+
+ /**
+ * Sets the maximum number of open prepared statements.
+ *
+ * @param maxOpenPreparedStatements
+ * The maximum number of open prepared statements.
+ */
+ public void setMaxOpenPreparedStatements(final int maxOpenPreparedStatements) {
+ this.maxOpenPreparedStatements = maxOpenPreparedStatements;
+ }
+
+ /**
+ * Deprecated due to typo in method name.
+ *
+ * @param maxOpenPreparedStatements
+ * The maximum number of open prepared statements.
+ * @deprecated Use {@link #setMaxOpenPreparedStatements(int)}.
+ */
+ @Deprecated // Due to typo in method name.
+ public void setMaxOpenPrepatedStatements(final int maxOpenPreparedStatements) {
+ setMaxOpenPreparedStatements(maxOpenPreparedStatements);
+ }
+
+ /**
+ * Sets the {@link ObjectPool} in which to pool {@link Connection}s.
+ *
+ * @param pool
+ * the {@link ObjectPool} in which to pool those {@link Connection}s
+ */
+ public synchronized void setPool(final ObjectPool<PoolableConnection> pool) {
+ if (null != this.pool && pool != this.pool) {
+ Utils.closeQuietly(this.pool);
+ }
+ this.pool = pool;
+ }
+
+ public void setPoolStatements(final boolean poolStatements) {
+ this.poolStatements = poolStatements;
+ }
+
+ public void setRollbackOnReturn(final boolean rollbackOnReturn) {
+ this.rollbackOnReturn = rollbackOnReturn;
+ }
+
+ /**
+ * Sets the query I use to {@link #validateObject validate} {@link Connection}s. Should return at least one row. If
+ * not specified, {@link Connection#isValid(int)} will be used to validate connections.
+ *
+ * @param validationQuery
+ * a query to use to {@link #validateObject validate} {@link Connection}s.
+ */
+ public void setValidationQuery(final String validationQuery) {
+ this.validationQuery = validationQuery;
+ }
+
+ /**
+ * Sets the validation query timeout, the amount of time, that connection validation will wait for a response from the
+ * database when executing a validation query. Use a value less than or equal to 0 for no timeout.
+ *
+ * @param validationQueryTimeoutDuration new validation query timeout duration.
+ * @since 2.10.0
+ */
+ public void setValidationQueryTimeout(final Duration validationQueryTimeoutDuration) {
+ this.validationQueryTimeoutDuration = validationQueryTimeoutDuration;
+ }
+
+ /**
+ * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a
+ * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout.
+ *
+ * @param validationQueryTimeoutSeconds
+ * new validation query timeout value in seconds
+ * @deprecated {@link #setValidationQueryTimeout(Duration)}.
+ */
+ @Deprecated
+ public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) {
+ this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds);
+ }
+
+ /**
+ * Validates the given connection if it is open.
+ *
+ * @param conn the connection to validate.
+ * @throws SQLException if the connection is closed or validate fails.
+ */
+ public void validateConnection(final PoolableConnection conn) throws SQLException {
+ if (conn.isClosed()) {
+ throw new SQLException("validateConnection: connection closed");
+ }
+ 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));
+ }
+ }
+ }
+
+ @Override
+ public boolean validateObject(final PooledObject<PoolableConnection> p) {
+ try {
+ validateLifetime(p);
+
+ validateConnection(p.getObject());
+ return true;
+ } catch (final Exception e) {
+ if (log.isDebugEnabled()) {
+ log.debug(Utils.getMessage("poolableConnectionFactory.validateObject.fail"), e);
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/org/apache/commons/dbcp2/Utils.java b/src/main/java/org/apache/commons/dbcp2/Utils.java
index 85ce3b90..8caf10d1 100644
--- a/src/main/java/org/apache/commons/dbcp2/Utils.java
+++ b/src/main/java/org/apache/commons/dbcp2/Utils.java
@@ -57,7 +57,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 = {};
@@ -149,6 +151,24 @@ 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
+ */
+ @SuppressWarnings("unchecked")
+ public static Set<String> getDisconnectionSqlCodes() {
+ return new HashSet<>(DISCONNECTION_SQL_CODES);
+ }
+
/**
* Gets the correct i18n message for the given key.
*