PoolableConnectionFactory.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.dbcp2;

  18. import java.sql.Connection;
  19. import java.sql.SQLException;
  20. import java.sql.Statement;
  21. import java.time.Duration;
  22. import java.util.Collection;
  23. import java.util.Objects;
  24. import java.util.concurrent.atomic.AtomicLong;

  25. import javax.management.MalformedObjectNameException;
  26. import javax.management.ObjectName;

  27. import org.apache.commons.logging.Log;
  28. import org.apache.commons.logging.LogFactory;
  29. import org.apache.commons.pool2.DestroyMode;
  30. import org.apache.commons.pool2.KeyedObjectPool;
  31. import org.apache.commons.pool2.ObjectPool;
  32. import org.apache.commons.pool2.PooledObject;
  33. import org.apache.commons.pool2.PooledObjectFactory;
  34. import org.apache.commons.pool2.impl.DefaultPooledObject;
  35. import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
  36. import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;

  37. /**
  38.  * A {@link PooledObjectFactory} that creates {@link PoolableConnection}s.
  39.  *
  40.  * @since 2.0
  41.  */
  42. public class PoolableConnectionFactory implements PooledObjectFactory<PoolableConnection> {

  43.     private static final Log log = LogFactory.getLog(PoolableConnectionFactory.class);

  44.     /**
  45.      * Internal constant to indicate the level is not set.
  46.      */
  47.     static final int UNKNOWN_TRANSACTION_ISOLATION = -1;

  48.     private final ConnectionFactory connectionFactory;

  49.     private final ObjectName dataSourceJmxObjectName;

  50.     private volatile String validationQuery;

  51.     private volatile Duration validationQueryTimeoutDuration = Duration.ofSeconds(-1);

  52.     private Collection<String> connectionInitSqls;

  53.     private Collection<String> disconnectionSqlCodes;

  54.     private Collection<String> disconnectionIgnoreSqlCodes;

  55.     private boolean fastFailValidation = true;

  56.     private volatile ObjectPool<PoolableConnection> pool;

  57.     private Boolean defaultReadOnly;

  58.     private Boolean defaultAutoCommit;

  59.     private boolean autoCommitOnReturn = true;

  60.     private boolean rollbackOnReturn = true;

  61.     private int defaultTransactionIsolation = UNKNOWN_TRANSACTION_ISOLATION;

  62.     private String defaultCatalog;

  63.     private String defaultSchema;

  64.     private boolean cacheState;

  65.     private boolean poolStatements;

  66.     private boolean clearStatementPoolOnReturn;

  67.     private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY;

  68.     private Duration maxConnDuration = Duration.ofMillis(-1);

  69.     private final AtomicLong connectionIndex = new AtomicLong();

  70.     private Duration defaultQueryTimeoutDuration;

  71.     /**
  72.      * Creates a new {@code PoolableConnectionFactory}.
  73.      *
  74.      * @param connFactory
  75.      *            the {@link ConnectionFactory} from which to obtain base {@link Connection}s
  76.      * @param dataSourceJmxObjectName
  77.      *            The JMX object name, may be null.
  78.      */
  79.     public PoolableConnectionFactory(final ConnectionFactory connFactory, final ObjectName dataSourceJmxObjectName) {
  80.         this.connectionFactory = connFactory;
  81.         this.dataSourceJmxObjectName = dataSourceJmxObjectName;
  82.     }

  83.     @Override
  84.     public void activateObject(final PooledObject<PoolableConnection> p) throws SQLException {

  85.         validateLifetime(p);

  86.         final PoolableConnection pConnection = p.getObject();
  87.         pConnection.activate();

  88.         if (defaultAutoCommit != null && pConnection.getAutoCommit() != defaultAutoCommit) {
  89.             pConnection.setAutoCommit(defaultAutoCommit);
  90.         }
  91.         if (defaultTransactionIsolation != UNKNOWN_TRANSACTION_ISOLATION
  92.                 && pConnection.getTransactionIsolation() != defaultTransactionIsolation) {
  93.             pConnection.setTransactionIsolation(defaultTransactionIsolation);
  94.         }
  95.         if (defaultReadOnly != null && pConnection.isReadOnly() != defaultReadOnly) {
  96.             pConnection.setReadOnly(defaultReadOnly);
  97.         }
  98.         if (defaultCatalog != null && !defaultCatalog.equals(pConnection.getCatalog())) {
  99.             pConnection.setCatalog(defaultCatalog);
  100.         }
  101.         if (defaultSchema != null && !defaultSchema.equals(Jdbc41Bridge.getSchema(pConnection))) {
  102.             Jdbc41Bridge.setSchema(pConnection, defaultSchema);
  103.         }
  104.         pConnection.setDefaultQueryTimeout(defaultQueryTimeoutDuration);
  105.     }

  106.     @Override
  107.     public void destroyObject(final PooledObject<PoolableConnection> p) throws SQLException {
  108.         p.getObject().reallyClose();
  109.     }

  110.     /**
  111.      * @since 2.9.0
  112.      */
  113.     @Override
  114.     public void destroyObject(final PooledObject<PoolableConnection> p, final DestroyMode mode) throws SQLException {
  115.         if (mode == DestroyMode.ABANDONED) {
  116.             Jdbc41Bridge.abort(p.getObject().getInnermostDelegate(), Runnable::run);
  117.         } else {
  118.             p.getObject().reallyClose();
  119.         }
  120.     }

  121.     /**
  122.      * Gets the cache state to propagate in {@link #makeObject()}.
  123.      *
  124.      * @return The cache state.
  125.      * @since 2.6.0.
  126.      */
  127.     public boolean getCacheState() {
  128.         return cacheState;
  129.     }

  130.     /**
  131.      * Gets the connection factory.
  132.      *
  133.      * @return The connection factory.
  134.      * @since 2.6.0.
  135.      */
  136.     public ConnectionFactory getConnectionFactory() {
  137.         return connectionFactory;
  138.     }

  139.     /**
  140.      * Gets how many connections were created in {@link #makeObject()}.
  141.      *
  142.      * @return the connection count.
  143.      */
  144.     protected AtomicLong getConnectionIndex() {
  145.         return connectionIndex;
  146.     }

  147.     /**
  148.      * Gets the collection of initialization SQL statements.
  149.      *
  150.      * @return The collection of initialization SQL statements.
  151.      * @since 2.6.0
  152.      */
  153.     public Collection<String> getConnectionInitSqls() {
  154.         return connectionInitSqls;
  155.     }

  156.     /**
  157.      * Gets data source JMX ObjectName.
  158.      *
  159.      * @return The data source JMX ObjectName.
  160.      * @since 2.6.0.
  161.      */
  162.     public ObjectName getDataSourceJmxName() {
  163.         return dataSourceJmxObjectName;
  164.     }

  165.     /**
  166.      * Gets the data source JMX ObjectName.
  167.      *
  168.      * @return The data source JMX ObjectName.
  169.      * @since 2.6.0
  170.      */
  171.     public ObjectName getDataSourceJmxObjectName() {
  172.         return dataSourceJmxObjectName;
  173.     }

  174.     /**
  175.      * Gets the Default auto-commit value.
  176.      *
  177.      * @return The default auto-commit value.
  178.      * @since 2.6.0
  179.      */
  180.     public Boolean getDefaultAutoCommit() {
  181.         return defaultAutoCommit;
  182.     }

  183.     /**
  184.      * Gets the default catalog.
  185.      *
  186.      * @return The default catalog.
  187.      * @since 2.6.0
  188.      */
  189.     public String getDefaultCatalog() {
  190.         return defaultCatalog;
  191.     }

  192.     /**
  193.      * Gets the default query timeout in seconds.
  194.      *
  195.      * @return The default query timeout in seconds.
  196.      * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}.
  197.      */
  198.     @Deprecated
  199.     public Integer getDefaultQueryTimeout() {
  200.         return getDefaultQueryTimeoutSeconds();
  201.     }

  202.     /**
  203.      * Gets the default query timeout Duration.
  204.      *
  205.      * @return The default query timeout Duration.
  206.      * @since 2.10.0
  207.      */
  208.     public Duration getDefaultQueryTimeoutDuration() {
  209.         return defaultQueryTimeoutDuration;
  210.     }

  211.     /**
  212.      * Gets the default query timeout in seconds.
  213.      *
  214.      * @return The default query timeout in seconds.
  215.      * @since 2.6.0
  216.      * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}.
  217.      */
  218.     @Deprecated
  219.     public Integer getDefaultQueryTimeoutSeconds() {
  220.         return defaultQueryTimeoutDuration == null ? null : (int) defaultQueryTimeoutDuration.getSeconds();
  221.     }

  222.     /**
  223.      * Gets the default read-only-value.
  224.      *
  225.      * @return The default read-only-value.
  226.      * @since 2.6.0
  227.      */
  228.     public Boolean getDefaultReadOnly() {
  229.         return defaultReadOnly;
  230.     }

  231.     /**
  232.      * Gets the default schema.
  233.      *
  234.      * @return The default schema.
  235.      * @since 2.6.0
  236.      */
  237.     public String getDefaultSchema() {
  238.         return defaultSchema;
  239.     }

  240.     /**
  241.      * Gets the default transaction isolation.
  242.      *
  243.      * @return The default transaction isolation.
  244.      * @since 2.6.0
  245.      */
  246.     public int getDefaultTransactionIsolation() {
  247.         return defaultTransactionIsolation;
  248.     }

  249.     /**
  250.      * Gets the collection of SQL State codes that are not considered fatal disconnection codes.
  251.      * <p>
  252.      * This method returns the collection of SQL State codes that have been set to be ignored when
  253.      * determining if a {@link SQLException} signals a disconnection. These codes are excluded from
  254.      * being treated as fatal even if they match the typical disconnection criteria.
  255.      * </p>
  256.      *
  257.      * @return a {@link Collection} of SQL State codes that should be ignored for disconnection checks.
  258.      * @since 2.13.0
  259.      */
  260.     public Collection<String> getDisconnectionIgnoreSqlCodes() {
  261.         return disconnectionIgnoreSqlCodes;
  262.     }

  263.     /**
  264.      * Gets SQL State codes considered to signal fatal conditions.
  265.      * <p>
  266.      * Overrides the defaults in {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with
  267.      * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #isFastFailValidation()} is
  268.      * {@code true}, whenever connections created by this factory generate exceptions with SQL State codes in this list,
  269.      * they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at isValid or
  270.      * validation query).
  271.      * </p>
  272.      * <p>
  273.      * If {@link #isFastFailValidation()} is {@code false} setting this property has no effect.
  274.      * </p>
  275.      *
  276.      * @return SQL State codes overriding defaults
  277.      * @since 2.1
  278.      */
  279.     public Collection<String> getDisconnectionSqlCodes() {
  280.         return disconnectionSqlCodes;
  281.     }

  282.     /**
  283.      * Gets the Maximum connection duration.
  284.      *
  285.      * @return Maximum connection duration.
  286.      * @since 2.10.0
  287.      */
  288.     public Duration getMaxConnDuration() {
  289.         return maxConnDuration;
  290.     }

  291.     /**
  292.      * Gets the Maximum connection lifetime in milliseconds.
  293.      *
  294.      * @return Maximum connection lifetime in milliseconds.
  295.      * @since 2.6.0
  296.      */
  297.     public long getMaxConnLifetimeMillis() {
  298.         return maxConnDuration.toMillis();
  299.     }

  300.     /**
  301.      * Gets the maximum number of open prepared statements.
  302.      *
  303.      * @return The maximum number of open prepared statements.
  304.      */
  305.     protected int getMaxOpenPreparedStatements() {
  306.         return maxOpenPreparedStatements;
  307.     }

  308.     /**
  309.      * Returns the {@link ObjectPool} in which {@link Connection}s are pooled.
  310.      *
  311.      * @return the connection pool
  312.      */
  313.     public synchronized ObjectPool<PoolableConnection> getPool() {
  314.         return pool;
  315.     }

  316.     /**
  317.      * Tests whether to pool statements.
  318.      *
  319.      * @return Whether to pool statements.
  320.      * @since 2.6.0.
  321.      */
  322.     public boolean getPoolStatements() {
  323.         return poolStatements;
  324.     }

  325.     /**
  326.      * Gets the validation query.
  327.      *
  328.      * @return Validation query.
  329.      * @since 2.6.0
  330.      */
  331.     public String getValidationQuery() {
  332.         return validationQuery;
  333.     }

  334.     /**
  335.      * Gets the query timeout in seconds.
  336.      *
  337.      * @return Validation query timeout in seconds.
  338.      * @since 2.10.0
  339.      */
  340.     public Duration getValidationQueryTimeoutDuration() {
  341.         return validationQueryTimeoutDuration;
  342.     }

  343.     /**
  344.      * Gets the query timeout in seconds.
  345.      *
  346.      * @return Validation query timeout in seconds.
  347.      * @since 2.6.0
  348.      * @deprecated Use {@link #getValidationQueryTimeoutDuration()}.
  349.      */
  350.     @Deprecated
  351.     public int getValidationQueryTimeoutSeconds() {
  352.         return (int) validationQueryTimeoutDuration.getSeconds();
  353.     }

  354.     /**
  355.      * Initializes the given connection with the collection of SQL statements set in {@link #setConnectionInitSql(Collection)}.
  356.      *
  357.      * @param conn the connection to initialize.
  358.      * @throws SQLException if a database access error occurs or this method is called on a closed connection.
  359.      * @see #setConnectionInitSql(Collection)
  360.      */
  361.     protected void initializeConnection(final Connection conn) throws SQLException {
  362.         final Collection<String> sqls = connectionInitSqls;
  363.         if (conn.isClosed()) {
  364.             throw new SQLException("initializeConnection: connection closed");
  365.         }
  366.         if (!Utils.isEmpty(sqls)) {
  367.             try (Statement statement = conn.createStatement()) {
  368.                 for (final String sql : sqls) {
  369.                     statement.execute(Objects.requireNonNull(sql, "null connectionInitSqls element"));
  370.                 }
  371.             }
  372.         }
  373.     }

  374.     /**
  375.      * Tests whether to set auto-commit on {@link #passivateObject(PooledObject)}.
  376.      *
  377.      * @return Whether to set auto-commit on {@link #passivateObject(PooledObject)}.
  378.      * @since 2.6.0
  379.      */
  380.     public boolean isAutoCommitOnReturn() {
  381.         return autoCommitOnReturn;
  382.     }

  383.     /**
  384.      * Tests whether to set auto-commit on {@link #passivateObject(PooledObject)}.
  385.      *
  386.      * @return Whether to set auto-commit on {@link #passivateObject(PooledObject)}.
  387.      * @deprecated Use {@link #isAutoCommitOnReturn()}.
  388.      */
  389.     @Deprecated
  390.     public boolean isEnableAutoCommitOnReturn() {
  391.         return autoCommitOnReturn;
  392.     }

  393.     /**
  394.      * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with
  395.      * SQL State indicating fatal disconnection errors.
  396.      *
  397.      * @return true if connections created by this factory will fast fail validation.
  398.      * @see #setDisconnectionSqlCodes(Collection)
  399.      * @since 2.1
  400.      * @since 2.5.0 Defaults to true, previous versions defaulted to false.
  401.      */
  402.     public boolean isFastFailValidation() {
  403.         return fastFailValidation;
  404.     }

  405.     /**
  406.      * Tests whether to rollback on return.
  407.      *
  408.      * @return Whether to rollback on return.
  409.      */
  410.     public boolean isRollbackOnReturn() {
  411.         return rollbackOnReturn;
  412.     }

  413.     @Override
  414.     public PooledObject<PoolableConnection> makeObject() throws SQLException {
  415.         Connection conn = connectionFactory.createConnection();
  416.         if (conn == null) {
  417.             throw new IllegalStateException("Connection factory returned null from createConnection");
  418.         }
  419.         try {
  420.             initializeConnection(conn);
  421.         } catch (final SQLException e) {
  422.             // Make sure the connection is closed
  423.             Utils.closeQuietly((AutoCloseable) conn);
  424.             // Rethrow original exception so it is visible to caller
  425.             throw e;
  426.         }

  427.         final long connIndex = connectionIndex.getAndIncrement();

  428.         if (poolStatements) {
  429.             conn = new PoolingConnection(conn);
  430.             final GenericKeyedObjectPoolConfig<DelegatingPreparedStatement> config = new GenericKeyedObjectPoolConfig<>();
  431.             config.setMaxTotalPerKey(-1);
  432.             config.setBlockWhenExhausted(false);
  433.             config.setMaxWait(Duration.ZERO);
  434.             config.setMaxIdlePerKey(1);
  435.             config.setMaxTotal(maxOpenPreparedStatements);
  436.             if (dataSourceJmxObjectName != null) {
  437.                 final StringBuilder base = new StringBuilder(dataSourceJmxObjectName.toString());
  438.                 base.append(Constants.JMX_CONNECTION_BASE_EXT);
  439.                 base.append(connIndex);
  440.                 config.setJmxNameBase(base.toString());
  441.                 config.setJmxNamePrefix(Constants.JMX_STATEMENT_POOL_PREFIX);
  442.             } else {
  443.                 config.setJmxEnabled(false);
  444.             }
  445.             final PoolingConnection poolingConn = (PoolingConnection) conn;
  446.             final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>(poolingConn, config);
  447.             poolingConn.setStatementPool(stmtPool);
  448.             poolingConn.setClearStatementPoolOnReturn(clearStatementPoolOnReturn);
  449.             poolingConn.setCacheState(cacheState);
  450.         }

  451.         // Register this connection with JMX
  452.         final ObjectName connJmxName;
  453.         if (dataSourceJmxObjectName == null) {
  454.             connJmxName = null;
  455.         } else {
  456.             final String name = dataSourceJmxObjectName.toString() + Constants.JMX_CONNECTION_BASE_EXT + connIndex;
  457.             try {
  458.                 connJmxName = new ObjectName(name);
  459.             } catch (final MalformedObjectNameException e) {
  460.                 Utils.closeQuietly((AutoCloseable) conn);
  461.                 throw new SQLException(name, e);
  462.             }
  463.         }

  464.         final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName,
  465.                 disconnectionSqlCodes, disconnectionIgnoreSqlCodes, fastFailValidation);
  466.         pc.setCacheState(cacheState);

  467.         return new DefaultPooledObject<>(pc);
  468.     }

  469.     @Override
  470.     public void passivateObject(final PooledObject<PoolableConnection> p) throws SQLException {

  471.         validateLifetime(p);

  472.         final PoolableConnection conn = p.getObject();
  473.         Boolean connAutoCommit = null;
  474.         if (rollbackOnReturn) {
  475.             connAutoCommit = conn.getAutoCommit();
  476.             if (!connAutoCommit && !conn.isReadOnly()) {
  477.                 conn.rollback();
  478.             }
  479.         }

  480.         conn.clearWarnings();

  481.         // DBCP-97 / DBCP-399 / DBCP-351 Idle connections in the pool should
  482.         // have autoCommit enabled
  483.         if (autoCommitOnReturn) {
  484.             if (connAutoCommit == null) {
  485.                 connAutoCommit = conn.getAutoCommit();
  486.             }
  487.             if (!connAutoCommit) {
  488.                 conn.setAutoCommit(true);
  489.             }
  490.         }

  491.         conn.passivate();
  492.     }

  493.     /**
  494.      * Sets whether to set auto-commit on {@link #passivateObject(PooledObject)}.
  495.      *
  496.      * @param autoCommitOnReturn whether to set auto-commit.
  497.      */
  498.     public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) {
  499.         this.autoCommitOnReturn = autoCommitOnReturn;
  500.     }

  501.     /**
  502.      * Sets the cache state to propagate in {@link #makeObject()}.
  503.      *
  504.      * @param cacheState the cache state to propagate.
  505.      */
  506.     public void setCacheState(final boolean cacheState) {
  507.         this.cacheState = cacheState;
  508.     }

  509.     /**
  510.      * Sets whether the pool of statements (which was enabled with {@link #setPoolStatements(boolean)}) should
  511.      * be cleared when the connection is returned to its pool. Default is false.
  512.      *
  513.      * @param clearStatementPoolOnReturn clear or not
  514.      * @since 2.8.0
  515.      */
  516.     public void setClearStatementPoolOnReturn(final boolean clearStatementPoolOnReturn) {
  517.         this.clearStatementPoolOnReturn = clearStatementPoolOnReturn;
  518.     }

  519.     /**
  520.      * Sets the SQL statements I use to initialize newly created {@link Connection}s. Using {@code null} turns off
  521.      * connection initialization.
  522.      *
  523.      * @param connectionInitSqls
  524.      *            SQL statement to initialize {@link Connection}s.
  525.      */
  526.     public void setConnectionInitSql(final Collection<String> connectionInitSqls) {
  527.         this.connectionInitSqls = connectionInitSqls;
  528.     }
  529.     /**
  530.      * Sets the default "auto commit" setting for borrowed {@link Connection}s
  531.      *
  532.      * @param defaultAutoCommit
  533.      *            the default "auto commit" setting for borrowed {@link Connection}s
  534.      */
  535.     public void setDefaultAutoCommit(final Boolean defaultAutoCommit) {
  536.         this.defaultAutoCommit = defaultAutoCommit;
  537.     }

  538.     /**
  539.      * Sets the default "catalog" setting for borrowed {@link Connection}s
  540.      *
  541.      * @param defaultCatalog
  542.      *            the default "catalog" setting for borrowed {@link Connection}s
  543.      */
  544.     public void setDefaultCatalog(final String defaultCatalog) {
  545.         this.defaultCatalog = defaultCatalog;
  546.     }

  547.     /**
  548.      * Sets the query timeout Duration.
  549.      *
  550.      * @param defaultQueryTimeoutDuration the query timeout Duration.
  551.      * @since 2.10.0
  552.      */
  553.     public void setDefaultQueryTimeout(final Duration defaultQueryTimeoutDuration) {
  554.         this.defaultQueryTimeoutDuration = defaultQueryTimeoutDuration;
  555.     }

  556.     /**
  557.      * Sets the query timeout in seconds.
  558.      *
  559.      * @param defaultQueryTimeoutSeconds the query timeout in seconds.
  560.      * @deprecated Use {@link #setDefaultQueryTimeout(Duration)}.
  561.      */
  562.     @Deprecated
  563.     public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) {
  564.         this.defaultQueryTimeoutDuration = defaultQueryTimeoutSeconds == null ? null : Duration.ofSeconds(defaultQueryTimeoutSeconds);
  565.     }

  566.     /**
  567.      * Sets the default "read only" setting for borrowed {@link Connection}s
  568.      *
  569.      * @param defaultReadOnly
  570.      *            the default "read only" setting for borrowed {@link Connection}s
  571.      */
  572.     public void setDefaultReadOnly(final Boolean defaultReadOnly) {
  573.         this.defaultReadOnly = defaultReadOnly;
  574.     }

  575.     /**
  576.      * Sets the default "schema" setting for borrowed {@link Connection}s
  577.      *
  578.      * @param defaultSchema
  579.      *            the default "schema" setting for borrowed {@link Connection}s
  580.      * @since 2.5.0
  581.      */
  582.     public void setDefaultSchema(final String defaultSchema) {
  583.         this.defaultSchema = defaultSchema;
  584.     }

  585.     /**
  586.      * Sets the default "Transaction Isolation" setting for borrowed {@link Connection}s
  587.      *
  588.      * @param defaultTransactionIsolation
  589.      *            the default "Transaction Isolation" setting for returned {@link Connection}s
  590.      */
  591.     public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) {
  592.         this.defaultTransactionIsolation = defaultTransactionIsolation;
  593.     }

  594.     /**
  595.      * Sets the disconnection SQL codes to ignore.
  596.      *
  597.      * @param disconnectionIgnoreSqlCodes
  598.      *            The collection of SQL State codes to be ignored.
  599.      * @see #getDisconnectionIgnoreSqlCodes()
  600.      * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionSqlCodes}.
  601.      * @since 2.13.0
  602.      */
  603.     public void setDisconnectionIgnoreSqlCodes(final Collection<String> disconnectionIgnoreSqlCodes) {
  604.         Utils.checkSqlCodes(disconnectionIgnoreSqlCodes, this.disconnectionSqlCodes);
  605.         this.disconnectionIgnoreSqlCodes = disconnectionIgnoreSqlCodes;
  606.     }

  607.     /**
  608.      * Sets the disconnection SQL codes.
  609.      *
  610.      * @param disconnectionSqlCodes
  611.      *            The disconnection SQL codes.
  612.      * @see #getDisconnectionSqlCodes()
  613.      * @since 2.1
  614.      * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionIgnoreSqlCodes}.
  615.      */
  616.     public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) {
  617.         Utils.checkSqlCodes(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes);
  618.         this.disconnectionSqlCodes = disconnectionSqlCodes;
  619.     }

  620.     /**
  621.      * Sets whether to set auto-commit on {@link #passivateObject(PooledObject)}.
  622.      *
  623.      * @param autoCommitOnReturn whether to set auto-commit.
  624.      */
  625.     @Deprecated
  626.     public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) {
  627.         this.autoCommitOnReturn = autoCommitOnReturn;
  628.     }

  629.     /**
  630.      * @see #isFastFailValidation()
  631.      * @param fastFailValidation
  632.      *            true means connections created by this factory will fast fail validation
  633.      * @since 2.1
  634.      */
  635.     public void setFastFailValidation(final boolean fastFailValidation) {
  636.         this.fastFailValidation = fastFailValidation;
  637.     }

  638.     /**
  639.      * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation,
  640.      * passivation and validation. A value of zero or less indicates an infinite lifetime. The default value is -1.
  641.      *
  642.      * @param maxConnDuration
  643.      *            The maximum lifetime in milliseconds.
  644.      * @since 2.10.0
  645.      */
  646.     public void setMaxConn(final Duration maxConnDuration) {
  647.         this.maxConnDuration = maxConnDuration;
  648.     }

  649.     /**
  650.      * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation,
  651.      * passivation and validation. A value of zero or less indicates an infinite lifetime. The default value is -1.
  652.      *
  653.      * @param maxConnLifetimeMillis
  654.      *            The maximum lifetime in milliseconds.
  655.      * @deprecated Use {@link #setMaxConn(Duration)}.
  656.      */
  657.     @Deprecated
  658.     public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) {
  659.         this.maxConnDuration = Duration.ofMillis(maxConnLifetimeMillis);
  660.     }

  661.     /**
  662.      * Sets the maximum number of open prepared statements.
  663.      *
  664.      * @param maxOpenPreparedStatements
  665.      *            The maximum number of open prepared statements.
  666.      */
  667.     public void setMaxOpenPreparedStatements(final int maxOpenPreparedStatements) {
  668.         this.maxOpenPreparedStatements = maxOpenPreparedStatements;
  669.     }

  670.     /**
  671.      * Deprecated due to typo in method name.
  672.      *
  673.      * @param maxOpenPreparedStatements
  674.      *            The maximum number of open prepared statements.
  675.      * @deprecated Use {@link #setMaxOpenPreparedStatements(int)}.
  676.      */
  677.     @Deprecated // Due to typo in method name.
  678.     public void setMaxOpenPrepatedStatements(final int maxOpenPreparedStatements) {
  679.         setMaxOpenPreparedStatements(maxOpenPreparedStatements);
  680.     }

  681.     /**
  682.      * Sets the {@link ObjectPool} in which to pool {@link Connection}s.
  683.      *
  684.      * @param pool
  685.      *            the {@link ObjectPool} in which to pool those {@link Connection}s
  686.      */
  687.     public synchronized void setPool(final ObjectPool<PoolableConnection> pool) {
  688.         if (null != this.pool && pool != this.pool) {
  689.             Utils.closeQuietly(this.pool);
  690.         }
  691.         this.pool = pool;
  692.     }

  693.     /**
  694.      * Sets whether to pool statements.
  695.      *
  696.      * @param poolStatements whether to pool statements.
  697.      */
  698.     public void setPoolStatements(final boolean poolStatements) {
  699.         this.poolStatements = poolStatements;
  700.     }

  701.     /**
  702.      * Sets whether to rollback on return.
  703.      *
  704.      * @param rollbackOnReturn whether to rollback on return.
  705.      */
  706.     public void setRollbackOnReturn(final boolean rollbackOnReturn) {
  707.         this.rollbackOnReturn = rollbackOnReturn;
  708.     }

  709.     /**
  710.      * Sets the query I use to {@link #validateObject validate} {@link Connection}s. Should return at least one row. If
  711.      * not specified, {@link Connection#isValid(int)} will be used to validate connections.
  712.      *
  713.      * @param validationQuery
  714.      *            a query to use to {@link #validateObject validate} {@link Connection}s.
  715.      */
  716.     public void setValidationQuery(final String validationQuery) {
  717.         this.validationQuery = validationQuery;
  718.     }

  719.     /**
  720.      * Sets the validation query timeout, the amount of time, that connection validation will wait for a response from the
  721.      * database when executing a validation query. Use a value less than or equal to 0 for no timeout.
  722.      *
  723.      * @param validationQueryTimeoutDuration new validation query timeout duration.
  724.      * @since 2.10.0
  725.      */
  726.     public void setValidationQueryTimeout(final Duration validationQueryTimeoutDuration) {
  727.         this.validationQueryTimeoutDuration = validationQueryTimeoutDuration;
  728.     }

  729.     /**
  730.      * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a
  731.      * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout.
  732.      *
  733.      * @param validationQueryTimeoutSeconds
  734.      *            new validation query timeout value in seconds
  735.      * @deprecated {@link #setValidationQueryTimeout(Duration)}.
  736.      */
  737.     @Deprecated
  738.     public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) {
  739.         this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds);
  740.     }

  741.     /**
  742.      * Validates the given connection if it is open.
  743.      *
  744.      * @param conn the connection to validate.
  745.      * @throws SQLException if the connection is closed or validate fails.
  746.      */
  747.     public void validateConnection(final PoolableConnection conn) throws SQLException {
  748.         if (conn.isClosed()) {
  749.             throw new SQLException("validateConnection: connection closed");
  750.         }
  751.         conn.validate(validationQuery, validationQueryTimeoutDuration);
  752.     }

  753.     private void validateLifetime(final PooledObject<PoolableConnection> p) throws LifetimeExceededException {
  754.         Utils.validateLifetime(p, maxConnDuration);
  755.     }

  756.     @Override
  757.     public boolean validateObject(final PooledObject<PoolableConnection> p) {
  758.         try {
  759.             validateLifetime(p);
  760.             validateConnection(p.getObject());
  761.             return true;
  762.         } catch (final Exception e) {
  763.             if (log.isDebugEnabled()) {
  764.                 log.debug(Utils.getMessage("poolableConnectionFactory.validateObject.fail"), e);
  765.             }
  766.             return false;
  767.         }
  768.     }
  769. }