BasicDataSource.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.io.OutputStreamWriter;
  19. import java.io.PrintWriter;
  20. import java.nio.charset.StandardCharsets;
  21. import java.security.AccessController;
  22. import java.security.PrivilegedActionException;
  23. import java.security.PrivilegedExceptionAction;
  24. import java.sql.Connection;
  25. import java.sql.Driver;
  26. import java.sql.DriverManager;
  27. import java.sql.SQLException;
  28. import java.sql.SQLFeatureNotSupportedException;
  29. import java.time.Duration;
  30. import java.util.Collection;
  31. import java.util.Collections;
  32. import java.util.LinkedHashSet;
  33. import java.util.List;
  34. import java.util.Objects;
  35. import java.util.Properties;
  36. import java.util.Set;
  37. import java.util.function.BiConsumer;
  38. import java.util.logging.Logger;
  39. import java.util.stream.Collector;
  40. import java.util.stream.Collectors;
  41. import java.util.stream.Stream;

  42. import javax.management.MBeanRegistration;
  43. import javax.management.MBeanServer;
  44. import javax.management.MalformedObjectNameException;
  45. import javax.management.NotCompliantMBeanException;
  46. import javax.management.ObjectName;
  47. import javax.management.StandardMBean;
  48. import javax.sql.DataSource;

  49. import org.apache.commons.logging.Log;
  50. import org.apache.commons.logging.LogFactory;
  51. import org.apache.commons.pool2.PooledObject;
  52. import org.apache.commons.pool2.impl.AbandonedConfig;
  53. import org.apache.commons.pool2.impl.BaseObjectPoolConfig;
  54. import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
  55. import org.apache.commons.pool2.impl.GenericObjectPool;
  56. import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

  57. /**
  58.  * Basic implementation of {@code javax.sql.DataSource} that is configured via JavaBeans properties.
  59.  * <p>
  60.  * This is not the only way to combine the <em>commons-dbcp2</em> and <em>commons-pool2</em> packages, but provides a
  61.  * one-stop solution for basic requirements.
  62.  * </p>
  63.  *
  64.  * @since 2.0
  65.  */
  66. public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBeanRegistration, AutoCloseable {

  67.     private static final Log log = LogFactory.getLog(BasicDataSource.class);

  68.     static {
  69.         // Attempt to prevent deadlocks - see DBCP - 272
  70.         DriverManager.getDrivers();
  71.         try {
  72.             // Load classes now to prevent AccessControlExceptions later
  73.             // A number of classes are loaded when getConnection() is called
  74.             // but the following classes are not loaded and therefore require
  75.             // explicit loading.
  76.             if (Utils.isSecurityEnabled()) {
  77.                 final ClassLoader loader = BasicDataSource.class.getClassLoader();
  78.                 final String dbcpPackageName = BasicDataSource.class.getPackage().getName();
  79.                 loader.loadClass(dbcpPackageName + ".DelegatingCallableStatement");
  80.                 loader.loadClass(dbcpPackageName + ".DelegatingDatabaseMetaData");
  81.                 loader.loadClass(dbcpPackageName + ".DelegatingPreparedStatement");
  82.                 loader.loadClass(dbcpPackageName + ".DelegatingResultSet");
  83.                 loader.loadClass(dbcpPackageName + ".PoolableCallableStatement");
  84.                 loader.loadClass(dbcpPackageName + ".PoolablePreparedStatement");
  85.                 loader.loadClass(dbcpPackageName + ".PoolingConnection$StatementType");
  86.                 loader.loadClass(dbcpPackageName + ".PStmtKey");

  87.                 final String poolPackageName = PooledObject.class.getPackage().getName();
  88.                 loader.loadClass(poolPackageName + ".impl.LinkedBlockingDeque$Node");
  89.                 loader.loadClass(poolPackageName + ".impl.GenericKeyedObjectPool$ObjectDeque");
  90.             }
  91.         } catch (final ClassNotFoundException cnfe) {
  92.             throw new IllegalStateException("Unable to pre-load classes", cnfe);
  93.         }
  94.     }

  95.     /**
  96.      * Validates the given factory.
  97.      *
  98.      * @param connectionFactory the factory
  99.      * @throws SQLException Thrown by one of the factory methods while managing a temporary pooled object.
  100.      */
  101.     @SuppressWarnings("resource")
  102.     protected static void validateConnectionFactory(final PoolableConnectionFactory connectionFactory) throws SQLException {
  103.         PoolableConnection conn = null;
  104.         PooledObject<PoolableConnection> p = null;
  105.         try {
  106.             p = connectionFactory.makeObject();
  107.             conn = p.getObject();
  108.             connectionFactory.activateObject(p);
  109.             connectionFactory.validateConnection(conn);
  110.             connectionFactory.passivateObject(p);
  111.         } finally {
  112.             if (p != null) {
  113.                 connectionFactory.destroyObject(p);
  114.             }
  115.         }
  116.     }

  117.     /**
  118.      * The default auto-commit state of connections created by this pool.
  119.      */
  120.     private volatile Boolean defaultAutoCommit;

  121.     /**
  122.      * The default read-only state of connections created by this pool.
  123.      */
  124.     private transient Boolean defaultReadOnly;

  125.     /**
  126.      * The default TransactionIsolation state of connections created by this pool.
  127.      */
  128.     private volatile int defaultTransactionIsolation = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION;

  129.     private Duration defaultQueryTimeoutDuration;

  130.     /**
  131.      * The default "catalog" of connections created by this pool.
  132.      */
  133.     private volatile String defaultCatalog;

  134.     /**
  135.      * The default "schema" of connections created by this pool.
  136.      */
  137.     private volatile String defaultSchema;

  138.     /**
  139.      * The property that controls if the pooled connections cache some state rather than query the database for current
  140.      * state to improve performance.
  141.      */
  142.     private boolean cacheState = true;

  143.     /**
  144.      * The instance of the JDBC Driver to use.
  145.      */
  146.     private Driver driver;

  147.     /**
  148.      * The fully qualified Java class name of the JDBC driver to be used.
  149.      */
  150.     private String driverClassName;

  151.     /**
  152.      * The class loader instance to use to load the JDBC driver. If not specified, {@link Class#forName(String)} is used
  153.      * to load the JDBC driver. If specified, {@link Class#forName(String, boolean, ClassLoader)} is used.
  154.      */
  155.     private ClassLoader driverClassLoader;

  156.     /**
  157.      * True means that borrowObject returns the most recently used ("last in") connection in the pool (if there are idle
  158.      * connections available). False means that the pool behaves as a FIFO queue - connections are taken from the idle
  159.      * instance pool in the order that they are returned to the pool.
  160.      */
  161.     private boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO;

  162.     /**
  163.      * The maximum number of active connections that can be allocated from this pool at the same time, or negative for
  164.      * no limit.
  165.      */
  166.     private int maxTotal = GenericObjectPoolConfig.DEFAULT_MAX_TOTAL;

  167.     /**
  168.      * The maximum number of connections that can remain idle in the pool, without extra ones being destroyed, or
  169.      * negative for no limit. If maxIdle is set too low on heavily loaded systems it is possible you will see
  170.      * connections being closed and almost immediately new connections being opened. This is a result of the active
  171.      * threads momentarily closing connections faster than they are opening them, causing the number of idle connections
  172.      * to rise above maxIdle. The best value for maxIdle for heavily loaded system will vary but the default is a good
  173.      * starting point.
  174.      */
  175.     private int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;

  176.     /**
  177.      * The minimum number of active connections that can remain idle in the pool, without extra ones being created when
  178.      * the evictor runs, or 0 to create none. The pool attempts to ensure that minIdle connections are available when
  179.      * the idle object evictor runs. The value of this property has no effect unless
  180.      * {@link #durationBetweenEvictionRuns} has a positive value.
  181.      */
  182.     private int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;

  183.     /**
  184.      * The initial number of connections that are created when the pool is started.
  185.      */
  186.     private int initialSize;

  187.     /**
  188.      * The maximum Duration that the pool will wait (when there are no available connections) for a
  189.      * connection to be returned before throwing an exception, or <= 0 to wait indefinitely.
  190.      */
  191.     private Duration maxWaitDuration = BaseObjectPoolConfig.DEFAULT_MAX_WAIT;

  192.     /**
  193.      * Prepared statement pooling for this pool. When this property is set to {@code true} both PreparedStatements
  194.      * and CallableStatements are pooled.
  195.      */
  196.     private boolean poolPreparedStatements;

  197.     private boolean clearStatementPoolOnReturn;

  198.     /**
  199.      * <p>
  200.      * The maximum number of open statements that can be allocated from the statement pool at the same time, or negative
  201.      * for no limit. Since a connection usually only uses one or two statements at a time, this is mostly used to help
  202.      * detect resource leaks.
  203.      * </p>
  204.      * <p>
  205.      * Note: As of version 1.3, CallableStatements (those produced by {@link Connection#prepareCall}) are pooled along
  206.      * with PreparedStatements (produced by {@link Connection#prepareStatement}) and
  207.      * {@code maxOpenPreparedStatements} limits the total number of prepared or callable statements that may be in
  208.      * use at a given time.
  209.      * </p>
  210.      */
  211.     private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL;

  212.     /**
  213.      * The indication of whether objects will be validated as soon as they have been created by the pool. If the object
  214.      * fails to validate, the borrow operation that triggered the creation will fail.
  215.      */
  216.     private boolean testOnCreate;

  217.     /**
  218.      * The indication of whether objects will be validated before being borrowed from the pool. If the object fails to
  219.      * validate, it will be dropped from the pool, and we will attempt to borrow another.
  220.      */
  221.     private boolean testOnBorrow = true;

  222.     /**
  223.      * The indication of whether objects will be validated before being returned to the pool.
  224.      */
  225.     private boolean testOnReturn;

  226.     /**
  227.      * The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no idle
  228.      * object evictor thread will be run.
  229.      */
  230.     private Duration durationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS;

  231.     /**
  232.      * The number of objects to examine during each run of the idle object evictor thread (if any).
  233.      */
  234.     private int numTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;

  235.     /**
  236.      * The minimum amount of time an object may sit idle in the pool before it is eligible for eviction by the idle
  237.      * object evictor (if any).
  238.      */
  239.     private Duration minEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION;

  240.     /**
  241.      * The minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the idle
  242.      * object evictor, with the extra condition that at least "minIdle" connections remain in the pool. Note that
  243.      * {@code minEvictableIdleTimeMillis} takes precedence over this parameter. See
  244.      * {@link #getSoftMinEvictableIdleDuration()}.
  245.      */
  246.     private Duration softMinEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION;

  247.     private String evictionPolicyClassName = BaseObjectPoolConfig.DEFAULT_EVICTION_POLICY_CLASS_NAME;

  248.     /**
  249.      * The indication of whether objects will be validated by the idle object evictor (if any). If an object fails to
  250.      * validate, it will be dropped from the pool.
  251.      */
  252.     private boolean testWhileIdle;

  253.     /**
  254.      * The connection password to be passed to our JDBC driver to establish a connection.
  255.      */
  256.     private volatile String password;

  257.     /**
  258.      * The connection string to be passed to our JDBC driver to establish a connection.
  259.      */
  260.     private String connectionString;

  261.     /**
  262.      * The connection user name to be passed to our JDBC driver to establish a connection.
  263.      */
  264.     private String userName;

  265.     /**
  266.      * The SQL query that will be used to validate connections from this pool before returning them to the caller. If
  267.      * specified, this query <strong>MUST</strong> be an SQL SELECT statement that returns at least one row. If not
  268.      * specified, {@link Connection#isValid(int)} will be used to validate connections.
  269.      */
  270.     private volatile String validationQuery;

  271.     /**
  272.      * Timeout in seconds before connection validation queries fail.
  273.      */
  274.     private volatile Duration validationQueryTimeoutDuration = Duration.ofSeconds(-1);

  275.     /**
  276.      * The fully qualified Java class name of a {@link ConnectionFactory} implementation.
  277.      */
  278.     private String connectionFactoryClassName;

  279.     /**
  280.      * These SQL statements run once after a Connection is created.
  281.      * <p>
  282.      * This property can be used for example to run ALTER SESSION SET NLS_SORT=XCYECH in an Oracle Database only once
  283.      * after connection creation.
  284.      * </p>
  285.      */
  286.     private volatile List<String> connectionInitSqls;

  287.     /**
  288.      * Controls access to the underlying connection.
  289.      */
  290.     private boolean accessToUnderlyingConnectionAllowed;

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

  292.     private boolean logExpiredConnections = true;

  293.     private String jmxName;

  294.     private boolean registerConnectionMBean = true;

  295.     private boolean autoCommitOnReturn = true;

  296.     private boolean rollbackOnReturn = true;

  297.     private volatile Set<String> disconnectionSqlCodes;

  298.     /**
  299.      * A collection of SQL State codes that are not considered fatal disconnection codes.
  300.      *
  301.      * @since 2.13.0
  302.      */
  303.     private volatile Set<String> disconnectionIgnoreSqlCodes;

  304.     private boolean fastFailValidation;

  305.     /**
  306.      * The object pool that internally manages our connections.
  307.      */
  308.     private volatile GenericObjectPool<PoolableConnection> connectionPool;

  309.     /**
  310.      * The connection properties that will be sent to our JDBC driver when establishing new connections.
  311.      * <strong>NOTE</strong> - The "user" and "password" properties will be passed explicitly, so they do not need to be
  312.      * included here.
  313.      */
  314.     private Properties connectionProperties = new Properties();

  315.     /**
  316.      * The data source we will use to manage connections. This object should be acquired <strong>ONLY</strong> by calls
  317.      * to the {@code createDataSource()} method.
  318.      */
  319.     private volatile DataSource dataSource;

  320.     /**
  321.      * The PrintWriter to which log messages should be directed.
  322.      */
  323.     private volatile PrintWriter logWriter = new PrintWriter(
  324.             new OutputStreamWriter(System.out, StandardCharsets.UTF_8));

  325.     private AbandonedConfig abandonedConfig;

  326.     private boolean closed;

  327.     /**
  328.      * Actual name under which this component has been registered.
  329.      */
  330.     private ObjectNameWrapper registeredJmxObjectName;

  331.     /**
  332.      * Adds a custom connection property to the set that will be passed to our JDBC driver. This <strong>MUST</strong>
  333.      * be called before the first connection is retrieved (along with all the other configuration property setters).
  334.      * Calls to this method after the connection pool has been initialized have no effect.
  335.      *
  336.      * @param name  Name of the custom connection property
  337.      * @param value Value of the custom connection property
  338.      */
  339.     public void addConnectionProperty(final String name, final String value) {
  340.         connectionProperties.put(name, value);
  341.     }

  342.     /**
  343.      * Closes and releases all idle connections that are currently stored in the connection pool associated with this
  344.      * data source.
  345.      * <p>
  346.      * Connections that are checked out to clients when this method is invoked are not affected. When client
  347.      * applications subsequently invoke {@link Connection#close()} to return these connections to the pool, the
  348.      * underlying JDBC connections are closed.
  349.      * </p>
  350.      * <p>
  351.      * Attempts to acquire connections using {@link #getConnection()} after this method has been invoked result in
  352.      * SQLExceptions.  To reopen a datasource that has been closed using this method, use {@link #start()}.
  353.      * </p>
  354.      * <p>
  355.      * This method is idempotent - i.e., closing an already closed BasicDataSource has no effect and does not generate
  356.      * exceptions.
  357.      * </p>
  358.      *
  359.      * @throws SQLException if an error occurs closing idle connections
  360.      */
  361.     @Override
  362.     public synchronized void close() throws SQLException {
  363.         if (registeredJmxObjectName != null) {
  364.             registeredJmxObjectName.unregisterMBean();
  365.             registeredJmxObjectName = null;
  366.         }
  367.         closed = true;
  368.         final GenericObjectPool<?> oldPool = connectionPool;
  369.         connectionPool = null;
  370.         dataSource = null;
  371.         try {
  372.             if (oldPool != null) {
  373.                 oldPool.close();
  374.             }
  375.         } catch (final RuntimeException e) {
  376.             throw e;
  377.         } catch (final Exception e) {
  378.             throw new SQLException(Utils.getMessage("pool.close.fail"), e);
  379.         }
  380.     }

  381.     /**
  382.      * Closes the connection pool, silently swallowing any exception that occurs.
  383.      */
  384.     private void closeConnectionPool() {
  385.         final GenericObjectPool<?> oldPool = connectionPool;
  386.         connectionPool = null;
  387.         Utils.closeQuietly(oldPool);
  388.     }

  389.     /**
  390.      * Creates a JDBC connection factory for this data source. The JDBC driver is loaded using the following algorithm:
  391.      * <ol>
  392.      * <li>If a Driver instance has been specified via {@link #setDriver(Driver)} use it</li>
  393.      * <li>If no Driver instance was specified and {code driverClassName} is specified that class is loaded using the
  394.      * {@link ClassLoader} of this class or, if {code driverClassLoader} is set, {code driverClassName} is loaded
  395.      * with the specified {@link ClassLoader}.</li>
  396.      * <li>If {code driverClassName} is specified and the previous attempt fails, the class is loaded using the
  397.      * context class loader of the current thread.</li>
  398.      * <li>If a driver still isn't loaded one is loaded via the {@link DriverManager} using the specified {code connectionString}.
  399.      * </ol>
  400.      * <p>
  401.      * This method exists so subclasses can replace the implementation class.
  402.      * </p>
  403.      *
  404.      * @return A new connection factory.
  405.      *
  406.      * @throws SQLException If the connection factory cannot be created
  407.      */
  408.     protected ConnectionFactory createConnectionFactory() throws SQLException {
  409.         // Load the JDBC driver class
  410.         return ConnectionFactoryFactory.createConnectionFactory(this, DriverFactory.createDriver(this));
  411.     }

  412.     /**
  413.      * Creates a connection pool for this datasource. This method only exists so subclasses can replace the
  414.      * implementation class.
  415.      * <p>
  416.      * This implementation configures all pool properties other than timeBetweenEvictionRunsMillis. Setting that
  417.      * property is deferred to {@link #startPoolMaintenance()}, since setting timeBetweenEvictionRunsMillis to a
  418.      * positive value causes {@link GenericObjectPool}'s eviction timer to be started.
  419.      * </p>
  420.      *
  421.      * @param factory The factory to use to create new connections for this pool.
  422.      */
  423.     protected void createConnectionPool(final PoolableConnectionFactory factory) {
  424.         // Create an object pool to contain our active connections
  425.         final GenericObjectPoolConfig<PoolableConnection> config = new GenericObjectPoolConfig<>();
  426.         updateJmxName(config);
  427.         // Disable JMX on the underlying pool if the DS is not registered:
  428.         config.setJmxEnabled(registeredJmxObjectName != null);
  429.         // Set up usage tracking if enabled
  430.         if (getAbandonedUsageTracking() && abandonedConfig != null) {
  431.             abandonedConfig.setUseUsageTracking(true);
  432.         }
  433.         final GenericObjectPool<PoolableConnection> gop = createObjectPool(factory, config, abandonedConfig);
  434.         gop.setMaxTotal(maxTotal);
  435.         gop.setMaxIdle(maxIdle);
  436.         gop.setMinIdle(minIdle);
  437.         gop.setMaxWait(maxWaitDuration);
  438.         gop.setTestOnCreate(testOnCreate);
  439.         gop.setTestOnBorrow(testOnBorrow);
  440.         gop.setTestOnReturn(testOnReturn);
  441.         gop.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
  442.         gop.setMinEvictableIdleDuration(minEvictableIdleDuration);
  443.         gop.setSoftMinEvictableIdleDuration(softMinEvictableIdleDuration);
  444.         gop.setTestWhileIdle(testWhileIdle);
  445.         gop.setLifo(lifo);
  446.         gop.setSwallowedExceptionListener(new SwallowedExceptionLogger(log, logExpiredConnections));
  447.         gop.setEvictionPolicyClassName(evictionPolicyClassName);
  448.         factory.setPool(gop);
  449.         connectionPool = gop;
  450.     }

  451.     /**
  452.      * Creates (if necessary) and return the internal data source we are using to manage our connections.
  453.      *
  454.      * @return The current internal DataSource or a newly created instance if it has not yet been created.
  455.      * @throws SQLException if the object pool cannot be created.
  456.      */
  457.     protected synchronized DataSource createDataSource() throws SQLException {
  458.         if (closed) {
  459.             throw new SQLException("Data source is closed");
  460.         }

  461.         // Return the pool if we have already created it
  462.         // This is double-checked locking. This is safe since dataSource is
  463.         // volatile and the code is targeted at Java 5 onwards.
  464.         if (dataSource != null) {
  465.             return dataSource;
  466.         }
  467.         synchronized (this) {
  468.             if (dataSource != null) {
  469.                 return dataSource;
  470.             }
  471.             jmxRegister();

  472.             // create factory which returns raw physical connections
  473.             final ConnectionFactory driverConnectionFactory = createConnectionFactory();

  474.             // Set up the poolable connection factory
  475.             final PoolableConnectionFactory poolableConnectionFactory;
  476.             try {
  477.                 poolableConnectionFactory = createPoolableConnectionFactory(driverConnectionFactory);
  478.                 poolableConnectionFactory.setPoolStatements(poolPreparedStatements);
  479.                 poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements);
  480.                 // create a pool for our connections
  481.                 createConnectionPool(poolableConnectionFactory);
  482.                 final DataSource newDataSource = createDataSourceInstance();
  483.                 newDataSource.setLogWriter(logWriter);
  484.                 connectionPool.addObjects(initialSize);
  485.                 // If timeBetweenEvictionRunsMillis > 0, start the pool's evictor
  486.                 // task
  487.                 startPoolMaintenance();
  488.                 dataSource = newDataSource;
  489.             } catch (final SQLException | RuntimeException se) {
  490.                 closeConnectionPool();
  491.                 throw se;
  492.             } catch (final Exception ex) {
  493.                 closeConnectionPool();
  494.                 throw new SQLException("Error creating connection factory", ex);
  495.             }

  496.             return dataSource;
  497.         }
  498.     }

  499.     /**
  500.      * Creates the actual data source instance. This method only exists so that subclasses can replace the
  501.      * implementation class.
  502.      *
  503.      * @throws SQLException if unable to create a datasource instance
  504.      *
  505.      * @return A new DataSource instance
  506.      */
  507.     protected DataSource createDataSourceInstance() throws SQLException {
  508.         final PoolingDataSource<PoolableConnection> pds = new PoolingDataSource<>(connectionPool);
  509.         pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
  510.         return pds;
  511.     }

  512.     /**
  513.      * Creates an object pool used to provide pooling support for {@link Connection JDBC connections}.
  514.      *
  515.      * @param factory         the object factory
  516.      * @param poolConfig      the object pool configuration
  517.      * @param abandonedConfig the abandoned objects configuration
  518.      * @return a non-null instance
  519.      */
  520.     protected GenericObjectPool<PoolableConnection> createObjectPool(final PoolableConnectionFactory factory,
  521.             final GenericObjectPoolConfig<PoolableConnection> poolConfig, final AbandonedConfig abandonedConfig) {
  522.         final GenericObjectPool<PoolableConnection> gop;
  523.         if (abandonedConfig != null && (abandonedConfig.getRemoveAbandonedOnBorrow()
  524.                 || abandonedConfig.getRemoveAbandonedOnMaintenance())) {
  525.             gop = new GenericObjectPool<>(factory, poolConfig, abandonedConfig);
  526.         } else {
  527.             gop = new GenericObjectPool<>(factory, poolConfig);
  528.         }
  529.         return gop;
  530.     }

  531.     /**
  532.      * Creates the PoolableConnectionFactory and attaches it to the connection pool. This method only exists so
  533.      * subclasses can replace the default implementation.
  534.      *
  535.      * @param driverConnectionFactory JDBC connection factory
  536.      * @throws SQLException if an error occurs creating the PoolableConnectionFactory
  537.      *
  538.      * @return A new PoolableConnectionFactory configured with the current configuration of this BasicDataSource
  539.      */
  540.     protected PoolableConnectionFactory createPoolableConnectionFactory(final ConnectionFactory driverConnectionFactory)
  541.             throws SQLException {
  542.         PoolableConnectionFactory connectionFactory = null;
  543.         try {
  544.             if (registerConnectionMBean) {
  545.                 connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, ObjectNameWrapper.unwrap(registeredJmxObjectName));
  546.             } else {
  547.                 connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, null);
  548.             }
  549.             connectionFactory.setValidationQuery(validationQuery);
  550.             connectionFactory.setValidationQueryTimeout(validationQueryTimeoutDuration);
  551.             connectionFactory.setConnectionInitSql(connectionInitSqls);
  552.             connectionFactory.setDefaultReadOnly(defaultReadOnly);
  553.             connectionFactory.setDefaultAutoCommit(defaultAutoCommit);
  554.             connectionFactory.setDefaultTransactionIsolation(defaultTransactionIsolation);
  555.             connectionFactory.setDefaultCatalog(defaultCatalog);
  556.             connectionFactory.setDefaultSchema(defaultSchema);
  557.             connectionFactory.setCacheState(cacheState);
  558.             connectionFactory.setPoolStatements(poolPreparedStatements);
  559.             connectionFactory.setClearStatementPoolOnReturn(clearStatementPoolOnReturn);
  560.             connectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements);
  561.             connectionFactory.setMaxConn(maxConnDuration);
  562.             connectionFactory.setRollbackOnReturn(getRollbackOnReturn());
  563.             connectionFactory.setAutoCommitOnReturn(getAutoCommitOnReturn());
  564.             connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeoutDuration());
  565.             connectionFactory.setFastFailValidation(fastFailValidation);
  566.             connectionFactory.setDisconnectionSqlCodes(disconnectionSqlCodes);
  567.             connectionFactory.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes);
  568.             validateConnectionFactory(connectionFactory);
  569.         } catch (final RuntimeException e) {
  570.             throw e;
  571.         } catch (final Exception e) {
  572.             throw new SQLException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e);
  573.         }
  574.         return connectionFactory;
  575.     }

  576.     /**
  577.      * Manually evicts idle connections
  578.      *
  579.      * @throws Exception when there is a problem evicting idle objects.
  580.      */
  581.     public void evict() throws Exception {
  582.         if (connectionPool != null) {
  583.             connectionPool.evict();
  584.         }
  585.     }

  586.     /**
  587.      * Gets the print writer used by this configuration to log information on abandoned objects.
  588.      *
  589.      * @return The print writer used by this configuration to log information on abandoned objects.
  590.      */
  591.     public PrintWriter getAbandonedLogWriter() {
  592.         return abandonedConfig == null ? null : abandonedConfig.getLogWriter();
  593.     }

  594.     /**
  595.      * If the connection pool implements {@link org.apache.commons.pool2.UsageTracking UsageTracking}, should the
  596.      * connection pool record a stack trace every time a method is called on a pooled connection and retain the most
  597.      * recent stack trace to aid debugging of abandoned connections?
  598.      *
  599.      * @return {@code true} if usage tracking is enabled
  600.      */
  601.     @Override
  602.     public boolean getAbandonedUsageTracking() {
  603.         return abandonedConfig != null && abandonedConfig.getUseUsageTracking();
  604.     }

  605.     /**
  606.      * Gets the value of the flag that controls whether or not connections being returned to the pool will be checked
  607.      * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
  608.      * setting is {@code false} when the connection is returned. It is {@code true} by default.
  609.      *
  610.      * @return Whether or not connections being returned to the pool will be checked and configured with auto-commit.
  611.      */
  612.     public boolean getAutoCommitOnReturn() {
  613.         return autoCommitOnReturn;
  614.     }

  615.     /**
  616.      * Gets the state caching flag.
  617.      *
  618.      * @return the state caching flag
  619.      */
  620.     @Override
  621.     public boolean getCacheState() {
  622.         return cacheState;
  623.     }

  624.     /**
  625.      * Creates (if necessary) and return a connection to the database.
  626.      *
  627.      * @throws SQLException if a database access error occurs
  628.      * @return a database connection
  629.      */
  630.     @Override
  631.     public Connection getConnection() throws SQLException {
  632.         if (Utils.isSecurityEnabled()) {
  633.             final PrivilegedExceptionAction<Connection> action = () -> createDataSource().getConnection();
  634.             try {
  635.                 return AccessController.doPrivileged(action);
  636.             } catch (final PrivilegedActionException e) {
  637.                 final Throwable cause = e.getCause();
  638.                 if (cause instanceof SQLException) {
  639.                     throw (SQLException) cause;
  640.                 }
  641.                 throw new SQLException(e);
  642.             }
  643.         }
  644.         return createDataSource().getConnection();
  645.     }

  646.     /**
  647.      * <strong>BasicDataSource does NOT support this method.</strong>
  648.      *
  649.      * @param user Database user on whose behalf the Connection is being made
  650.      * @param pass The database user's password
  651.      *
  652.      * @throws UnsupportedOperationException always thrown.
  653.      * @throws SQLException                  if a database access error occurs
  654.      * @return nothing - always throws UnsupportedOperationException
  655.      */
  656.     @Override
  657.     public Connection getConnection(final String user, final String pass) throws SQLException {
  658.         // This method isn't supported by the PoolingDataSource returned by the
  659.         // createDataSource
  660.         throw new UnsupportedOperationException("Not supported by BasicDataSource");
  661.     }

  662.     /**
  663.      * Gets the ConnectionFactoryClassName that has been configured for use by this pool.
  664.      * <p>
  665.      * Note: This getter only returns the last value set by a call to {@link #setConnectionFactoryClassName(String)}.
  666.      * </p>
  667.      *
  668.      * @return the ConnectionFactoryClassName that has been configured for use by this pool.
  669.      * @since 2.7.0
  670.      */
  671.     public String getConnectionFactoryClassName() {
  672.         return this.connectionFactoryClassName;
  673.     }

  674.     /**
  675.      * Gets the list of SQL statements executed when a physical connection is first created. Returns an empty list if
  676.      * there are no initialization statements configured.
  677.      *
  678.      * @return initialization SQL statements
  679.      */
  680.     public List<String> getConnectionInitSqls() {
  681.         final List<String> result = connectionInitSqls;
  682.         return result == null ? Collections.emptyList() : result;
  683.     }

  684.     /**
  685.      * Provides the same data as {@link #getConnectionInitSqls()} but in an array so it is accessible via JMX.
  686.      */
  687.     @Override
  688.     public String[] getConnectionInitSqlsAsArray() {
  689.         return getConnectionInitSqls().toArray(Utils.EMPTY_STRING_ARRAY);
  690.     }

  691.     /**
  692.      * Gets the underlying connection pool.
  693.      *
  694.      * @return the underlying connection pool.
  695.      * @since 2.10.0
  696.      */
  697.     public GenericObjectPool<PoolableConnection> getConnectionPool() {
  698.         return connectionPool;
  699.     }

  700.     Properties getConnectionProperties() {
  701.         return connectionProperties;
  702.     }

  703.     /**
  704.      * Gets the default auto-commit property.
  705.      *
  706.      * @return true if default auto-commit is enabled
  707.      */
  708.     @Override
  709.     public Boolean getDefaultAutoCommit() {
  710.         return defaultAutoCommit;
  711.     }

  712.     /**
  713.      * Gets the default catalog.
  714.      *
  715.      * @return the default catalog
  716.      */
  717.     @Override
  718.     public String getDefaultCatalog() {
  719.         return this.defaultCatalog;
  720.     }

  721.     /**
  722.      * Gets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
  723.      * connection. {@code null} means that the driver default will be used.
  724.      *
  725.      * @return The default query timeout in seconds.
  726.      * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}.
  727.      */
  728.     @Deprecated
  729.     public Integer getDefaultQueryTimeout() {
  730.         return defaultQueryTimeoutDuration == null ? null : (int) defaultQueryTimeoutDuration.getSeconds();
  731.     }

  732.     /**
  733.      * Gets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
  734.      * connection. {@code null} means that the driver default will be used.
  735.      *
  736.      * @return The default query timeout Duration.
  737.      * @since 2.10.0
  738.      */
  739.     public Duration getDefaultQueryTimeoutDuration() {
  740.         return defaultQueryTimeoutDuration;
  741.     }

  742.     /**
  743.      * Gets the default readOnly property.
  744.      *
  745.      * @return true if connections are readOnly by default
  746.      */
  747.     @Override
  748.     public Boolean getDefaultReadOnly() {
  749.         return defaultReadOnly;
  750.     }

  751.     /**
  752.      * Gets the default schema.
  753.      *
  754.      * @return the default schema.
  755.      * @since 2.5.0
  756.      */
  757.     @Override
  758.     public String getDefaultSchema() {
  759.         return this.defaultSchema;
  760.     }

  761.     /**
  762.      * Gets the default transaction isolation state of returned connections.
  763.      *
  764.      * @return the default value for transaction isolation state
  765.      * @see Connection#getTransactionIsolation
  766.      */
  767.     @Override
  768.     public int getDefaultTransactionIsolation() {
  769.         return this.defaultTransactionIsolation;
  770.     }

  771.     /**
  772.      * Gets the set of SQL State codes that are not considered fatal disconnection codes.
  773.      * <p>
  774.      * This method returns the set of SQL State codes that have been specified to be ignored
  775.      * when determining if a {@link SQLException} signals a disconnection. These codes will not
  776.      * trigger a disconnection even if they match other disconnection criteria.
  777.      * </p>
  778.      *
  779.      * @return a set of SQL State codes that should be ignored for disconnection checks, or an empty set if none have been specified.
  780.      * @since 2.13.0
  781.      */
  782.     public Set<String> getDisconnectionIgnoreSqlCodes() {
  783.         final Set<String> result = disconnectionIgnoreSqlCodes;
  784.         return result == null ? Collections.emptySet() : result;
  785.     }

  786.     /**
  787.      * Provides the same data as {@link #getDisconnectionIgnoreSqlCodes()} but in an array, so it is accessible via JMX.
  788.      *
  789.      * @since 2.13.0
  790.      */
  791.     @Override
  792.     public String[] getDisconnectionIgnoreSqlCodesAsArray() {
  793.         return getDisconnectionIgnoreSqlCodes().toArray(Utils.EMPTY_STRING_ARRAY);
  794.     }

  795.     /**
  796.      * Gets the set of SQL State codes considered to signal fatal conditions.
  797.      *
  798.      * @return fatal disconnection state codes
  799.      * @see #setDisconnectionSqlCodes(Collection)
  800.      * @since 2.1
  801.      */
  802.     public Set<String> getDisconnectionSqlCodes() {
  803.         final Set<String> result = disconnectionSqlCodes;
  804.         return result == null ? Collections.emptySet() : result;
  805.     }

  806.     /**
  807.      * Provides the same data as {@link #getDisconnectionSqlCodes} but in an array so it is accessible via JMX.
  808.      *
  809.      * @since 2.1
  810.      */
  811.     @Override
  812.     public String[] getDisconnectionSqlCodesAsArray() {
  813.         return getDisconnectionSqlCodes().toArray(Utils.EMPTY_STRING_ARRAY);
  814.     }

  815.     /**
  816.      * Gets the JDBC Driver that has been configured for use by this pool.
  817.      * <p>
  818.      * Note: This getter only returns the last value set by a call to {@link #setDriver(Driver)}. It does not return any
  819.      * driver instance that may have been created from the value set via {@link #setDriverClassName(String)}.
  820.      * </p>
  821.      *
  822.      * @return the JDBC Driver that has been configured for use by this pool
  823.      */
  824.     public synchronized Driver getDriver() {
  825.         return driver;
  826.     }

  827.     /**
  828.      * Gets the class loader specified for loading the JDBC driver. Returns {@code null} if no class loader has
  829.      * been explicitly specified.
  830.      * <p>
  831.      * Note: This getter only returns the last value set by a call to {@link #setDriverClassLoader(ClassLoader)}. It
  832.      * does not return the class loader of any driver that may have been set via {@link #setDriver(Driver)}.
  833.      * </p>
  834.      *
  835.      * @return The class loader specified for loading the JDBC driver.
  836.      */
  837.     public synchronized ClassLoader getDriverClassLoader() {
  838.         return this.driverClassLoader;
  839.     }

  840.     /**
  841.      * Gets the JDBC driver class name.
  842.      * <p>
  843.      * Note: This getter only returns the last value set by a call to {@link #setDriverClassName(String)}. It does not
  844.      * return the class name of any driver that may have been set via {@link #setDriver(Driver)}.
  845.      * </p>
  846.      *
  847.      * @return the JDBC driver class name
  848.      */
  849.     @Override
  850.     public synchronized String getDriverClassName() {
  851.         return this.driverClassName;
  852.     }

  853.     /**
  854.      * Gets the value of the {code durationBetweenEvictionRuns} property.
  855.      *
  856.      * @return the time (in milliseconds) between evictor runs
  857.      * @see #setDurationBetweenEvictionRuns(Duration)
  858.      * @since 2.10.0
  859.      */
  860.     public synchronized Duration getDurationBetweenEvictionRuns() {
  861.         return this.durationBetweenEvictionRuns;
  862.     }

  863.     /**
  864.      * Gets the value of the flag that controls whether or not connections being returned to the pool will be checked
  865.      * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
  866.      * setting is {@code false} when the connection is returned. It is {@code true} by default.
  867.      *
  868.      * @return Whether or not connections being returned to the pool will be checked and configured with auto-commit.
  869.      * @deprecated Use {@link #getAutoCommitOnReturn()}.
  870.      */
  871.     @Deprecated
  872.     public boolean getEnableAutoCommitOnReturn() {
  873.         return autoCommitOnReturn;
  874.     }

  875.     /**
  876.      * Gets the EvictionPolicy implementation in use with this connection pool.
  877.      *
  878.      * @return The EvictionPolicy implementation in use with this connection pool.
  879.      */
  880.     public synchronized String getEvictionPolicyClassName() {
  881.         return evictionPolicyClassName;
  882.     }

  883.     /**
  884.      * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with
  885.      * SQL State indicating fatal disconnection errors.
  886.      *
  887.      * @return true if connections created by this datasource will fast fail validation.
  888.      * @see #setDisconnectionSqlCodes(Collection)
  889.      * @see #setDisconnectionIgnoreSqlCodes(Collection)
  890.      * @since 2.1
  891.      */
  892.     @Override
  893.     public boolean getFastFailValidation() {
  894.         return fastFailValidation;
  895.     }

  896.     /**
  897.      * Gets the initial size of the connection pool.
  898.      *
  899.      * @return the number of connections created when the pool is initialized
  900.      */
  901.     @Override
  902.     public synchronized int getInitialSize() {
  903.         return this.initialSize;
  904.     }

  905.     /**
  906.      * Gets the JMX name that has been requested for this DataSource. If the requested name is not valid, an
  907.      * alternative may be chosen.
  908.      *
  909.      * @return The JMX name that has been requested for this DataSource.
  910.      */
  911.     public String getJmxName() {
  912.         return jmxName;
  913.     }

  914.     /**
  915.      * Gets the LIFO property.
  916.      *
  917.      * @return true if connection pool behaves as a LIFO queue.
  918.      */
  919.     @Override
  920.     public synchronized boolean getLifo() {
  921.         return this.lifo;
  922.     }

  923.     /**
  924.      * Flag to log stack traces for application code which abandoned a Statement or Connection.
  925.      * <p>
  926.      * Defaults to false.
  927.      * </p>
  928.      * <p>
  929.      * Logging of abandoned Statements and Connections adds overhead for every Connection open or new Statement because
  930.      * a stack trace has to be generated.
  931.      * </p>
  932.      */
  933.     @Override
  934.     public boolean getLogAbandoned() {
  935.         return abandonedConfig != null && abandonedConfig.getLogAbandoned();
  936.     }

  937.     /**
  938.      * When {@link #getMaxConnDuration()} is set to limit connection lifetime, this property determines whether or
  939.      * not log messages are generated when the pool closes connections due to maximum lifetime exceeded.
  940.      *
  941.      * @since 2.1
  942.      */
  943.     @Override
  944.     public boolean getLogExpiredConnections() {
  945.         return logExpiredConnections;
  946.     }

  947.     /**
  948.      * <strong>BasicDataSource does NOT support this method.</strong>
  949.      *
  950.      * <p>
  951.      * Gets the login timeout (in seconds) for connecting to the database.
  952.      * </p>
  953.      * <p>
  954.      * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool.
  955.      * </p>
  956.      *
  957.      * @throws SQLException                  if a database access error occurs
  958.      * @throws UnsupportedOperationException If the DataSource implementation does not support the login timeout
  959.      *                                       feature.
  960.      * @return login timeout in seconds
  961.      */
  962.     @Override
  963.     public int getLoginTimeout() throws SQLException {
  964.         // This method isn't supported by the PoolingDataSource returned by the createDataSource
  965.         throw new UnsupportedOperationException("Not supported by BasicDataSource");
  966.     }

  967.     /**
  968.      * Gets the log writer being used by this data source.
  969.      * <p>
  970.      * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool.
  971.      * </p>
  972.      *
  973.      * @throws SQLException if a database access error occurs
  974.      * @return log writer in use
  975.      */
  976.     @Override
  977.     public PrintWriter getLogWriter() throws SQLException {
  978.         return createDataSource().getLogWriter();
  979.     }

  980.     /**
  981.      * Gets the maximum permitted duration of a connection. A value of zero or less indicates an
  982.      * infinite lifetime.
  983.      * @return the maximum permitted duration of a connection.
  984.      * @since 2.10.0
  985.      */
  986.     public Duration getMaxConnDuration() {
  987.         return maxConnDuration;
  988.     }

  989.     /**
  990.      * Gets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an
  991.      * infinite lifetime.
  992.      * @deprecated Use {@link #getMaxConnDuration()}.
  993.      */
  994.     @Override
  995.     @Deprecated
  996.     public long getMaxConnLifetimeMillis() {
  997.         return maxConnDuration.toMillis();
  998.     }

  999.     /**
  1000.      * Gets the maximum number of connections that can remain idle in the pool. Excess idle connections are destroyed
  1001.      * on return to the pool.
  1002.      * <p>
  1003.      * A negative value indicates that there is no limit
  1004.      * </p>
  1005.      *
  1006.      * @return the maximum number of idle connections
  1007.      */
  1008.     @Override
  1009.     public synchronized int getMaxIdle() {
  1010.         return this.maxIdle;
  1011.     }

  1012.     /**
  1013.      * Gets the value of the {@code maxOpenPreparedStatements} property.
  1014.      *
  1015.      * @return the maximum number of open statements
  1016.      */
  1017.     @Override
  1018.     public synchronized int getMaxOpenPreparedStatements() {
  1019.         return this.maxOpenPreparedStatements;
  1020.     }

  1021.     /**
  1022.      * Gets the maximum number of active connections that can be allocated at the same time.
  1023.      * <p>
  1024.      * A negative number means that there is no limit.
  1025.      * </p>
  1026.      *
  1027.      * @return the maximum number of active connections
  1028.      */
  1029.     @Override
  1030.     public synchronized int getMaxTotal() {
  1031.         return this.maxTotal;
  1032.     }

  1033.     /**
  1034.      * Gets the maximum Duration that the pool will wait for a connection to be returned before throwing an exception. A
  1035.      * value less than or equal to zero means the pool is set to wait indefinitely.
  1036.      *
  1037.      * @return the maxWaitDuration property value.
  1038.      * @since 2.10.0
  1039.      */
  1040.     public synchronized Duration getMaxWaitDuration() {
  1041.         return this.maxWaitDuration;
  1042.     }

  1043.     /**
  1044.      * Gets the maximum number of milliseconds that the pool will wait for a connection to be returned before
  1045.      * throwing an exception. A value less than or equal to zero means the pool is set to wait indefinitely.
  1046.      *
  1047.      * @return the maxWaitMillis property value.
  1048.      * @deprecated Use {@link #getMaxWaitDuration()}.
  1049.      */
  1050.     @Deprecated
  1051.     @Override
  1052.     public synchronized long getMaxWaitMillis() {
  1053.         return this.maxWaitDuration.toMillis();
  1054.     }

  1055.     /**
  1056.      * Gets the {code minEvictableIdleDuration} property.
  1057.      *
  1058.      * @return the value of the {code minEvictableIdleDuration} property
  1059.      * @see #setMinEvictableIdle(Duration)
  1060.      * @since 2.10.0
  1061.      */
  1062.     public synchronized Duration getMinEvictableIdleDuration() {
  1063.         return this.minEvictableIdleDuration;
  1064.     }

  1065.     /**
  1066.      * Gets the {code minEvictableIdleDuration} property.
  1067.      *
  1068.      * @return the value of the {code minEvictableIdleDuration} property
  1069.      * @see #setMinEvictableIdle(Duration)
  1070.      * @deprecated Use {@link #getMinEvictableIdleDuration()}.
  1071.      */
  1072.     @Deprecated
  1073.     @Override
  1074.     public synchronized long getMinEvictableIdleTimeMillis() {
  1075.         return this.minEvictableIdleDuration.toMillis();
  1076.     }

  1077.     /**
  1078.      * Gets the minimum number of idle connections in the pool. The pool attempts to ensure that minIdle connections
  1079.      * are available when the idle object evictor runs. The value of this property has no effect unless
  1080.      * {code durationBetweenEvictionRuns} has a positive value.
  1081.      *
  1082.      * @return the minimum number of idle connections
  1083.      * @see GenericObjectPool#getMinIdle()
  1084.      */
  1085.     @Override
  1086.     public synchronized int getMinIdle() {
  1087.         return this.minIdle;
  1088.     }

  1089.     /**
  1090.      * [Read Only] The current number of active connections that have been allocated from this data source.
  1091.      *
  1092.      * @return the current number of active connections
  1093.      */
  1094.     @Override
  1095.     public int getNumActive() {
  1096.         // Copy reference to avoid NPE if close happens after null check
  1097.         final GenericObjectPool<PoolableConnection> pool = connectionPool;
  1098.         return pool == null ? 0 : pool.getNumActive();
  1099.     }

  1100.     /**
  1101.      * [Read Only] The current number of idle connections that are waiting to be allocated from this data source.
  1102.      *
  1103.      * @return the current number of idle connections
  1104.      */
  1105.     @Override
  1106.     public int getNumIdle() {
  1107.         // Copy reference to avoid NPE if close happens after null check
  1108.         final GenericObjectPool<PoolableConnection> pool = connectionPool;
  1109.         return pool == null ? 0 : pool.getNumIdle();
  1110.     }

  1111.     /**
  1112.      * Gets the value of the {code numTestsPerEvictionRun} property.
  1113.      *
  1114.      * @return the number of objects to examine during idle object evictor runs
  1115.      * @see #setNumTestsPerEvictionRun(int)
  1116.      */
  1117.     @Override
  1118.     public synchronized int getNumTestsPerEvictionRun() {
  1119.         return this.numTestsPerEvictionRun;
  1120.     }

  1121.     @Override
  1122.     public Logger getParentLogger() throws SQLFeatureNotSupportedException {
  1123.         throw new SQLFeatureNotSupportedException();
  1124.     }

  1125.     /**
  1126.      * Gets the password passed to the JDBC driver to establish connections.
  1127.      *
  1128.      * @return the connection password
  1129.      * @deprecated Exposing passwords via JMX is an Information Exposure issue.
  1130.      */
  1131.     @Deprecated
  1132.     @Override
  1133.     public String getPassword() {
  1134.         return this.password;
  1135.     }

  1136.     /**
  1137.      * Gets the registered JMX ObjectName.
  1138.      *
  1139.      * @return the registered JMX ObjectName.
  1140.      */
  1141.     protected ObjectName getRegisteredJmxName() {
  1142.         return ObjectNameWrapper.unwrap(registeredJmxObjectName);
  1143.     }

  1144.     /**
  1145.      * Flag to remove abandoned connections if they exceed the removeAbandonedTimeout when borrowObject is invoked.
  1146.      * <p>
  1147.      * The default value is false.
  1148.      * </p>
  1149.      * <p>
  1150.      * If set to true a connection is considered abandoned and eligible for removal if it has not been used for more
  1151.      * than {@link #getRemoveAbandonedTimeoutDuration() removeAbandonedTimeout} seconds.
  1152.      * </p>
  1153.      * <p>
  1154.      * Abandoned connections are identified and removed when {@link #getConnection()} is invoked and all of the
  1155.      * following conditions hold:
  1156.      * </p>
  1157.      * <ul>
  1158.      * <li>{@link #getRemoveAbandonedOnBorrow()}</li>
  1159.      * <li>{@link #getNumActive()} &gt; {@link #getMaxTotal()} - 3</li>
  1160.      * <li>{@link #getNumIdle()} &lt; 2</li>
  1161.      * </ul>
  1162.      *
  1163.      * @see #getRemoveAbandonedTimeoutDuration()
  1164.      */
  1165.     @Override
  1166.     public boolean getRemoveAbandonedOnBorrow() {
  1167.         return abandonedConfig != null && abandonedConfig.getRemoveAbandonedOnBorrow();
  1168.     }

  1169.     /**
  1170.      * Flag to remove abandoned connections if they exceed the removeAbandonedTimeout during pool maintenance.
  1171.      * <p>
  1172.      * The default value is false.
  1173.      * </p>
  1174.      * <p>
  1175.      * If set to true a connection is considered abandoned and eligible for removal if it has not been used for more
  1176.      * than {@link #getRemoveAbandonedTimeoutDuration() removeAbandonedTimeout} seconds.
  1177.      * </p>
  1178.      *
  1179.      * @see #getRemoveAbandonedTimeoutDuration()
  1180.      */
  1181.     @Override
  1182.     public boolean getRemoveAbandonedOnMaintenance() {
  1183.         return abandonedConfig != null && abandonedConfig.getRemoveAbandonedOnMaintenance();
  1184.     }

  1185.     /**
  1186.      * Gets the timeout in seconds before an abandoned connection can be removed.
  1187.      * <p>
  1188.      * Creating a Statement, PreparedStatement or CallableStatement or using one of these to execute a query (using one
  1189.      * of the execute methods) resets the lastUsed property of the parent connection.
  1190.      * </p>
  1191.      * <p>
  1192.      * Abandoned connection cleanup happens when:
  1193.      * </p>
  1194.      * <ul>
  1195.      * <li>{@link #getRemoveAbandonedOnBorrow()} or {@link #getRemoveAbandonedOnMaintenance()} = true</li>
  1196.      * <li>{@link #getNumIdle() numIdle} &lt; 2</li>
  1197.      * <li>{@link #getNumActive() numActive} &gt; {@link #getMaxTotal() maxTotal} - 3</li>
  1198.      * </ul>
  1199.      * <p>
  1200.      * The default value is 300 seconds.
  1201.      * </p>
  1202.      * @deprecated Use {@link #getRemoveAbandonedTimeoutDuration()}.
  1203.      */
  1204.     @Deprecated
  1205.     @Override
  1206.     public int getRemoveAbandonedTimeout() {
  1207.         return (int) getRemoveAbandonedTimeoutDuration().getSeconds();
  1208.     }

  1209.     /**
  1210.      * Gets the timeout before an abandoned connection can be removed.
  1211.      * <p>
  1212.      * Creating a Statement, PreparedStatement or CallableStatement or using one of these to execute a query (using one
  1213.      * of the execute methods) resets the lastUsed property of the parent connection.
  1214.      * </p>
  1215.      * <p>
  1216.      * Abandoned connection cleanup happens when:
  1217.      * </p>
  1218.      * <ul>
  1219.      * <li>{@link #getRemoveAbandonedOnBorrow()} or {@link #getRemoveAbandonedOnMaintenance()} = true</li>
  1220.      * <li>{@link #getNumIdle() numIdle} &lt; 2</li>
  1221.      * <li>{@link #getNumActive() numActive} &gt; {@link #getMaxTotal() maxTotal} - 3</li>
  1222.      * </ul>
  1223.      * <p>
  1224.      * The default value is 300 seconds.
  1225.      * </p>
  1226.      * @return Timeout before an abandoned connection can be removed.
  1227.      * @since 2.10.0
  1228.      */
  1229.     public Duration getRemoveAbandonedTimeoutDuration() {
  1230.         return abandonedConfig == null ? Duration.ofSeconds(300) : abandonedConfig.getRemoveAbandonedTimeoutDuration();
  1231.     }

  1232.     /**
  1233.      * Gets the current value of the flag that controls whether a connection will be rolled back when it is returned to
  1234.      * the pool if auto commit is not enabled and the connection is not read only.
  1235.      *
  1236.      * @return whether a connection will be rolled back when it is returned to the pool.
  1237.      */
  1238.     public boolean getRollbackOnReturn() {
  1239.         return rollbackOnReturn;
  1240.     }

  1241.     /**
  1242.      * Gets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by
  1243.      * the idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool.
  1244.      * <p>
  1245.      * When {@link #getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} is set to a positive value,
  1246.      * minEvictableIdleTimeMillis is examined first by the idle connection evictor - i.e. when idle connections are
  1247.      * visited by the evictor, idle time is first compared against {@code minEvictableIdleTimeMillis} (without
  1248.      * considering the number of idle connections in the pool) and then against {@code softMinEvictableIdleTimeMillis},
  1249.      * including the {@code minIdle}, constraint.
  1250.      * </p>
  1251.      *
  1252.      * @return minimum amount of time a connection may sit idle in the pool before it is eligible for eviction, assuming
  1253.      *         there are minIdle idle connections in the pool
  1254.      * @since 2.10.0
  1255.      */
  1256.     public synchronized Duration getSoftMinEvictableIdleDuration() {
  1257.         return softMinEvictableIdleDuration;
  1258.     }

  1259.     /**
  1260.      * Gets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by
  1261.      * the idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool.
  1262.      * <p>
  1263.      * When {@link #getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} is set to a positive value,
  1264.      * minEvictableIdleTimeMillis is examined first by the idle connection evictor - i.e. when idle connections are
  1265.      * visited by the evictor, idle time is first compared against {@code minEvictableIdleTimeMillis} (without
  1266.      * considering the number of idle connections in the pool) and then against {@code softMinEvictableIdleTimeMillis},
  1267.      * including the {@code minIdle}, constraint.
  1268.      * </p>
  1269.      *
  1270.      * @return minimum amount of time a connection may sit idle in the pool before it is eligible for eviction, assuming
  1271.      *         there are minIdle idle connections in the pool
  1272.      * @deprecated Use {@link #getSoftMinEvictableIdleDuration()}.
  1273.      */
  1274.     @Deprecated
  1275.     @Override
  1276.     public synchronized long getSoftMinEvictableIdleTimeMillis() {
  1277.         return softMinEvictableIdleDuration.toMillis();
  1278.     }

  1279.     /**
  1280.      * Gets the {code testOnBorrow} property.
  1281.      *
  1282.      * @return true if objects are validated before being borrowed from the pool
  1283.      *
  1284.      * @see #setTestOnBorrow(boolean)
  1285.      */
  1286.     @Override
  1287.     public synchronized boolean getTestOnBorrow() {
  1288.         return this.testOnBorrow;
  1289.     }

  1290.     /**
  1291.      * Gets the {code testOnCreate} property.
  1292.      *
  1293.      * @return true if objects are validated immediately after they are created by the pool
  1294.      * @see #setTestOnCreate(boolean)
  1295.      */
  1296.     @Override
  1297.     public synchronized boolean getTestOnCreate() {
  1298.         return this.testOnCreate;
  1299.     }

  1300.     /**
  1301.      * Gets the value of the {code testOnReturn} property.
  1302.      *
  1303.      * @return true if objects are validated before being returned to the pool
  1304.      * @see #setTestOnReturn(boolean)
  1305.      */
  1306.     public synchronized boolean getTestOnReturn() {
  1307.         return this.testOnReturn;
  1308.     }

  1309.     /**
  1310.      * Gets the value of the {code testWhileIdle} property.
  1311.      *
  1312.      * @return true if objects examined by the idle object evictor are validated
  1313.      * @see #setTestWhileIdle(boolean)
  1314.      */
  1315.     @Override
  1316.     public synchronized boolean getTestWhileIdle() {
  1317.         return this.testWhileIdle;
  1318.     }

  1319.     /**
  1320.      * Gets the value of the {code durationBetweenEvictionRuns} property.
  1321.      *
  1322.      * @return the time (in milliseconds) between evictor runs
  1323.      * @see #setDurationBetweenEvictionRuns(Duration)
  1324.      * @deprecated Use {@link #getDurationBetweenEvictionRuns()}.
  1325.      */
  1326.     @Deprecated
  1327.     @Override
  1328.     public synchronized long getTimeBetweenEvictionRunsMillis() {
  1329.         return this.durationBetweenEvictionRuns.toMillis();
  1330.     }

  1331.     /**
  1332.      * Gets the JDBC connection {code connectionString} property.
  1333.      *
  1334.      * @return the {code connectionString} passed to the JDBC driver to establish connections
  1335.      */
  1336.     @Override
  1337.     public synchronized String getUrl() {
  1338.         return this.connectionString;
  1339.     }

  1340.     /**
  1341.      * Gets the JDBC connection {code userName} property.
  1342.      *
  1343.      * @return the {code userName} passed to the JDBC driver to establish connections
  1344.      * @deprecated Use {@link #getUserName()}.
  1345.      */
  1346.     @Deprecated
  1347.     @Override
  1348.     public String getUsername() {
  1349.         return this.userName;
  1350.     }

  1351.     /**
  1352.      * Gets the validation query used to validate connections before returning them.
  1353.      *
  1354.      * @return the SQL validation query
  1355.      * @see #setValidationQuery(String)
  1356.      */
  1357.     @Override
  1358.     public String getValidationQuery() {
  1359.         return this.validationQuery;
  1360.     }

  1361.     /**
  1362.      * Gets the validation query timeout.
  1363.      *
  1364.      * @return the timeout in seconds before connection validation queries fail.
  1365.      * @deprecated Use {@link #getValidationQueryTimeoutDuration()}.
  1366.      */
  1367.     @Deprecated
  1368.     @Override
  1369.     public int getValidationQueryTimeout() {
  1370.         return (int) validationQueryTimeoutDuration.getSeconds();
  1371.     }

  1372.     /**
  1373.      * Gets the validation query timeout.
  1374.      *
  1375.      * @return the timeout in seconds before connection validation queries fail.
  1376.      */
  1377.     public Duration getValidationQueryTimeoutDuration() {
  1378.         return validationQueryTimeoutDuration;
  1379.     }

  1380.     /**
  1381.      * Manually invalidates a connection, effectively requesting the pool to try to close it, remove it from the pool
  1382.      * and reclaim pool capacity.
  1383.      *
  1384.      * @param connection The Connection to invalidate.
  1385.      *
  1386.      * @throws IllegalStateException if invalidating the connection failed.
  1387.      * @since 2.1
  1388.      */
  1389.     @SuppressWarnings("resource")
  1390.     public void invalidateConnection(final Connection connection) throws IllegalStateException {
  1391.         if (connection == null) {
  1392.             return;
  1393.         }
  1394.         if (connectionPool == null) {
  1395.             throw new IllegalStateException("Cannot invalidate connection: ConnectionPool is null.");
  1396.         }

  1397.         final PoolableConnection poolableConnection;
  1398.         try {
  1399.             poolableConnection = connection.unwrap(PoolableConnection.class);
  1400.             if (poolableConnection == null) {
  1401.                 throw new IllegalStateException(
  1402.                         "Cannot invalidate connection: Connection is not a poolable connection.");
  1403.             }
  1404.         } catch (final SQLException e) {
  1405.             throw new IllegalStateException("Cannot invalidate connection: Unwrapping poolable connection failed.", e);
  1406.         }

  1407.         try {
  1408.             connectionPool.invalidateObject(poolableConnection);
  1409.         } catch (final Exception e) {
  1410.             throw new IllegalStateException("Invalidating connection threw unexpected exception", e);
  1411.         }
  1412.     }

  1413.     /**
  1414.      * Gets the value of the accessToUnderlyingConnectionAllowed property.
  1415.      *
  1416.      * @return true if access to the underlying connection is allowed, false otherwise.
  1417.      */
  1418.     @Override
  1419.     public synchronized boolean isAccessToUnderlyingConnectionAllowed() {
  1420.         return this.accessToUnderlyingConnectionAllowed;
  1421.     }

  1422.     /**
  1423.      * Returns true if the statement pool is cleared when the connection is returned to its pool.
  1424.      *
  1425.      * @return true if the statement pool is cleared at connection return
  1426.      * @since 2.8.0
  1427.      */
  1428.     @Override
  1429.     public boolean isClearStatementPoolOnReturn() {
  1430.         return clearStatementPoolOnReturn;
  1431.     }

  1432.     /**
  1433.      * If true, this data source is closed and no more connections can be retrieved from this data source.
  1434.      *
  1435.      * @return true, if the data source is closed; false otherwise
  1436.      */
  1437.     @Override
  1438.     public synchronized boolean isClosed() {
  1439.         return closed;
  1440.     }

  1441.     /**
  1442.      * Delegates in a null-safe manner to {@link String#isEmpty()}.
  1443.      *
  1444.      * @param value the string to test, may be null.
  1445.      * @return boolean false if value is null, otherwise {@link String#isEmpty()}.
  1446.      */
  1447.     private boolean isEmpty(final String value) {
  1448.         return value == null || value.trim().isEmpty();
  1449.     }

  1450.     /**
  1451.      * Returns true if we are pooling statements.
  1452.      *
  1453.      * @return true if prepared and callable statements are pooled
  1454.      */
  1455.     @Override
  1456.     public synchronized boolean isPoolPreparedStatements() {
  1457.         return this.poolPreparedStatements;
  1458.     }

  1459.     @Override
  1460.     public boolean isWrapperFor(final Class<?> iface) throws SQLException {
  1461.         return iface != null && iface.isInstance(this);
  1462.     }

  1463.     private void jmxRegister() {
  1464.         // Return immediately if this DataSource has already been registered
  1465.         if (registeredJmxObjectName != null) {
  1466.             return;
  1467.         }
  1468.         // Return immediately if no JMX name has been specified
  1469.         final String requestedName = getJmxName();
  1470.         if (requestedName == null) {
  1471.             return;
  1472.         }
  1473.         registeredJmxObjectName = registerJmxObjectName(requestedName, null);
  1474.         try {
  1475.             final StandardMBean standardMBean = new StandardMBean(this, DataSourceMXBean.class);
  1476.             registeredJmxObjectName.registerMBean(standardMBean);
  1477.         } catch (final NotCompliantMBeanException e) {
  1478.             log.warn("The requested JMX name [" + requestedName + "] was not valid and will be ignored.");
  1479.         }
  1480.     }

  1481.     /**
  1482.      * Logs the given message.
  1483.      *
  1484.      * @param message the message to log.
  1485.      */
  1486.     protected void log(final String message) {
  1487.         if (logWriter != null) {
  1488.             logWriter.println(message);
  1489.         }
  1490.     }

  1491.     /**
  1492.      * Logs the given message and throwable.
  1493.      *
  1494.      * @param message value to be log.
  1495.      * @param throwable the throwable.
  1496.      * @since 2.7.0
  1497.      */
  1498.     protected void log(final String message, final Throwable throwable) {
  1499.         if (logWriter != null) {
  1500.             logWriter.println(message);
  1501.             throwable.printStackTrace(logWriter);
  1502.         }
  1503.     }

  1504.     @Override
  1505.     public void postDeregister() {
  1506.         // NO-OP
  1507.     }

  1508.     @Override
  1509.     public void postRegister(final Boolean registrationDone) {
  1510.         // NO-OP
  1511.     }

  1512.     @Override
  1513.     public void preDeregister() throws Exception {
  1514.         // NO-OP
  1515.     }

  1516.     @Override
  1517.     public ObjectName preRegister(final MBeanServer server, final ObjectName objectName) {
  1518.         registeredJmxObjectName = registerJmxObjectName(getJmxName(), objectName);
  1519.         return ObjectNameWrapper.unwrap(registeredJmxObjectName);
  1520.     }

  1521.     private ObjectNameWrapper registerJmxObjectName(final String requestedName, final ObjectName objectName) {
  1522.         ObjectNameWrapper objectNameWrapper = null;
  1523.         if (requestedName != null) {
  1524.             try {
  1525.                 objectNameWrapper = ObjectNameWrapper.wrap(requestedName);
  1526.             } catch (final MalformedObjectNameException e) {
  1527.                 log.warn("The requested JMX name '" + requestedName + "' was not valid and will be ignored.");
  1528.             }
  1529.         }
  1530.         if (objectNameWrapper == null) {
  1531.             objectNameWrapper = ObjectNameWrapper.wrap(objectName);
  1532.         }
  1533.         return objectNameWrapper;
  1534.     }

  1535.     /**
  1536.      * Removes a custom connection property.
  1537.      *
  1538.      * @param name Name of the custom connection property to remove
  1539.      * @see #addConnectionProperty(String, String)
  1540.      */
  1541.     public void removeConnectionProperty(final String name) {
  1542.         connectionProperties.remove(name);
  1543.     }

  1544.     /**
  1545.      * Restarts the datasource.
  1546.      * <p>
  1547.      * This method calls {@link #close()} and {@link #start()} in sequence within synchronized scope so any
  1548.      * connection requests that come in while the datasource is shutting down will be served by the new pool.
  1549.      * <p>
  1550.      * Idle connections that are stored in the connection pool when this method is invoked are closed, but
  1551.      * connections that are checked out to clients when this method is invoked are not affected. When client
  1552.      * applications subsequently invoke {@link Connection#close()} to return these connections to the pool, the
  1553.      * underlying JDBC connections are closed. These connections do not count in {@link #getMaxTotal()} or
  1554.      * {@link #getNumActive()} after invoking this method. For example, if there are 3 connections checked out by
  1555.      * clients when {@link #restart()} is invoked, after this method is called, {@link #getNumActive()} will
  1556.      * return 0 and up to {@link #getMaxTotal()} + 3 connections may be open until the connections sourced from
  1557.      * the original pool are returned.
  1558.      * <p>
  1559.      * The new connection pool created by this method is initialized with currently set configuration properties.
  1560.      *
  1561.      * @throws SQLException if an error occurs initializing the datasource
  1562.      */
  1563.     @Override
  1564.     public synchronized void restart() throws SQLException {
  1565.         close();
  1566.         start();
  1567.     }

  1568.     private <T> void setAbandoned(final BiConsumer<AbandonedConfig, T> consumer, final T object) {
  1569.         if (abandonedConfig == null) {
  1570.             abandonedConfig = new AbandonedConfig();
  1571.         }
  1572.         consumer.accept(abandonedConfig, object);
  1573.         final GenericObjectPool<?> gop = this.connectionPool;
  1574.         if (gop != null) {
  1575.             gop.setAbandonedConfig(abandonedConfig);
  1576.         }
  1577.     }

  1578.     /**
  1579.      * Sets the print writer to be used by this configuration to log information on abandoned objects.
  1580.      *
  1581.      * @param logWriter The new log writer
  1582.      */
  1583.     public void setAbandonedLogWriter(final PrintWriter logWriter) {
  1584.         setAbandoned(AbandonedConfig::setLogWriter, logWriter);
  1585.     }

  1586.     /**
  1587.      * If the connection pool implements {@link org.apache.commons.pool2.UsageTracking UsageTracking}, configure whether
  1588.      * the connection pool should record a stack trace every time a method is called on a pooled connection and retain
  1589.      * the most recent stack trace to aid debugging of abandoned connections.
  1590.      *
  1591.      * @param usageTracking A value of {@code true} will enable the recording of a stack trace on every use of a
  1592.      *                      pooled connection
  1593.      */
  1594.     public void setAbandonedUsageTracking(final boolean usageTracking) {
  1595.         setAbandoned(AbandonedConfig::setUseUsageTracking, usageTracking);
  1596.     }

  1597.     /**
  1598.      * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to
  1599.      * the underlying connection. (Default: false)
  1600.      * <p>
  1601.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1602.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  1603.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  1604.      * </p>
  1605.      *
  1606.      * @param allow Access to the underlying connection is granted when true.
  1607.      */
  1608.     public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) {
  1609.         this.accessToUnderlyingConnectionAllowed = allow;
  1610.     }

  1611.     /**
  1612.      * Sets the value of the flag that controls whether or not connections being returned to the pool will be checked
  1613.      * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
  1614.      * setting is {@code false} when the connection is returned. It is {@code true} by default.
  1615.      *
  1616.      * @param autoCommitOnReturn Whether or not connections being returned to the pool will be checked and configured
  1617.      *                           with auto-commit.
  1618.      * @since 2.6.0
  1619.      */
  1620.     public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) {
  1621.         this.autoCommitOnReturn = autoCommitOnReturn;
  1622.     }

  1623.     /**
  1624.      * Sets the state caching flag.
  1625.      *
  1626.      * @param cacheState The new value for the state caching flag
  1627.      */
  1628.     public void setCacheState(final boolean cacheState) {
  1629.         this.cacheState = cacheState;
  1630.     }

  1631.     /**
  1632.      * Sets whether the pool of statements (which was enabled with {@link #setPoolPreparedStatements(boolean)}) should
  1633.      * be cleared when the connection is returned to its pool. Default is false.
  1634.      *
  1635.      * @param clearStatementPoolOnReturn clear or not
  1636.      * @since 2.8.0
  1637.      */
  1638.     public void setClearStatementPoolOnReturn(final boolean clearStatementPoolOnReturn) {
  1639.         this.clearStatementPoolOnReturn = clearStatementPoolOnReturn;
  1640.     }

  1641.     /**
  1642.      * Sets the ConnectionFactory class name.
  1643.      *
  1644.      * @param connectionFactoryClassName A class name.
  1645.      * @since 2.7.0
  1646.      */
  1647.     public void setConnectionFactoryClassName(final String connectionFactoryClassName) {
  1648.         this.connectionFactoryClassName = isEmpty(connectionFactoryClassName) ? null : connectionFactoryClassName;
  1649.     }

  1650.     /**
  1651.      * Sets the collection of SQL statements to be executed when a physical connection is first created.
  1652.      * <p>
  1653.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1654.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  1655.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  1656.      * </p>
  1657.      *
  1658.      * @param connectionInitSqls Collection of SQL statements to execute on connection creation
  1659.      */
  1660.     public void setConnectionInitSqls(final Collection<String> connectionInitSqls) {
  1661.         final List<String> collect = Utils.isEmpty(connectionInitSqls) ? null
  1662.                 : connectionInitSqls.stream().filter(s -> !isEmpty(s)).collect(Collectors.toList());
  1663.         this.connectionInitSqls = Utils.isEmpty(collect) ? null : collect;
  1664.     }

  1665.     /**
  1666.      * Sets the list of SQL statements to be executed when a physical connection is first created.
  1667.      * <p>
  1668.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1669.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  1670.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  1671.      * </p>
  1672.      *
  1673.      * @param connectionInitSqls List of SQL statements to execute on connection creation
  1674.      * @since 2.12.0
  1675.      */
  1676.     public void setConnectionInitSqls(final List<String> connectionInitSqls) {
  1677.         setConnectionInitSqls((Collection<String>) connectionInitSqls);
  1678.     }

  1679.     private <T> void setConnectionPool(final BiConsumer<GenericObjectPool<PoolableConnection>, T> consumer, final T object) {
  1680.         if (connectionPool != null) {
  1681.             consumer.accept(connectionPool, object);
  1682.         }
  1683.     }

  1684.     /**
  1685.      * Sets the connection properties passed to driver.connect(...).
  1686.      * <p>
  1687.      * Format of the string must be [propertyName=property;]*
  1688.      * </p>
  1689.      * <p>
  1690.      * NOTE - The "user" and "password" properties will be added explicitly, so they do not need to be included here.
  1691.      * </p>
  1692.      *
  1693.      * @param connectionProperties the connection properties used to create new connections
  1694.      */
  1695.     public void setConnectionProperties(final String connectionProperties) {
  1696.         Objects.requireNonNull(connectionProperties, "connectionProperties");
  1697.         final String[] entries = connectionProperties.split(";");
  1698.         final Properties properties = new Properties();
  1699.         Stream.of(entries).filter(e -> !e.isEmpty()).forEach(entry -> {
  1700.             final int index = entry.indexOf('=');
  1701.             if (index > 0) {
  1702.                 final String name = entry.substring(0, index);
  1703.                 final String value = entry.substring(index + 1);
  1704.                 properties.setProperty(name, value);
  1705.             } else {
  1706.                 // no value is empty string which is how
  1707.                 // java.util.Properties works
  1708.                 properties.setProperty(entry, "");
  1709.             }
  1710.         });
  1711.         this.connectionProperties = properties;
  1712.     }

  1713.     /**
  1714.      * Sets default auto-commit state of connections returned by this datasource.
  1715.      * <p>
  1716.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1717.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  1718.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  1719.      * </p>
  1720.      *
  1721.      * @param defaultAutoCommit default auto-commit value
  1722.      */
  1723.     public void setDefaultAutoCommit(final Boolean defaultAutoCommit) {
  1724.         this.defaultAutoCommit = defaultAutoCommit;
  1725.     }

  1726.     /**
  1727.      * Sets the default catalog.
  1728.      * <p>
  1729.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1730.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  1731.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  1732.      * </p>
  1733.      *
  1734.      * @param defaultCatalog the default catalog
  1735.      */
  1736.     public void setDefaultCatalog(final String defaultCatalog) {
  1737.         this.defaultCatalog = isEmpty(defaultCatalog) ? null : defaultCatalog;
  1738.     }

  1739.     /**
  1740.      * Sets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
  1741.      * connection. {@code null} means that the driver default will be used.
  1742.      *
  1743.      * @param defaultQueryTimeoutDuration The default query timeout Duration.
  1744.      * @since 2.10.0
  1745.      */
  1746.     public void setDefaultQueryTimeout(final Duration defaultQueryTimeoutDuration) {
  1747.         this.defaultQueryTimeoutDuration = defaultQueryTimeoutDuration;
  1748.     }

  1749.     /**
  1750.      * Sets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
  1751.      * connection. {@code null} means that the driver default will be used.
  1752.      *
  1753.      * @param defaultQueryTimeoutSeconds The default query timeout in seconds.
  1754.      * @deprecated Use {@link #setDefaultQueryTimeout(Duration)}.
  1755.      */
  1756.     @Deprecated
  1757.     public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) {
  1758.         this.defaultQueryTimeoutDuration = defaultQueryTimeoutSeconds == null ? null : Duration.ofSeconds(defaultQueryTimeoutSeconds);
  1759.     }

  1760.     /**
  1761.      * Sets defaultReadonly property.
  1762.      * <p>
  1763.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1764.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  1765.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  1766.      * </p>
  1767.      *
  1768.      * @param defaultReadOnly default read-only value
  1769.      */
  1770.     public void setDefaultReadOnly(final Boolean defaultReadOnly) {
  1771.         this.defaultReadOnly = defaultReadOnly;
  1772.     }

  1773.     /**
  1774.      * Sets the default schema.
  1775.      * <p>
  1776.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1777.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  1778.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  1779.      * </p>
  1780.      *
  1781.      * @param defaultSchema the default catalog
  1782.      * @since 2.5.0
  1783.      */
  1784.     public void setDefaultSchema(final String defaultSchema) {
  1785.         this.defaultSchema = isEmpty(defaultSchema) ? null : defaultSchema;
  1786.     }

  1787.     /**
  1788.      * Sets the default transaction isolation state for returned connections.
  1789.      * <p>
  1790.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1791.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  1792.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  1793.      * </p>
  1794.      *
  1795.      * @param defaultTransactionIsolation the default transaction isolation state
  1796.      * @see Connection#getTransactionIsolation
  1797.      */
  1798.     public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) {
  1799.         this.defaultTransactionIsolation = defaultTransactionIsolation;
  1800.     }

  1801.     /**
  1802.      * Sets the SQL State codes that should be ignored when determining fatal disconnection conditions.
  1803.      * <p>
  1804.      * This method allows you to specify a collection of SQL State codes that will be excluded from
  1805.      * disconnection checks. These codes will not trigger the "fatally disconnected" status even if they
  1806.      * match the typical disconnection criteria. This can be useful in scenarios where certain SQL State
  1807.      * codes (e.g., specific codes starting with "08") are known to be non-fatal in your environment.
  1808.      * </p>
  1809.      * <p>
  1810.      * The effect of this method is similar to the one described in {@link #setDisconnectionSqlCodes(Collection)},
  1811.      * but instead of setting codes that signal fatal disconnections, it defines codes that should be ignored
  1812.      * during such checks.
  1813.      * </p>
  1814.      * <p>
  1815.      * Note: This method currently has no effect once the pool has been initialized. The pool is initialized the first
  1816.      * time one of the following methods is invoked: {@code getConnection, setLogwriter, setLoginTimeout,
  1817.      * getLoginTimeout, getLogWriter}.
  1818.      * </p>
  1819.      *
  1820.      * @param disconnectionIgnoreSqlCodes SQL State codes that should be ignored in disconnection checks
  1821.      * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionSqlCodes}.
  1822.      * @since 2.13.0
  1823.      */
  1824.     public void setDisconnectionIgnoreSqlCodes(final Collection<String> disconnectionIgnoreSqlCodes) {
  1825.         Utils.checkSqlCodes(disconnectionIgnoreSqlCodes, this.disconnectionSqlCodes);
  1826.         final Set<String> collect = Utils.isEmpty(disconnectionIgnoreSqlCodes) ? null
  1827.                 : disconnectionIgnoreSqlCodes.stream().filter(s -> !isEmpty(s)).collect(toLinkedHashSet());
  1828.         this.disconnectionIgnoreSqlCodes = Utils.isEmpty(collect) ? null : collect;
  1829.     }

  1830.     /**
  1831.      * Sets the SQL State codes considered to signal fatal conditions.
  1832.      * <p>
  1833.      * Overrides the defaults in {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with
  1834.      * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #getFastFailValidation()}
  1835.      * is {@code true}, whenever connections created by this datasource generate exceptions with SQL State codes in this
  1836.      * list, they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at
  1837.      * isValid or validation query).
  1838.      * </p>
  1839.      * <p>
  1840.      * If {@link #getFastFailValidation()} is {@code false} setting this property has no effect.
  1841.      * </p>
  1842.      * <p>
  1843.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1844.      * time one of the following methods is invoked: {@code getConnection, setLogwriter,
  1845.      * setLoginTimeout, getLoginTimeout, getLogWriter}.
  1846.      * </p>
  1847.      *
  1848.      * @param disconnectionSqlCodes SQL State codes considered to signal fatal conditions
  1849.      * @since 2.1
  1850.      * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionIgnoreSqlCodes}.
  1851.      */
  1852.     public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) {
  1853.         Utils.checkSqlCodes(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes);
  1854.         final Set<String> collect = Utils.isEmpty(disconnectionSqlCodes) ? null
  1855.                 : disconnectionSqlCodes.stream().filter(s -> !isEmpty(s)).collect(toLinkedHashSet());
  1856.         this.disconnectionSqlCodes = Utils.isEmpty(collect) ? null : collect;
  1857.     }

  1858.     /**
  1859.      * Sets the JDBC Driver instance to use for this pool.
  1860.      * <p>
  1861.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1862.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  1863.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  1864.      * </p>
  1865.      *
  1866.      * @param driver The JDBC Driver instance to use for this pool.
  1867.      */
  1868.     public synchronized void setDriver(final Driver driver) {
  1869.         this.driver = driver;
  1870.     }

  1871.     /**
  1872.      * Sets the class loader to be used to load the JDBC driver.
  1873.      * <p>
  1874.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1875.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  1876.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  1877.      * </p>
  1878.      *
  1879.      * @param driverClassLoader the class loader with which to load the JDBC driver
  1880.      */
  1881.     public synchronized void setDriverClassLoader(final ClassLoader driverClassLoader) {
  1882.         this.driverClassLoader = driverClassLoader;
  1883.     }

  1884.     /**
  1885.      * Sets the JDBC driver class name.
  1886.      * <p>
  1887.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1888.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  1889.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  1890.      * </p>
  1891.      *
  1892.      * @param driverClassName the class name of the JDBC driver
  1893.      */
  1894.     public synchronized void setDriverClassName(final String driverClassName) {
  1895.         this.driverClassName = isEmpty(driverClassName) ? null : driverClassName;
  1896.     }

  1897.     /**
  1898.      * Sets the {code durationBetweenEvictionRuns} property.
  1899.      *
  1900.      * @param timeBetweenEvictionRunsMillis the new time between evictor runs
  1901.      * @see #setDurationBetweenEvictionRuns(Duration)
  1902.      * @since 2.10.0
  1903.      */
  1904.     public synchronized void setDurationBetweenEvictionRuns(final Duration timeBetweenEvictionRunsMillis) {
  1905.         this.durationBetweenEvictionRuns = timeBetweenEvictionRunsMillis;
  1906.         setConnectionPool(GenericObjectPool::setDurationBetweenEvictionRuns, timeBetweenEvictionRunsMillis);
  1907.     }

  1908.     /**
  1909.      * Sets the value of the flag that controls whether or not connections being returned to the pool will be checked
  1910.      * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
  1911.      * setting is {@code false} when the connection is returned. It is {@code true} by default.
  1912.      *
  1913.      * @param autoCommitOnReturn Whether or not connections being returned to the pool will be checked and configured
  1914.      *                           with auto-commit.
  1915.      * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}.
  1916.      */
  1917.     @Deprecated
  1918.     public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) {
  1919.         this.autoCommitOnReturn = autoCommitOnReturn;
  1920.     }

  1921.     /**
  1922.      * Sets the EvictionPolicy implementation to use with this connection pool.
  1923.      *
  1924.      * @param evictionPolicyClassName The fully qualified class name of the EvictionPolicy implementation
  1925.      */
  1926.     public synchronized void setEvictionPolicyClassName(final String evictionPolicyClassName) {
  1927.         setConnectionPool(GenericObjectPool::setEvictionPolicyClassName, evictionPolicyClassName);
  1928.         this.evictionPolicyClassName = evictionPolicyClassName;
  1929.     }

  1930.     /**
  1931.      * @see #getFastFailValidation()
  1932.      * @param fastFailValidation true means connections created by this factory will fast fail validation
  1933.      * @since 2.1
  1934.      */
  1935.     public void setFastFailValidation(final boolean fastFailValidation) {
  1936.         this.fastFailValidation = fastFailValidation;
  1937.     }

  1938.     /**
  1939.      * Sets the initial size of the connection pool.
  1940.      * <p>
  1941.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  1942.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  1943.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  1944.      * </p>
  1945.      *
  1946.      * @param initialSize the number of connections created when the pool is initialized
  1947.      */
  1948.     public synchronized void setInitialSize(final int initialSize) {
  1949.         this.initialSize = initialSize;
  1950.     }

  1951.     /**
  1952.      * Sets the JMX name that has been requested for this DataSource. If the requested name is not valid, an alternative
  1953.      * may be chosen. This DataSource will attempt to register itself using this name. If another component registers
  1954.      * this DataSource with JMX and this name is valid this name will be used in preference to any specified by the
  1955.      * other component.
  1956.      *
  1957.      * @param jmxName The JMX name that has been requested for this DataSource
  1958.      */
  1959.     public void setJmxName(final String jmxName) {
  1960.         this.jmxName = jmxName;
  1961.     }

  1962.     /**
  1963.      * Sets the LIFO property. True means the pool behaves as a LIFO queue; false means FIFO.
  1964.      *
  1965.      * @param lifo the new value for the LIFO property
  1966.      */
  1967.     public synchronized void setLifo(final boolean lifo) {
  1968.         this.lifo = lifo;
  1969.         setConnectionPool(GenericObjectPool::setLifo, lifo);
  1970.     }

  1971.     /**
  1972.      * @param logAbandoned new logAbandoned property value
  1973.      */
  1974.     public void setLogAbandoned(final boolean logAbandoned) {
  1975.         setAbandoned(AbandonedConfig::setLogAbandoned, logAbandoned);
  1976.     }

  1977.     /**
  1978.      * When {@link #getMaxConnDuration()} is set to limit connection lifetime, this property determines whether or
  1979.      * not log messages are generated when the pool closes connections due to maximum lifetime exceeded. Set this
  1980.      * property to false to suppress log messages when connections expire.
  1981.      *
  1982.      * @param logExpiredConnections Whether or not log messages are generated when the pool closes connections due to
  1983.      *                              maximum lifetime exceeded.
  1984.      */
  1985.     public void setLogExpiredConnections(final boolean logExpiredConnections) {
  1986.         this.logExpiredConnections = logExpiredConnections;
  1987.     }

  1988.     /**
  1989.      * <strong>BasicDataSource does NOT support this method. </strong>
  1990.      *
  1991.      * <p>
  1992.      * Sets the login timeout (in seconds) for connecting to the database.
  1993.      * </p>
  1994.      * <p>
  1995.      * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool.
  1996.      * </p>
  1997.      *
  1998.      * @param loginTimeout The new login timeout, or zero for no timeout
  1999.      * @throws UnsupportedOperationException If the DataSource implementation does not support the login timeout
  2000.      *                                       feature.
  2001.      * @throws SQLException                  if a database access error occurs
  2002.      */
  2003.     @Override
  2004.     public void setLoginTimeout(final int loginTimeout) throws SQLException {
  2005.         // This method isn't supported by the PoolingDataSource returned by the
  2006.         // createDataSource
  2007.         throw new UnsupportedOperationException("Not supported by BasicDataSource");
  2008.     }

  2009.     /**
  2010.      * Sets the log writer being used by this data source.
  2011.      * <p>
  2012.      * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool.
  2013.      * </p>
  2014.      *
  2015.      * @param logWriter The new log writer
  2016.      * @throws SQLException if a database access error occurs
  2017.      */
  2018.     @Override
  2019.     public void setLogWriter(final PrintWriter logWriter) throws SQLException {
  2020.         createDataSource().setLogWriter(logWriter);
  2021.         this.logWriter = logWriter;
  2022.     }

  2023.     /**
  2024.      * Sets the maximum permitted lifetime of a connection. A value of zero or less indicates an
  2025.      * infinite lifetime.
  2026.      * <p>
  2027.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  2028.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  2029.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  2030.      * </p>
  2031.      *
  2032.      * @param maxConnDuration The maximum permitted lifetime of a connection.
  2033.      * @since 2.10.0
  2034.      */
  2035.     public void setMaxConn(final Duration maxConnDuration) {
  2036.         this.maxConnDuration = maxConnDuration;
  2037.     }

  2038.     /**
  2039.      * Sets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an
  2040.      * infinite lifetime.
  2041.      * <p>
  2042.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  2043.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  2044.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  2045.      * </p>
  2046.      *
  2047.      * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection in milliseconds.
  2048.      * @deprecated Use {@link #setMaxConn(Duration)}.
  2049.      */
  2050.     @Deprecated
  2051.     public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) {
  2052.         this.maxConnDuration = Duration.ofMillis(maxConnLifetimeMillis);
  2053.     }

  2054.     /**
  2055.      * Sets the maximum number of connections that can remain idle in the pool. Excess idle connections are destroyed on
  2056.      * return to the pool.
  2057.      *
  2058.      * @see #getMaxIdle()
  2059.      * @param maxIdle the new value for maxIdle
  2060.      */
  2061.     public synchronized void setMaxIdle(final int maxIdle) {
  2062.         this.maxIdle = maxIdle;
  2063.         setConnectionPool(GenericObjectPool::setMaxIdle, maxIdle);
  2064.     }

  2065.     /**
  2066.      * Sets the value of the {@code maxOpenPreparedStatements} property.
  2067.      * <p>
  2068.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  2069.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  2070.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  2071.      * </p>
  2072.      *
  2073.      * @param maxOpenStatements the new maximum number of prepared statements
  2074.      */
  2075.     public synchronized void setMaxOpenPreparedStatements(final int maxOpenStatements) {
  2076.         this.maxOpenPreparedStatements = maxOpenStatements;
  2077.     }

  2078.     /**
  2079.      * Sets the maximum total number of idle and borrows connections that can be active at the same time. Use a negative
  2080.      * value for no limit.
  2081.      *
  2082.      * @param maxTotal the new value for maxTotal
  2083.      * @see #getMaxTotal()
  2084.      */
  2085.     public synchronized void setMaxTotal(final int maxTotal) {
  2086.         this.maxTotal = maxTotal;
  2087.         setConnectionPool(GenericObjectPool::setMaxTotal, maxTotal);
  2088.     }

  2089.     /**
  2090.      * Sets the MaxWaitMillis property. Use -1 to make the pool wait indefinitely.
  2091.      *
  2092.      * @param maxWaitDuration the new value for MaxWaitMillis
  2093.      * @see #getMaxWaitDuration()
  2094.      * @since 2.10.0
  2095.      */
  2096.     public synchronized void setMaxWait(final Duration maxWaitDuration) {
  2097.         this.maxWaitDuration = maxWaitDuration;
  2098.         setConnectionPool(GenericObjectPool::setMaxWait, maxWaitDuration);
  2099.     }

  2100.     /**
  2101.      * Sets the MaxWaitMillis property. Use -1 to make the pool wait indefinitely.
  2102.      *
  2103.      * @param maxWaitMillis the new value for MaxWaitMillis
  2104.      * @see #getMaxWaitDuration()
  2105.      * @deprecated {@link #setMaxWait(Duration)}.
  2106.      */
  2107.     @Deprecated
  2108.     public synchronized void setMaxWaitMillis(final long maxWaitMillis) {
  2109.         setMaxWait(Duration.ofMillis(maxWaitMillis));
  2110.     }

  2111.     /**
  2112.      * Sets the {code minEvictableIdleDuration} property.
  2113.      *
  2114.      * @param minEvictableIdleDuration the minimum amount of time an object may sit idle in the pool
  2115.      * @see #setMinEvictableIdle(Duration)
  2116.      * @since 2.10.0
  2117.      */
  2118.     public synchronized void setMinEvictableIdle(final Duration minEvictableIdleDuration) {
  2119.         this.minEvictableIdleDuration = minEvictableIdleDuration;
  2120.         setConnectionPool(GenericObjectPool::setMinEvictableIdleDuration, minEvictableIdleDuration);
  2121.     }

  2122.     /**
  2123.      * Sets the {code minEvictableIdleDuration} property.
  2124.      *
  2125.      * @param minEvictableIdleTimeMillis the minimum amount of time an object may sit idle in the pool
  2126.      * @see #setMinEvictableIdle(Duration)
  2127.      * @deprecated Use {@link #setMinEvictableIdle(Duration)}.
  2128.      */
  2129.     @Deprecated
  2130.     public synchronized void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) {
  2131.         setMinEvictableIdle(Duration.ofMillis(minEvictableIdleTimeMillis));
  2132.     }

  2133.     /**
  2134.      * Sets the minimum number of idle connections in the pool. The pool attempts to ensure that minIdle connections are
  2135.      * available when the idle object evictor runs. The value of this property has no effect unless
  2136.      * {code durationBetweenEvictionRuns} has a positive value.
  2137.      *
  2138.      * @param minIdle the new value for minIdle
  2139.      * @see GenericObjectPool#setMinIdle(int)
  2140.      */
  2141.     public synchronized void setMinIdle(final int minIdle) {
  2142.         this.minIdle = minIdle;
  2143.         setConnectionPool(GenericObjectPool::setMinIdle, minIdle);
  2144.     }

  2145.     /**
  2146.      * Sets the value of the {code numTestsPerEvictionRun} property.
  2147.      *
  2148.      * @param numTestsPerEvictionRun the new {code numTestsPerEvictionRun} value
  2149.      * @see #setNumTestsPerEvictionRun(int)
  2150.      */
  2151.     public synchronized void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
  2152.         this.numTestsPerEvictionRun = numTestsPerEvictionRun;
  2153.         setConnectionPool(GenericObjectPool::setNumTestsPerEvictionRun, numTestsPerEvictionRun);
  2154.     }

  2155.     /**
  2156.      * Sets the {code password}.
  2157.      * <p>
  2158.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  2159.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  2160.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  2161.      * </p>
  2162.      *
  2163.      * @param password new value for the password
  2164.      */
  2165.     public void setPassword(final String password) {
  2166.         this.password = password;
  2167.     }

  2168.     /**
  2169.      * Sets whether to pool statements or not.
  2170.      * <p>
  2171.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  2172.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  2173.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  2174.      * </p>
  2175.      *
  2176.      * @param poolingStatements pooling on or off
  2177.      */
  2178.     public synchronized void setPoolPreparedStatements(final boolean poolingStatements) {
  2179.         this.poolPreparedStatements = poolingStatements;
  2180.     }

  2181.     /**
  2182.      * Sets if connection level JMX tracking is requested for this DataSource. If true, each connection will be
  2183.      * registered for tracking with JMX.
  2184.      *
  2185.      * @param registerConnectionMBean connection tracking requested for this DataSource.
  2186.      */
  2187.     public void setRegisterConnectionMBean(final boolean registerConnectionMBean) {
  2188.         this.registerConnectionMBean = registerConnectionMBean;
  2189.     }

  2190.     /**
  2191.      * @param removeAbandonedOnBorrow true means abandoned connections may be removed when connections are borrowed from
  2192.      *                                the pool.
  2193.      * @see #getRemoveAbandonedOnBorrow()
  2194.      */
  2195.     public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) {
  2196.         setAbandoned(AbandonedConfig::setRemoveAbandonedOnBorrow, removeAbandonedOnBorrow);
  2197.     }

  2198.     /**
  2199.      * @param removeAbandonedOnMaintenance true means abandoned connections may be removed on pool maintenance.
  2200.      * @see #getRemoveAbandonedOnMaintenance()
  2201.      */
  2202.     public void setRemoveAbandonedOnMaintenance(final boolean removeAbandonedOnMaintenance) {
  2203.         setAbandoned(AbandonedConfig::setRemoveAbandonedOnMaintenance, removeAbandonedOnMaintenance);
  2204.     }

  2205.     /**
  2206.      * Sets the timeout before an abandoned connection can be removed.
  2207.      * <p>
  2208.      * Setting this property has no effect if {@link #getRemoveAbandonedOnBorrow()} and
  2209.      * {code getRemoveAbandonedOnMaintenance()} are false.
  2210.      * </p>
  2211.      *
  2212.      * @param removeAbandonedTimeout new abandoned timeout
  2213.      * @see #getRemoveAbandonedTimeoutDuration()
  2214.      * @see #getRemoveAbandonedOnBorrow()
  2215.      * @see #getRemoveAbandonedOnMaintenance()
  2216.      * @since 2.10.0
  2217.      */
  2218.     public void setRemoveAbandonedTimeout(final Duration removeAbandonedTimeout) {
  2219.         setAbandoned(AbandonedConfig::setRemoveAbandonedTimeout, removeAbandonedTimeout);
  2220.     }

  2221.     /**
  2222.      * Sets the timeout in seconds before an abandoned connection can be removed.
  2223.      * <p>
  2224.      * Setting this property has no effect if {@link #getRemoveAbandonedOnBorrow()} and
  2225.      * {@link #getRemoveAbandonedOnMaintenance()} are false.
  2226.      * </p>
  2227.      *
  2228.      * @param removeAbandonedTimeout new abandoned timeout in seconds
  2229.      * @see #getRemoveAbandonedTimeoutDuration()
  2230.      * @see #getRemoveAbandonedOnBorrow()
  2231.      * @see #getRemoveAbandonedOnMaintenance()
  2232.      * @deprecated Use {@link #setRemoveAbandonedTimeout(Duration)}.
  2233.      */
  2234.     @Deprecated
  2235.     public void setRemoveAbandonedTimeout(final int removeAbandonedTimeout) {
  2236.         setAbandoned(AbandonedConfig::setRemoveAbandonedTimeout, Duration.ofSeconds(removeAbandonedTimeout));
  2237.     }

  2238.     /**
  2239.      * Sets the flag that controls if a connection will be rolled back when it is returned to the pool if auto commit is
  2240.      * not enabled and the connection is not read only.
  2241.      *
  2242.      * @param rollbackOnReturn whether a connection will be rolled back when it is returned to the pool.
  2243.      */
  2244.     public void setRollbackOnReturn(final boolean rollbackOnReturn) {
  2245.         this.rollbackOnReturn = rollbackOnReturn;
  2246.     }

  2247.     /**
  2248.      * Sets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the
  2249.      * idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool.
  2250.      *
  2251.      * @param softMinEvictableIdleTimeMillis minimum amount of time a connection may sit idle in the pool before it is
  2252.      *                                       eligible for eviction, assuming there are minIdle idle connections in the
  2253.      *                                       pool.
  2254.      * @see #getSoftMinEvictableIdleTimeMillis
  2255.      * @since 2.10.0
  2256.      */
  2257.     public synchronized void setSoftMinEvictableIdle(final Duration softMinEvictableIdleTimeMillis) {
  2258.         this.softMinEvictableIdleDuration = softMinEvictableIdleTimeMillis;
  2259.         setConnectionPool(GenericObjectPool::setSoftMinEvictableIdleDuration, softMinEvictableIdleTimeMillis);
  2260.     }

  2261.     /**
  2262.      * Sets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the
  2263.      * idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool.
  2264.      *
  2265.      * @param softMinEvictableIdleTimeMillis minimum amount of time a connection may sit idle in the pool before it is
  2266.      *                                       eligible for eviction, assuming there are minIdle idle connections in the
  2267.      *                                       pool.
  2268.      * @see #getSoftMinEvictableIdleTimeMillis
  2269.      * @deprecated Use {@link #setSoftMinEvictableIdle(Duration)}.
  2270.      */
  2271.     @Deprecated
  2272.     public synchronized void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) {
  2273.         setSoftMinEvictableIdle(Duration.ofMillis(softMinEvictableIdleTimeMillis));
  2274.     }

  2275.     /**
  2276.      * Sets the {code testOnBorrow} property. This property determines whether or not the pool will validate objects
  2277.      * before they are borrowed from the pool.
  2278.      *
  2279.      * @param testOnBorrow new value for testOnBorrow property
  2280.      */
  2281.     public synchronized void setTestOnBorrow(final boolean testOnBorrow) {
  2282.         this.testOnBorrow = testOnBorrow;
  2283.         setConnectionPool(GenericObjectPool::setTestOnBorrow, testOnBorrow);
  2284.     }

  2285.     /**
  2286.      * Sets the {code testOnCreate} property. This property determines whether or not the pool will validate objects
  2287.      * immediately after they are created by the pool
  2288.      *
  2289.      * @param testOnCreate new value for testOnCreate property
  2290.      */
  2291.     public synchronized void setTestOnCreate(final boolean testOnCreate) {
  2292.         this.testOnCreate = testOnCreate;
  2293.         setConnectionPool(GenericObjectPool::setTestOnCreate, testOnCreate);
  2294.     }

  2295.     /**
  2296.      * Sets the {@code testOnReturn} property. This property determines whether or not the pool will validate
  2297.      * objects before they are returned to the pool.
  2298.      *
  2299.      * @param testOnReturn new value for testOnReturn property
  2300.      */
  2301.     public synchronized void setTestOnReturn(final boolean testOnReturn) {
  2302.         this.testOnReturn = testOnReturn;
  2303.         setConnectionPool(GenericObjectPool::setTestOnReturn, testOnReturn);
  2304.     }

  2305.     /**
  2306.      * Sets the {@code testWhileIdle} property. This property determines whether or not the idle object evictor
  2307.      * will validate connections.
  2308.      *
  2309.      * @param testWhileIdle new value for testWhileIdle property
  2310.      */
  2311.     public synchronized void setTestWhileIdle(final boolean testWhileIdle) {
  2312.         this.testWhileIdle = testWhileIdle;
  2313.         setConnectionPool(GenericObjectPool::setTestWhileIdle, testWhileIdle);
  2314.     }

  2315.     /**
  2316.      * Sets the {code durationBetweenEvictionRuns} property.
  2317.      *
  2318.      * @param timeBetweenEvictionRunsMillis the new time between evictor runs
  2319.      * @see #setDurationBetweenEvictionRuns(Duration)
  2320.      * @deprecated Use {@link #setDurationBetweenEvictionRuns(Duration)}.
  2321.      */
  2322.     @Deprecated
  2323.     public synchronized void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
  2324.         setDurationBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRunsMillis));
  2325.     }

  2326.     /**
  2327.      * Sets the {code connection string}.
  2328.      * <p>
  2329.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  2330.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  2331.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  2332.      * </p>
  2333.      *
  2334.      * @param connectionString the new value for the JDBC connection connectionString
  2335.      */
  2336.     public synchronized void setUrl(final String connectionString) {
  2337.         this.connectionString = connectionString;
  2338.     }

  2339.     /**
  2340.      * Sets the {code userName}.
  2341.      * <p>
  2342.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  2343.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  2344.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  2345.      * </p>
  2346.      *
  2347.      * @param userName the new value for the JDBC connection user name
  2348.      */
  2349.     public void setUsername(final String userName) {
  2350.         this.userName = userName;
  2351.     }

  2352.     /**
  2353.      * Sets the {code validationQuery}.
  2354.      * <p>
  2355.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  2356.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  2357.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  2358.      * </p>
  2359.      *
  2360.      * @param validationQuery the new value for the validation query
  2361.      */
  2362.     public void setValidationQuery(final String validationQuery) {
  2363.         this.validationQuery = isEmpty(validationQuery) ? null : validationQuery;
  2364.     }

  2365.     /**
  2366.      * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a
  2367.      * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout.
  2368.      * <p>
  2369.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  2370.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  2371.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  2372.      * </p>
  2373.      *
  2374.      * @param validationQueryTimeoutDuration new validation query timeout value in seconds
  2375.      * @since 2.10.0
  2376.      */
  2377.     public void setValidationQueryTimeout(final Duration validationQueryTimeoutDuration) {
  2378.         this.validationQueryTimeoutDuration = validationQueryTimeoutDuration;
  2379.     }

  2380.     /**
  2381.      * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a
  2382.      * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout.
  2383.      * <p>
  2384.      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
  2385.      * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
  2386.      * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
  2387.      * </p>
  2388.      *
  2389.      * @param validationQueryTimeoutSeconds new validation query timeout value in seconds
  2390.      * @deprecated Use {@link #setValidationQueryTimeout(Duration)}.
  2391.      */
  2392.     @Deprecated
  2393.     public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) {
  2394.         this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds);
  2395.     }

  2396.     /**
  2397.      * Starts the datasource.
  2398.      * <p>
  2399.      * It is not necessary to call this method before using a newly created BasicDataSource instance, but
  2400.      * calling it in that context causes the datasource to be immediately initialized (instead of waiting for
  2401.      * the first {@link #getConnection()} request). Its primary use is to restart and reinitialize a
  2402.      * datasource that has been closed.
  2403.      * <p>
  2404.      * When this method is called after {@link #close()}, connections checked out by clients
  2405.      * before the datasource was stopped do not count in {@link #getMaxTotal()} or {@link #getNumActive()}.
  2406.      * For example, if there are 3 connections checked out by clients when {@link #close()} is invoked and they are
  2407.      * not returned before {@link #start()} is invoked, after this method is called, {@link #getNumActive()} will
  2408.      * return 0.  These connections will be physically closed when they are returned, but they will not count against
  2409.      * the maximum allowed in the newly started datasource.
  2410.      *
  2411.      * @throws SQLException if an error occurs initializing the datasource
  2412.      */
  2413.     @Override
  2414.     public synchronized void start() throws SQLException {
  2415.         closed = false;
  2416.         createDataSource();
  2417.     }

  2418.     /**
  2419.      * Starts the connection pool maintenance task, if configured.
  2420.      */
  2421.     protected void startPoolMaintenance() {
  2422.         if (connectionPool != null && durationBetweenEvictionRuns.compareTo(Duration.ZERO) > 0) {
  2423.             connectionPool.setDurationBetweenEvictionRuns(durationBetweenEvictionRuns);
  2424.         }
  2425.     }

  2426.     private Collector<String, ?, LinkedHashSet<String>> toLinkedHashSet() {
  2427.         return Collectors.toCollection(LinkedHashSet::new);
  2428.     }

  2429.     @Override
  2430.     public <T> T unwrap(final Class<T> iface) throws SQLException {
  2431.         if (isWrapperFor(iface)) {
  2432.             return iface.cast(this);
  2433.         }
  2434.         throw new SQLException(this + " is not a wrapper for " + iface);
  2435.     }

  2436.     private void updateJmxName(final GenericObjectPoolConfig<?> config) {
  2437.         if (registeredJmxObjectName == null) {
  2438.             return;
  2439.         }
  2440.         final StringBuilder base = new StringBuilder(registeredJmxObjectName.toString());
  2441.         base.append(Constants.JMX_CONNECTION_POOL_BASE_EXT);
  2442.         config.setJmxNameBase(base.toString());
  2443.         config.setJmxNamePrefix(Constants.JMX_CONNECTION_POOL_PREFIX);
  2444.     }

  2445. }