    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.dbcp2;
    018
    019import java.io.OutputStreamWriter;
    020import java.io.PrintWriter;
    021import java.nio.charset.StandardCharsets;
    022import java.security.AccessController;
    023import java.security.PrivilegedActionException;
    024import java.security.PrivilegedExceptionAction;
    025import java.sql.Connection;
    026import java.sql.Driver;
    027import java.sql.DriverManager;
    028import java.sql.SQLException;
    029import java.sql.SQLFeatureNotSupportedException;
    030import java.time.Duration;
    031import java.util.Collection;
    032import java.util.Collections;
    033import java.util.List;
    034import java.util.Objects;
    035import java.util.Properties;
    036import java.util.Set;
    037import java.util.function.BiConsumer;
    038import java.util.logging.Logger;
    039import java.util.stream.Collectors;
    040import java.util.stream.Stream;
    041
    042import javax.management.MBeanRegistration;
    043import javax.management.MBeanServer;
    044import javax.management.MalformedObjectNameException;
    045import javax.management.NotCompliantMBeanException;
    046import javax.management.ObjectName;
    047import javax.management.StandardMBean;
    048import javax.sql.DataSource;
    049
    050import org.apache.commons.logging.Log;
    051import org.apache.commons.logging.LogFactory;
    052import org.apache.commons.pool2.PooledObject;
    053import org.apache.commons.pool2.impl.AbandonedConfig;
    054import org.apache.commons.pool2.impl.BaseObjectPoolConfig;
    055import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
    056import org.apache.commons.pool2.impl.GenericObjectPool;
    057import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
    058
    059/**
    060 * Basic implementation of {@code javax.sql.DataSource} that is configured via JavaBeans properties.
    061 *
    062 * <p>
    063 * This is not the only way to combine the <em>commons-dbcp2</em> and <em>commons-pool2</em> packages, but provides a
    064 * one-stop solution for basic requirements.
    065 * </p>
    066 *
    067 * @since 2.0
    068 */
    069public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBeanRegistration, AutoCloseable {
    070
    071    private static final Log log = LogFactory.getLog(BasicDataSource.class);
    072
    073    static {
    074        // Attempt to prevent deadlocks - see DBCP - 272
    075        DriverManager.getDrivers();
    076        try {
    077            // Load classes now to prevent AccessControlExceptions later
    078            // A number of classes are loaded when getConnection() is called
    079            // but the following classes are not loaded and therefore require
    080            // explicit loading.
    081            if (Utils.isSecurityEnabled()) {
    082                final ClassLoader loader = BasicDataSource.class.getClassLoader();
    083                final String dbcpPackageName = BasicDataSource.class.getPackage().getName();
    084                loader.loadClass(dbcpPackageName + ".DelegatingCallableStatement");
    085                loader.loadClass(dbcpPackageName + ".DelegatingDatabaseMetaData");
    086                loader.loadClass(dbcpPackageName + ".DelegatingPreparedStatement");
    087                loader.loadClass(dbcpPackageName + ".DelegatingResultSet");
    088                loader.loadClass(dbcpPackageName + ".PoolableCallableStatement");
    089                loader.loadClass(dbcpPackageName + ".PoolablePreparedStatement");
    090                loader.loadClass(dbcpPackageName + ".PoolingConnection$StatementType");
    091                loader.loadClass(dbcpPackageName + ".PStmtKey");
    092
    093                final String poolPackageName = PooledObject.class.getPackage().getName();
    094                loader.loadClass(poolPackageName + ".impl.LinkedBlockingDeque$Node");
    095                loader.loadClass(poolPackageName + ".impl.GenericKeyedObjectPool$ObjectDeque");
    096            }
    097        } catch (final ClassNotFoundException cnfe) {
    098            throw new IllegalStateException("Unable to pre-load classes", cnfe);
    099        }
    100    }
    101
    102    /**
    103     * Validates the given factory.
    104     *
    105     * @param connectionFactory the factory
    106     * @throws SQLException Thrown by one of the factory methods while managing a temporary pooled object.
    107     */
    108    @SuppressWarnings("resource")
    109    protected static void validateConnectionFactory(final PoolableConnectionFactory connectionFactory) throws SQLException {
    110        PoolableConnection conn = null;
    111        PooledObject<PoolableConnection> p = null;
    112        try {
    113            p = connectionFactory.makeObject();
    114            conn = p.getObject();
    115            connectionFactory.activateObject(p);
    116            connectionFactory.validateConnection(conn);
    117            connectionFactory.passivateObject(p);
    118        } finally {
    119            if (p != null) {
    120                connectionFactory.destroyObject(p);
    121            }
    122        }
    123    }
    124
    125    /**
    126     * The default auto-commit state of connections created by this pool.
    127     */
    128    private volatile Boolean defaultAutoCommit;
    129
    130    /**
    131     * The default read-only state of connections created by this pool.
    132     */
    133    private transient Boolean defaultReadOnly;
    134
    135    /**
    136     * The default TransactionIsolation state of connections created by this pool.
    137     */
    138    private volatile int defaultTransactionIsolation = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION;
    139
    140    private Duration defaultQueryTimeoutDuration;
    141
    142    /**
    143     * The default "catalog" of connections created by this pool.
    144     */
    145    private volatile String defaultCatalog;
    146
    147    /**
    148     * The default "schema" of connections created by this pool.
    149     */
    150    private volatile String defaultSchema;
    151
    152    /**
    153     * The property that controls if the pooled connections cache some state rather than query the database for current
    154     * state to improve performance.
    155     */
    156    private boolean cacheState = true;
    157
    158    /**
    159     * The instance of the JDBC Driver to use.
    160     */
    161    private Driver driver;
    162
    163    /**
    164     * The fully qualified Java class name of the JDBC driver to be used.
    165     */
    166    private String driverClassName;
    167
    168    /**
    169     * The class loader instance to use to load the JDBC driver. If not specified, {@link Class#forName(String)} is used
    170     * to load the JDBC driver. If specified, {@link Class#forName(String, boolean, ClassLoader)} is used.
    171     */
    172    private ClassLoader driverClassLoader;
    173
    174    /**
    175     * True means that borrowObject returns the most recently used ("last in") connection in the pool (if there are idle
    176     * connections available). False means that the pool behaves as a FIFO queue - connections are taken from the idle
    177     * instance pool in the order that they are returned to the pool.
    178     */
    179    private boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO;
    180
    181    /**
    182     * The maximum number of active connections that can be allocated from this pool at the same time, or negative for
    183     * no limit.
    184     */
    185    private int maxTotal = GenericObjectPoolConfig.DEFAULT_MAX_TOTAL;
    186
    187    /**
    188     * The maximum number of connections that can remain idle in the pool, without extra ones being destroyed, or
    189     * negative for no limit. If maxIdle is set too low on heavily loaded systems it is possible you will see
    190     * connections being closed and almost immediately new connections being opened. This is a result of the active
    191     * threads momentarily closing connections faster than they are opening them, causing the number of idle connections
    192     * to rise above maxIdle. The best value for maxIdle for heavily loaded system will vary but the default is a good
    193     * starting point.
    194     */
    195    private int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
    196
    197    /**
    198     * The minimum number of active connections that can remain idle in the pool, without extra ones being created when
    199     * the evictor runs, or 0 to create none. The pool attempts to ensure that minIdle connections are available when
    200     * the idle object evictor runs. The value of this property has no effect unless
    201     * {@link #durationBetweenEvictionRuns} has a positive value.
    202     */
    203    private int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
    204
    205    /**
    206     * The initial number of connections that are created when the pool is started.
    207     */
    208    private int initialSize;
    209
    210    /**
    211     * The maximum Duration that the pool will wait (when there are no available connections) for a
    212     * connection to be returned before throwing an exception, or <= 0 to wait indefinitely.
    213     */
    214    private Duration maxWaitDuration = BaseObjectPoolConfig.DEFAULT_MAX_WAIT;
    215
    216    /**
    217     * Prepared statement pooling for this pool. When this property is set to {@code true} both PreparedStatements
    218     * and CallableStatements are pooled.
    219     */
    220    private boolean poolPreparedStatements;
    221
    222    private boolean clearStatementPoolOnReturn;
    223
    224    /**
    225     * <p>
    226     * The maximum number of open statements that can be allocated from the statement pool at the same time, or negative
    227     * for no limit. Since a connection usually only uses one or two statements at a time, this is mostly used to help
    228     * detect resource leaks.
    229     * </p>
    230     * <p>
    231     * Note: As of version 1.3, CallableStatements (those produced by {@link Connection#prepareCall}) are pooled along
    232     * with PreparedStatements (produced by {@link Connection#prepareStatement}) and
    233     * {@code maxOpenPreparedStatements} limits the total number of prepared or callable statements that may be in
    234     * use at a given time.
    235     * </p>
    236     */
    237    private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL;
    238
    239    /**
    240     * The indication of whether objects will be validated as soon as they have been created by the pool. If the object
    241     * fails to validate, the borrow operation that triggered the creation will fail.
    242     */
    243    private boolean testOnCreate;
    244
    245    /**
    246     * The indication of whether objects will be validated before being borrowed from the pool. If the object fails to
    247     * validate, it will be dropped from the pool, and we will attempt to borrow another.
    248     */
    249    private boolean testOnBorrow = true;
    250
    251    /**
    252     * The indication of whether objects will be validated before being returned to the pool.
    253     */
    254    private boolean testOnReturn;
    255
    256    /**
    257     * The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no idle
    258     * object evictor thread will be run.
    259     */
    260    private Duration durationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS;
    261
    262    /**
    263     * The number of objects to examine during each run of the idle object evictor thread (if any).
    264     */
    265    private int numTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
    266
    267    /**
    268     * The minimum amount of time an object may sit idle in the pool before it is eligible for eviction by the idle
    269     * object evictor (if any).
    270     */
    271    private Duration minEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION;
    272
    273    /**
    274     * The minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the idle
    275     * object evictor, with the extra condition that at least "minIdle" connections remain in the pool. Note that
    276     * {@code minEvictableIdleTimeMillis} takes precedence over this parameter. See
    277     * {@link #getSoftMinEvictableIdleDuration()}.
    278     */
    279    private Duration softMinEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION;
    280
    281    private String evictionPolicyClassName = BaseObjectPoolConfig.DEFAULT_EVICTION_POLICY_CLASS_NAME;
    282
    283    /**
    284     * The indication of whether objects will be validated by the idle object evictor (if any). If an object fails to
    285     * validate, it will be dropped from the pool.
    286     */
    287    private boolean testWhileIdle;
    288
    289    /**
    290     * The connection password to be passed to our JDBC driver to establish a connection.
    291     */
    292    private volatile String password;
    293
    294    /**
    295     * The connection string to be passed to our JDBC driver to establish a connection.
    296     */
    297    private String connectionString;
    298
    299    /**
    300     * The connection user name to be passed to our JDBC driver to establish a connection.
    301     */
    302    private String userName;
    303
    304    /**
    305     * The SQL query that will be used to validate connections from this pool before returning them to the caller. If
    306     * specified, this query <strong>MUST</strong> be an SQL SELECT statement that returns at least one row. If not
    307     * specified, {@link Connection#isValid(int)} will be used to validate connections.
    308     */
    309    private volatile String validationQuery;
    310
    311    /**
    312     * Timeout in seconds before connection validation queries fail.
    313     */
    314    private volatile Duration validationQueryTimeoutDuration = Duration.ofSeconds(-1);
    315
    316    /**
    317     * The fully qualified Java class name of a {@link ConnectionFactory} implementation.
    318     */
    319    private String connectionFactoryClassName;
    320
    321    /**
    322     * These SQL statements run once after a Connection is created.
    323     * <p>
    324     * This property can be used for example to run ALTER SESSION SET NLS_SORT=XCYECH in an Oracle Database only once
    325     * after connection creation.
    326     * </p>
    327     */
    328    private volatile List<String> connectionInitSqls;
    329
    330    /**
    331     * Controls access to the underlying connection.
    332     */
    333    private boolean accessToUnderlyingConnectionAllowed;
    334
    335    private Duration maxConnDuration = Duration.ofMillis(-1);
    336
    337    private boolean logExpiredConnections = true;
    338
    339    private String jmxName;
    340
    341    private boolean registerConnectionMBean = true;
    342
    343    private boolean autoCommitOnReturn = true;
    344
    345    private boolean rollbackOnReturn = true;
    346
    347    private volatile Set<String> disconnectionSqlCodes;
    348
    349    private boolean fastFailValidation;
    350
    351    /**
    352     * The object pool that internally manages our connections.
    353     */
    354    private volatile GenericObjectPool<PoolableConnection> connectionPool;
    355
    356    /**
    357     * The connection properties that will be sent to our JDBC driver when establishing new connections.
    358     * <strong>NOTE</strong> - The "user" and "password" properties will be passed explicitly, so they do not need to be
    359     * included here.
    360     */
    361    private Properties connectionProperties = new Properties();
    362
    363    /**
    364     * The data source we will use to manage connections. This object should be acquired <strong>ONLY</strong> by calls
    365     * to the {@code createDataSource()} method.
    366     */
    367    private volatile DataSource dataSource;
    368
    369    /**
    370     * The PrintWriter to which log messages should be directed.
    371     */
    372    private volatile PrintWriter logWriter = new PrintWriter(
    373            new OutputStreamWriter(System.out, StandardCharsets.UTF_8));
    374
    375    private AbandonedConfig abandonedConfig;
    376
    377    private boolean closed;
    378
    379    /**
    380     * Actual name under which this component has been registered.
    381     */
    382    private ObjectNameWrapper registeredJmxObjectName;
    383
    384    /**
    385     * Adds a custom connection property to the set that will be passed to our JDBC driver. This <strong>MUST</strong>
    386     * be called before the first connection is retrieved (along with all the other configuration property setters).
    387     * Calls to this method after the connection pool has been initialized have no effect.
    388     *
    389     * @param name  Name of the custom connection property
    390     * @param value Value of the custom connection property
    391     */
    392    public void addConnectionProperty(final String name, final String value) {
    393        connectionProperties.put(name, value);
    394    }
    395
    396    /**
    397     * Closes and releases all idle connections that are currently stored in the connection pool associated with this
    398     * data source.
    399     * <p>
    400     * Connections that are checked out to clients when this method is invoked are not affected. When client
    401     * applications subsequently invoke {@link Connection#close()} to return these connections to the pool, the
    402     * underlying JDBC connections are closed.
    403     * </p>
    404     * <p>
    405     * Attempts to acquire connections using {@link #getConnection()} after this method has been invoked result in
    406     * SQLExceptions.  To reopen a datasource that has been closed using this method, use {@link #start()}.
    407     * </p>
    408     * <p>
    409     * This method is idempotent - i.e., closing an already closed BasicDataSource has no effect and does not generate
    410     * exceptions.
    411     * </p>
    412     *
    413     * @throws SQLException if an error occurs closing idle connections
    414     */
    415    @Override
    416    public synchronized void close() throws SQLException {
    417        if (registeredJmxObjectName != null) {
    418            registeredJmxObjectName.unregisterMBean();
    419            registeredJmxObjectName = null;
    420        }
    421        closed = true;
    422        final GenericObjectPool<?> oldPool = connectionPool;
    423        connectionPool = null;
    424        dataSource = null;
    425        try {
    426            if (oldPool != null) {
    427                oldPool.close();
    428            }
    429        } catch (final RuntimeException e) {
    430            throw e;
    431        } catch (final Exception e) {
    432            throw new SQLException(Utils.getMessage("pool.close.fail"), e);
    433        }
    434    }
    435
    436    /**
    437     * Closes the connection pool, silently swallowing any exception that occurs.
    438     */
    439    private void closeConnectionPool() {
    440        final GenericObjectPool<?> oldPool = connectionPool;
    441        connectionPool = null;
    442        Utils.closeQuietly(oldPool);
    443    }
    444
    445    /**
    446     * Creates a JDBC connection factory for this data source. The JDBC driver is loaded using the following algorithm:
    447     * <ol>
    448     * <li>If a Driver instance has been specified via {@link #setDriver(Driver)} use it</li>
    449     * <li>If no Driver instance was specified and {code driverClassName} is specified that class is loaded using the
    450     * {@link ClassLoader} of this class or, if {code driverClassLoader} is set, {code driverClassName} is loaded
    451     * with the specified {@link ClassLoader}.</li>
    452     * <li>If {code driverClassName} is specified and the previous attempt fails, the class is loaded using the
    453     * context class loader of the current thread.</li>
    454     * <li>If a driver still isn't loaded one is loaded via the {@link DriverManager} using the specified {code connectionString}.
    455     * </ol>
    456     * <p>
    457     * This method exists so subclasses can replace the implementation class.
    458     * </p>
    459     *
    460     * @return A new connection factory.
    461     *
    462     * @throws SQLException If the connection factory cannot be created
    463     */
    464    protected ConnectionFactory createConnectionFactory() throws SQLException {
    465        // Load the JDBC driver class
    466        return ConnectionFactoryFactory.createConnectionFactory(this, DriverFactory.createDriver(this));
    467    }
    468
    469    /**
    470     * Creates a connection pool for this datasource. This method only exists so subclasses can replace the
    471     * implementation class.
    472     * <p>
    473     * This implementation configures all pool properties other than timeBetweenEvictionRunsMillis. Setting that
    474     * property is deferred to {@link #startPoolMaintenance()}, since setting timeBetweenEvictionRunsMillis to a
    475     * positive value causes {@link GenericObjectPool}'s eviction timer to be started.
    476     * </p>
    477     *
    478     * @param factory The factory to use to create new connections for this pool.
    479     */
    480    protected void createConnectionPool(final PoolableConnectionFactory factory) {
    481        // Create an object pool to contain our active connections
    482        final GenericObjectPoolConfig<PoolableConnection> config = new GenericObjectPoolConfig<>();
    483        updateJmxName(config);
    484        // Disable JMX on the underlying pool if the DS is not registered:
    485        config.setJmxEnabled(registeredJmxObjectName != null);
    486        // Set up usage tracking if enabled
    487        if (getAbandonedUsageTracking() && abandonedConfig != null) {
    488            abandonedConfig.setUseUsageTracking(true);
    489        }
    490        final GenericObjectPool<PoolableConnection> gop = createObjectPool(factory, config, abandonedConfig);
    491        gop.setMaxTotal(maxTotal);
    492        gop.setMaxIdle(maxIdle);
    493        gop.setMinIdle(minIdle);
    494        gop.setMaxWait(maxWaitDuration);
    495        gop.setTestOnCreate(testOnCreate);
    496        gop.setTestOnBorrow(testOnBorrow);
    497        gop.setTestOnReturn(testOnReturn);
    498        gop.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
    499        gop.setMinEvictableIdleDuration(minEvictableIdleDuration);
    500        gop.setSoftMinEvictableIdleDuration(softMinEvictableIdleDuration);
    501        gop.setTestWhileIdle(testWhileIdle);
    502        gop.setLifo(lifo);
    503        gop.setSwallowedExceptionListener(new SwallowedExceptionLogger(log, logExpiredConnections));
    504        gop.setEvictionPolicyClassName(evictionPolicyClassName);
    505        factory.setPool(gop);
    506        connectionPool = gop;
    507    }
    508
    509    /**
    510     * Creates (if necessary) and return the internal data source we are using to manage our connections.
    511     *
    512     * @return The current internal DataSource or a newly created instance if it has not yet been created.
    513     * @throws SQLException if the object pool cannot be created.
    514     */
    515    protected synchronized DataSource createDataSource() throws SQLException {
    516        if (closed) {
    517            throw new SQLException("Data source is closed");
    518        }
    519
    520        // Return the pool if we have already created it
    521        // This is double-checked locking. This is safe since dataSource is
    522        // volatile and the code is targeted at Java 5 onwards.
    523        if (dataSource != null) {
    524            return dataSource;
    525        }
    526        synchronized (this) {
    527            if (dataSource != null) {
    528                return dataSource;
    529            }
    530            jmxRegister();
    531
    532            // create factory which returns raw physical connections
    533            final ConnectionFactory driverConnectionFactory = createConnectionFactory();
    534
    535            // Set up the poolable connection factory
    536            final PoolableConnectionFactory poolableConnectionFactory;
    537            try {
    538                poolableConnectionFactory = createPoolableConnectionFactory(driverConnectionFactory);
    539                poolableConnectionFactory.setPoolStatements(poolPreparedStatements);
    540                poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements);
    541                // create a pool for our connections
    542                createConnectionPool(poolableConnectionFactory);
    543                final DataSource newDataSource = createDataSourceInstance();
    544                newDataSource.setLogWriter(logWriter);
    545                connectionPool.addObjects(initialSize);
    546                // If timeBetweenEvictionRunsMillis > 0, start the pool's evictor
    547                // task
    548                startPoolMaintenance();
    549                dataSource = newDataSource;
    550            } catch (final SQLException | RuntimeException se) {
    551                closeConnectionPool();
    552                throw se;
    553            } catch (final Exception ex) {
    554                closeConnectionPool();
    555                throw new SQLException("Error creating connection factory", ex);
    556            }
    557
    558            return dataSource;
    559        }
    560    }
    561
    562    /**
    563     * Creates the actual data source instance. This method only exists so that subclasses can replace the
    564     * implementation class.
    565     *
    566     * @throws SQLException if unable to create a datasource instance
    567     *
    568     * @return A new DataSource instance
    569     */
    570    protected DataSource createDataSourceInstance() throws SQLException {
    571        final PoolingDataSource<PoolableConnection> pds = new PoolingDataSource<>(connectionPool);
    572        pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
    573        return pds;
    574    }
    575
    576    /**
    577     * Creates an object pool used to provide pooling support for {@link Connection JDBC connections}.
    578     *
    579     * @param factory         the object factory
    580     * @param poolConfig      the object pool configuration
    581     * @param abandonedConfig the abandoned objects configuration
    582     * @return a non-null instance
    583     */
    584    protected GenericObjectPool<PoolableConnection> createObjectPool(final PoolableConnectionFactory factory,
    585            final GenericObjectPoolConfig<PoolableConnection> poolConfig, final AbandonedConfig abandonedConfig) {
    586        final GenericObjectPool<PoolableConnection> gop;
    587        if (abandonedConfig != null && (abandonedConfig.getRemoveAbandonedOnBorrow()
    588                || abandonedConfig.getRemoveAbandonedOnMaintenance())) {
    589            gop = new GenericObjectPool<>(factory, poolConfig, abandonedConfig);
    590        } else {
    591            gop = new GenericObjectPool<>(factory, poolConfig);
    592        }
    593        return gop;
    594    }
    595
    596    /**
    597     * Creates the PoolableConnectionFactory and attaches it to the connection pool. This method only exists so
    598     * subclasses can replace the default implementation.
    599     *
    600     * @param driverConnectionFactory JDBC connection factory
    601     * @throws SQLException if an error occurs creating the PoolableConnectionFactory
    602     *
    603     * @return A new PoolableConnectionFactory configured with the current configuration of this BasicDataSource
    604     */
    605    protected PoolableConnectionFactory createPoolableConnectionFactory(final ConnectionFactory driverConnectionFactory)
    606            throws SQLException {
    607        PoolableConnectionFactory connectionFactory = null;
    608        try {
    609            if (registerConnectionMBean) {
    610                connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, ObjectNameWrapper.unwrap(registeredJmxObjectName));
    611            } else {
    612                connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, null);
    613            }
    614            connectionFactory.setValidationQuery(validationQuery);
    615            connectionFactory.setValidationQueryTimeout(validationQueryTimeoutDuration);
    616            connectionFactory.setConnectionInitSql(connectionInitSqls);
    617            connectionFactory.setDefaultReadOnly(defaultReadOnly);
    618            connectionFactory.setDefaultAutoCommit(defaultAutoCommit);
    619            connectionFactory.setDefaultTransactionIsolation(defaultTransactionIsolation);
    620            connectionFactory.setDefaultCatalog(defaultCatalog);
    621            connectionFactory.setDefaultSchema(defaultSchema);
    622            connectionFactory.setCacheState(cacheState);
    623            connectionFactory.setPoolStatements(poolPreparedStatements);
    624            connectionFactory.setClearStatementPoolOnReturn(clearStatementPoolOnReturn);
    625            connectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements);
    626            connectionFactory.setMaxConn(maxConnDuration);
    627            connectionFactory.setRollbackOnReturn(getRollbackOnReturn());
    628            connectionFactory.setAutoCommitOnReturn(getAutoCommitOnReturn());
    629            connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeoutDuration());
    630            connectionFactory.setFastFailValidation(fastFailValidation);
    631            connectionFactory.setDisconnectionSqlCodes(disconnectionSqlCodes);
    632            validateConnectionFactory(connectionFactory);
    633        } catch (final RuntimeException e) {
    634            throw e;
    635        } catch (final Exception e) {
    636            throw new SQLException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e);
    637        }
    638        return connectionFactory;
    639    }
    640
    641    /**
    642     * Manually evicts idle connections
    643     *
    644     * @throws Exception when there is a problem evicting idle objects.
    645     */
    646    public void evict() throws Exception {
    647        if (connectionPool != null) {
    648            connectionPool.evict();
    649        }
    650    }
    651
    652    /**
    653     * Gets the print writer used by this configuration to log information on abandoned objects.
    654     *
    655     * @return The print writer used by this configuration to log information on abandoned objects.
    656     */
    657    public PrintWriter getAbandonedLogWriter() {
    658        return abandonedConfig == null ? null : abandonedConfig.getLogWriter();
    659    }
    660
    661    /**
    662     * If the connection pool implements {@link org.apache.commons.pool2.UsageTracking UsageTracking}, should the
    663     * connection pool record a stack trace every time a method is called on a pooled connection and retain the most
    664     * recent stack trace to aid debugging of abandoned connections?
    665     *
    666     * @return {@code true} if usage tracking is enabled
    667     */
    668    @Override
    669    public boolean getAbandonedUsageTracking() {
    670        return abandonedConfig != null && abandonedConfig.getUseUsageTracking();
    671    }
    672
    673    /**
    674     * Gets the value of the flag that controls whether or not connections being returned to the pool will be checked
    675     * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
    676     * setting is {@code false} when the connection is returned. It is {@code true} by default.
    677     *
    678     * @return Whether or not connections being returned to the pool will be checked and configured with auto-commit.
    679     */
    680    public boolean getAutoCommitOnReturn() {
    681        return autoCommitOnReturn;
    682    }
    683
    684    /**
    685     * Gets the state caching flag.
    686     *
    687     * @return the state caching flag
    688     */
    689    @Override
    690    public boolean getCacheState() {
    691        return cacheState;
    692    }
    693
    694    /**
    695     * Creates (if necessary) and return a connection to the database.
    696     *
    697     * @throws SQLException if a database access error occurs
    698     * @return a database connection
    699     */
    700    @Override
    701    public Connection getConnection() throws SQLException {
    702        if (Utils.isSecurityEnabled()) {
    703            final PrivilegedExceptionAction<Connection> action = () -> createDataSource().getConnection();
    704            try {
    705                return AccessController.doPrivileged(action);
    706            } catch (final PrivilegedActionException e) {
    707                final Throwable cause = e.getCause();
    708                if (cause instanceof SQLException) {
    709                    throw (SQLException) cause;
    710                }
    711                throw new SQLException(e);
    712            }
    713        }
    714        return createDataSource().getConnection();
    715    }
    716
    717    /**
    718     * <strong>BasicDataSource does NOT support this method.</strong>
    719     *
    720     * @param user Database user on whose behalf the Connection is being made
    721     * @param pass The database user's password
    722     *
    723     * @throws UnsupportedOperationException always thrown.
    724     * @throws SQLException                  if a database access error occurs
    725     * @return nothing - always throws UnsupportedOperationException
    726     */
    727    @Override
    728    public Connection getConnection(final String user, final String pass) throws SQLException {
    729        // This method isn't supported by the PoolingDataSource returned by the
    730        // createDataSource
    731        throw new UnsupportedOperationException("Not supported by BasicDataSource");
    732    }
    733
    734    /**
    735     * Gets the ConnectionFactoryClassName that has been configured for use by this pool.
    736     * <p>
    737     * Note: This getter only returns the last value set by a call to {@link #setConnectionFactoryClassName(String)}.
    738     * </p>
    739     *
    740     * @return the ConnectionFactoryClassName that has been configured for use by this pool.
    741     * @since 2.7.0
    742     */
    743    public String getConnectionFactoryClassName() {
    744        return this.connectionFactoryClassName;
    745    }
    746
    747    /**
    748     * Gets the list of SQL statements executed when a physical connection is first created. Returns an empty list if
    749     * there are no initialization statements configured.
    750     *
    751     * @return initialization SQL statements
    752     */
    753    public List<String> getConnectionInitSqls() {
    754        final List<String> result = connectionInitSqls;
    755        return result == null ? Collections.emptyList() : result;
    756    }
    757
    758    /**
    759     * Provides the same data as {@link #getConnectionInitSqls()} but in an array so it is accessible via JMX.
    760     */
    761    @Override
    762    public String[] getConnectionInitSqlsAsArray() {
    763        return getConnectionInitSqls().toArray(Utils.EMPTY_STRING_ARRAY);
    764    }
    765
    766    /**
    767     * Gets the underlying connection pool.
    768     *
    769     * @return the underlying connection pool.
    770     * @since 2.10.0
    771     */
    772    public GenericObjectPool<PoolableConnection> getConnectionPool() {
    773        return connectionPool;
    774    }
    775
    776    Properties getConnectionProperties() {
    777        return connectionProperties;
    778    }
    779
    780    /**
    781     * Gets the default auto-commit property.
    782     *
    783     * @return true if default auto-commit is enabled
    784     */
    785    @Override
    786    public Boolean getDefaultAutoCommit() {
    787        return defaultAutoCommit;
    788    }
    789
    790    /**
    791     * Gets the default catalog.
    792     *
    793     * @return the default catalog
    794     */
    795    @Override
    796    public String getDefaultCatalog() {
    797        return this.defaultCatalog;
    798    }
    799
    800    /**
    801     * Gets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
    802     * connection. {@code null} means that the driver default will be used.
    803     *
    804     * @return The default query timeout in seconds.
    805     * @deprecated Use {@link #getDefaultQueryTimeoutDuration()}.
    806     */
    807    @Deprecated
    808    public Integer getDefaultQueryTimeout() {
    809        return defaultQueryTimeoutDuration == null ? null : (int) defaultQueryTimeoutDuration.getSeconds();
    810    }
    811
    812    /**
    813     * Gets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
    814     * connection. {@code null} means that the driver default will be used.
    815     *
    816     * @return The default query timeout Duration.
    817     * @since 2.10.0
    818     */
    819    public Duration getDefaultQueryTimeoutDuration() {
    820        return defaultQueryTimeoutDuration;
    821    }
    822
    823    /**
    824     * Gets the default readOnly property.
    825     *
    826     * @return true if connections are readOnly by default
    827     */
    828    @Override
    829    public Boolean getDefaultReadOnly() {
    830        return defaultReadOnly;
    831    }
    832
    833    /**
    834     * Gets the default schema.
    835     *
    836     * @return the default schema.
    837     * @since 2.5.0
    838     */
    839    @Override
    840    public String getDefaultSchema() {
    841        return this.defaultSchema;
    842    }
    843
    844    /**
    845     * Gets the default transaction isolation state of returned connections.
    846     *
    847     * @return the default value for transaction isolation state
    848     * @see Connection#getTransactionIsolation
    849     */
    850    @Override
    851    public int getDefaultTransactionIsolation() {
    852        return this.defaultTransactionIsolation;
    853    }
    854
    855    /**
    856     * Gets the set of SQL_STATE codes considered to signal fatal conditions.
    857     *
    858     * @return fatal disconnection state codes
    859     * @see #setDisconnectionSqlCodes(Collection)
    860     * @since 2.1
    861     */
    862    public Set<String> getDisconnectionSqlCodes() {
    863        final Set<String> result = disconnectionSqlCodes;
    864        return result == null ? Collections.emptySet() : result;
    865    }
    866
    867    /**
    868     * Provides the same data as {@link #getDisconnectionSqlCodes} but in an array so it is accessible via JMX.
    869     *
    870     * @since 2.1
    871     */
    872    @Override
    873    public String[] getDisconnectionSqlCodesAsArray() {
    874        return getDisconnectionSqlCodes().toArray(Utils.EMPTY_STRING_ARRAY);
    875    }
    876
    877    /**
    878     * Gets the JDBC Driver that has been configured for use by this pool.
    879     * <p>
    880     * Note: This getter only returns the last value set by a call to {@link #setDriver(Driver)}. It does not return any
    881     * driver instance that may have been created from the value set via {@link #setDriverClassName(String)}.
    882     * </p>
    883     *
    884     * @return the JDBC Driver that has been configured for use by this pool
    885     */
    886    public synchronized Driver getDriver() {
    887        return driver;
    888    }
    889
    890    /**
    891     * Gets the class loader specified for loading the JDBC driver. Returns {@code null} if no class loader has
    892     * been explicitly specified.
    893     * <p>
    894     * Note: This getter only returns the last value set by a call to {@link #setDriverClassLoader(ClassLoader)}. It
    895     * does not return the class loader of any driver that may have been set via {@link #setDriver(Driver)}.
    896     * </p>
    897     *
    898     * @return The class loader specified for loading the JDBC driver.
    899     */
    900    public synchronized ClassLoader getDriverClassLoader() {
    901        return this.driverClassLoader;
    902    }
    903
    904    /**
    905     * Gets the JDBC driver class name.
    906     * <p>
    907     * Note: This getter only returns the last value set by a call to {@link #setDriverClassName(String)}. It does not
    908     * return the class name of any driver that may have been set via {@link #setDriver(Driver)}.
    909     * </p>
    910     *
    911     * @return the JDBC driver class name
    912     */
    913    @Override
    914    public synchronized String getDriverClassName() {
    915        return this.driverClassName;
    916    }
    917
    918    /**
    919     * Gets the value of the {code durationBetweenEvictionRuns} property.
    920     *
    921     * @return the time (in milliseconds) between evictor runs
    922     * @see #setDurationBetweenEvictionRuns(Duration)
    923     * @since 2.10.0
    924     */
    925    public synchronized Duration getDurationBetweenEvictionRuns() {
    926        return this.durationBetweenEvictionRuns;
    927    }
    928
    929    /**
    930     * Gets the value of the flag that controls whether or not connections being returned to the pool will be checked
    931     * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
    932     * setting is {@code false} when the connection is returned. It is {@code true} by default.
    933     *
    934     * @return Whether or not connections being returned to the pool will be checked and configured with auto-commit.
    935     * @deprecated Use {@link #getAutoCommitOnReturn()}.
    936     */
    937    @Deprecated
    938    public boolean getEnableAutoCommitOnReturn() {
    939        return autoCommitOnReturn;
    940    }
    941
    942    /**
    943     * Gets the EvictionPolicy implementation in use with this connection pool.
    944     *
    945     * @return The EvictionPolicy implementation in use with this connection pool.
    946     */
    947    public synchronized String getEvictionPolicyClassName() {
    948        return evictionPolicyClassName;
    949    }
    950
    951    /**
    952     * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with
    953     * SQL_STATE indicating fatal disconnection errors.
    954     *
    955     * @return true if connections created by this datasource will fast fail validation.
    956     * @see #setDisconnectionSqlCodes(Collection)
    957     * @since 2.1
    958     */
    959    @Override
    960    public boolean getFastFailValidation() {
    961        return fastFailValidation;
    962    }
    963
    964    /**
    965     * Gets the initial size of the connection pool.
    966     *
    967     * @return the number of connections created when the pool is initialized
    968     */
    969    @Override
    970    public synchronized int getInitialSize() {
    971        return this.initialSize;
    972    }
    973
    974    /**
    975     * Gets the JMX name that has been requested for this DataSource. If the requested name is not valid, an
    976     * alternative may be chosen.
    977     *
    978     * @return The JMX name that has been requested for this DataSource.
    979     */
    980    public String getJmxName() {
    981        return jmxName;
    982    }
    983
    984    /**
    985     * Gets the LIFO property.
    986     *
    987     * @return true if connection pool behaves as a LIFO queue.
    988     */
    989    @Override
    990    public synchronized boolean getLifo() {
    991        return this.lifo;
    992    }
    993
    994    /**
    995     * Flag to log stack traces for application code which abandoned a Statement or Connection.
    996     * <p>
    997     * Defaults to false.
    998     * </p>
    999     * <p>
    1000     * Logging of abandoned Statements and Connections adds overhead for every Connection open or new Statement because
    1001     * a stack trace has to be generated.
    1002     * </p>
    1003     */
    1004    @Override
    1005    public boolean getLogAbandoned() {
    1006        return abandonedConfig != null && abandonedConfig.getLogAbandoned();
    1007    }
    1008
    1009    /**
    1010     * When {@link #getMaxConnDuration()} is set to limit connection lifetime, this property determines whether or
    1011     * not log messages are generated when the pool closes connections due to maximum lifetime exceeded.
    1012     *
    1013     * @since 2.1
    1014     */
    1015    @Override
    1016    public boolean getLogExpiredConnections() {
    1017        return logExpiredConnections;
    1018    }
    1019
    1020    /**
    1021     * <strong>BasicDataSource does NOT support this method.</strong>
    1022     *
    1023     * <p>
    1024     * Gets the login timeout (in seconds) for connecting to the database.
    1025     * </p>
    1026     * <p>
    1027     * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool.
    1028     * </p>
    1029     *
    1030     * @throws SQLException                  if a database access error occurs
    1031     * @throws UnsupportedOperationException If the DataSource implementation does not support the login timeout
    1032     *                                       feature.
    1033     * @return login timeout in seconds
    1034     */
    1035    @Override
    1036    public int getLoginTimeout() throws SQLException {
    1037        // This method isn't supported by the PoolingDataSource returned by the createDataSource
    1038        throw new UnsupportedOperationException("Not supported by BasicDataSource");
    1039    }
    1040
    1041    /**
    1042     * Gets the log writer being used by this data source.
    1043     * <p>
    1044     * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool.
    1045     * </p>
    1046     *
    1047     * @throws SQLException if a database access error occurs
    1048     * @return log writer in use
    1049     */
    1050    @Override
    1051    public PrintWriter getLogWriter() throws SQLException {
    1052        return createDataSource().getLogWriter();
    1053    }
    1054
    1055    /**
    1056     * Gets the maximum permitted duration of a connection. A value of zero or less indicates an
    1057     * infinite lifetime.
    1058     * @return the maximum permitted duration of a connection.
    1059     * @since 2.10.0
    1060     */
    1061    public Duration getMaxConnDuration() {
    1062        return maxConnDuration;
    1063    }
    1064
    1065    /**
    1066     * Gets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an
    1067     * infinite lifetime.
    1068     * @deprecated Use {@link #getMaxConnDuration()}.
    1069     */
    1070    @Override
    1071    @Deprecated
    1072    public long getMaxConnLifetimeMillis() {
    1073        return maxConnDuration.toMillis();
    1074    }
    1075
    1076    /**
    1077     * Gets the maximum number of connections that can remain idle in the pool. Excess idle connections are destroyed
    1078     * on return to the pool.
    1079     * <p>
    1080     * A negative value indicates that there is no limit
    1081     * </p>
    1082     *
    1083     * @return the maximum number of idle connections
    1084     */
    1085    @Override
    1086    public synchronized int getMaxIdle() {
    1087        return this.maxIdle;
    1088    }
    1089
    1090    /**
    1091     * Gets the value of the {@code maxOpenPreparedStatements} property.
    1092     *
    1093     * @return the maximum number of open statements
    1094     */
    1095    @Override
    1096    public synchronized int getMaxOpenPreparedStatements() {
    1097        return this.maxOpenPreparedStatements;
    1098    }
    1099
    1100    /**
    1101     * Gets the maximum number of active connections that can be allocated at the same time.
    1102     * <p>
    1103     * A negative number means that there is no limit.
    1104     * </p>
    1105     *
    1106     * @return the maximum number of active connections
    1107     */
    1108    @Override
    1109    public synchronized int getMaxTotal() {
    1110        return this.maxTotal;
    1111    }
    1112
    1113    /**
    1114     * Gets the maximum Duration that the pool will wait for a connection to be returned before throwing an exception. A
    1115     * value less than or equal to zero means the pool is set to wait indefinitely.
    1116     *
    1117     * @return the maxWaitDuration property value.
    1118     * @since 2.10.0
    1119     */
    1120    public synchronized Duration getMaxWaitDuration() {
    1121        return this.maxWaitDuration;
    1122    }
    1123
    1124    /**
    1125     * Gets the maximum number of milliseconds that the pool will wait for a connection to be returned before
    1126     * throwing an exception. A value less than or equal to zero means the pool is set to wait indefinitely.
    1127     *
    1128     * @return the maxWaitMillis property value.
    1129     * @deprecated Use {@link #getMaxWaitDuration()}.
    1130     */
    1131    @Deprecated
    1132    @Override
    1133    public synchronized long getMaxWaitMillis() {
    1134        return this.maxWaitDuration.toMillis();
    1135    }
    1136
    1137    /**
    1138     * Gets the {code minEvictableIdleDuration} property.
    1139     *
    1140     * @return the value of the {code minEvictableIdleDuration} property
    1141     * @see #setMinEvictableIdle(Duration)
    1142     * @since 2.10.0
    1143     */
    1144    public synchronized Duration getMinEvictableIdleDuration() {
    1145        return this.minEvictableIdleDuration;
    1146    }
    1147
    1148    /**
    1149     * Gets the {code minEvictableIdleDuration} property.
    1150     *
    1151     * @return the value of the {code minEvictableIdleDuration} property
    1152     * @see #setMinEvictableIdle(Duration)
    1153     * @deprecated Use {@link #getMinEvictableIdleDuration()}.
    1154     */
    1155    @Deprecated
    1156    @Override
    1157    public synchronized long getMinEvictableIdleTimeMillis() {
    1158        return this.minEvictableIdleDuration.toMillis();
    1159    }
    1160
    1161    /**
    1162     * Gets the minimum number of idle connections in the pool. The pool attempts to ensure that minIdle connections
    1163     * are available when the idle object evictor runs. The value of this property has no effect unless
    1164     * {code durationBetweenEvictionRuns} has a positive value.
    1165     *
    1166     * @return the minimum number of idle connections
    1167     * @see GenericObjectPool#getMinIdle()
    1168     */
    1169    @Override
    1170    public synchronized int getMinIdle() {
    1171        return this.minIdle;
    1172    }
    1173
    1174    /**
    1175     * [Read Only] The current number of active connections that have been allocated from this data source.
    1176     *
    1177     * @return the current number of active connections
    1178     */
    1179    @Override
    1180    public int getNumActive() {
    1181        // Copy reference to avoid NPE if close happens after null check
    1182        final GenericObjectPool<PoolableConnection> pool = connectionPool;
    1183        return pool == null ? 0 : pool.getNumActive();
    1184    }
    1185
    1186    /**
    1187     * [Read Only] The current number of idle connections that are waiting to be allocated from this data source.
    1188     *
    1189     * @return the current number of idle connections
    1190     */
    1191    @Override
    1192    public int getNumIdle() {
    1193        // Copy reference to avoid NPE if close happens after null check
    1194        final GenericObjectPool<PoolableConnection> pool = connectionPool;
    1195        return pool == null ? 0 : pool.getNumIdle();
    1196    }
    1197
    1198    /**
    1199     * Gets the value of the {code numTestsPerEvictionRun} property.
    1200     *
    1201     * @return the number of objects to examine during idle object evictor runs
    1202     * @see #setNumTestsPerEvictionRun(int)
    1203     */
    1204    @Override
    1205    public synchronized int getNumTestsPerEvictionRun() {
    1206        return this.numTestsPerEvictionRun;
    1207    }
    1208
    1209    @Override
    1210    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
    1211        throw new SQLFeatureNotSupportedException();
    1212    }
    1213
    1214    /**
    1215     * Gets the password passed to the JDBC driver to establish connections.
    1216     *
    1217     * @return the connection password
    1218     * @deprecated Exposing passwords via JMX is an Information Exposure issue.
    1219     */
    1220    @Deprecated
    1221    @Override
    1222    public String getPassword() {
    1223        return this.password;
    1224    }
    1225
    1226    /**
    1227     * Gets the registered JMX ObjectName.
    1228     *
    1229     * @return the registered JMX ObjectName.
    1230     */
    1231    protected ObjectName getRegisteredJmxName() {
    1232        return ObjectNameWrapper.unwrap(registeredJmxObjectName);
    1233    }
    1234
    1235    /**
    1236     * Flag to remove abandoned connections if they exceed the removeAbandonedTimeout when borrowObject is invoked.
    1237     * <p>
    1238     * The default value is false.
    1239     * </p>
    1240     * <p>
    1241     * If set to true a connection is considered abandoned and eligible for removal if it has not been used for more
    1242     * than {@link #getRemoveAbandonedTimeoutDuration() removeAbandonedTimeout} seconds.
    1243     * </p>
    1244     * <p>
    1245     * Abandoned connections are identified and removed when {@link #getConnection()} is invoked and all of the
    1246     * following conditions hold:
    1247     * </p>
    1248     * <ul>
    1249     * <li>{@link #getRemoveAbandonedOnBorrow()}</li>
    1250     * <li>{@link #getNumActive()} &gt; {@link #getMaxTotal()} - 3</li>
    1251     * <li>{@link #getNumIdle()} &lt; 2</li>
    1252     * </ul>
    1253     *
    1254     * @see #getRemoveAbandonedTimeoutDuration()
    1255     */
    1256    @Override
    1257    public boolean getRemoveAbandonedOnBorrow() {
    1258        return abandonedConfig != null && abandonedConfig.getRemoveAbandonedOnBorrow();
    1259    }
    1260
    1261    /**
    1262     * Flag to remove abandoned connections if they exceed the removeAbandonedTimeout during pool maintenance.
    1263     * <p>
    1264     * The default value is false.
    1265     * </p>
    1266     * <p>
    1267     * If set to true a connection is considered abandoned and eligible for removal if it has not been used for more
    1268     * than {@link #getRemoveAbandonedTimeoutDuration() removeAbandonedTimeout} seconds.
    1269     * </p>
    1270     *
    1271     * @see #getRemoveAbandonedTimeoutDuration()
    1272     */
    1273    @Override
    1274    public boolean getRemoveAbandonedOnMaintenance() {
    1275        return abandonedConfig != null && abandonedConfig.getRemoveAbandonedOnMaintenance();
    1276    }
    1277
    1278    /**
    1279     * Gets the timeout in seconds before an abandoned connection can be removed.
    1280     * <p>
    1281     * Creating a Statement, PreparedStatement or CallableStatement or using one of these to execute a query (using one
    1282     * of the execute methods) resets the lastUsed property of the parent connection.
    1283     * </p>
    1284     * <p>
    1285     * Abandoned connection cleanup happens when:
    1286     * </p>
    1287     * <ul>
    1288     * <li>{@link #getRemoveAbandonedOnBorrow()} or {@link #getRemoveAbandonedOnMaintenance()} = true</li>
    1289     * <li>{@link #getNumIdle() numIdle} &lt; 2</li>
    1290     * <li>{@link #getNumActive() numActive} &gt; {@link #getMaxTotal() maxTotal} - 3</li>
    1291     * </ul>
    1292     * <p>
    1293     * The default value is 300 seconds.
    1294     * </p>
    1295     * @deprecated Use {@link #getRemoveAbandonedTimeoutDuration()}.
    1296     */
    1297    @Deprecated
    1298    @Override
    1299    public int getRemoveAbandonedTimeout() {
    1300        return (int) getRemoveAbandonedTimeoutDuration().getSeconds();
    1301    }
    1302
    1303    /**
    1304     * Gets the timeout before an abandoned connection can be removed.
    1305     * <p>
    1306     * Creating a Statement, PreparedStatement or CallableStatement or using one of these to execute a query (using one
    1307     * of the execute methods) resets the lastUsed property of the parent connection.
    1308     * </p>
    1309     * <p>
    1310     * Abandoned connection cleanup happens when:
    1311     * </p>
    1312     * <ul>
    1313     * <li>{@link #getRemoveAbandonedOnBorrow()} or {@link #getRemoveAbandonedOnMaintenance()} = true</li>
    1314     * <li>{@link #getNumIdle() numIdle} &lt; 2</li>
    1315     * <li>{@link #getNumActive() numActive} &gt; {@link #getMaxTotal() maxTotal} - 3</li>
    1316     * </ul>
    1317     * <p>
    1318     * The default value is 300 seconds.
    1319     * </p>
    1320     * @return Timeout before an abandoned connection can be removed.
    1321     * @since 2.10.0
    1322     */
    1323    public Duration getRemoveAbandonedTimeoutDuration() {
    1324        return abandonedConfig == null ? Duration.ofSeconds(300) : abandonedConfig.getRemoveAbandonedTimeoutDuration();
    1325    }
    1326
    1327    /**
    1328     * Gets the current value of the flag that controls whether a connection will be rolled back when it is returned to
    1329     * the pool if auto commit is not enabled and the connection is not read only.
    1330     *
    1331     * @return whether a connection will be rolled back when it is returned to the pool.
    1332     */
    1333    public boolean getRollbackOnReturn() {
    1334        return rollbackOnReturn;
    1335    }
    1336
    1337    /**
    1338     * Gets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by
    1339     * the idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool.
    1340     * <p>
    1341     * When {@link #getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} is set to a positive value,
    1342     * minEvictableIdleTimeMillis is examined first by the idle connection evictor - i.e. when idle connections are
    1343     * visited by the evictor, idle time is first compared against {@code minEvictableIdleTimeMillis} (without
    1344     * considering the number of idle connections in the pool) and then against {@code softMinEvictableIdleTimeMillis},
    1345     * including the {@code minIdle}, constraint.
    1346     * </p>
    1347     *
    1348     * @return minimum amount of time a connection may sit idle in the pool before it is eligible for eviction, assuming
    1349     *         there are minIdle idle connections in the pool
    1350     * @since 2.10.0
    1351     */
    1352    public synchronized Duration getSoftMinEvictableIdleDuration() {
    1353        return softMinEvictableIdleDuration;
    1354    }
    1355
    1356    /**
    1357     * Gets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by
    1358     * the idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool.
    1359     * <p>
    1360     * When {@link #getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} is set to a positive value,
    1361     * minEvictableIdleTimeMillis is examined first by the idle connection evictor - i.e. when idle connections are
    1362     * visited by the evictor, idle time is first compared against {@code minEvictableIdleTimeMillis} (without
    1363     * considering the number of idle connections in the pool) and then against {@code softMinEvictableIdleTimeMillis},
    1364     * including the {@code minIdle}, constraint.
    1365     * </p>
    1366     *
    1367     * @return minimum amount of time a connection may sit idle in the pool before it is eligible for eviction, assuming
    1368     *         there are minIdle idle connections in the pool
    1369     * @deprecated Use {@link #getSoftMinEvictableIdleDuration()}.
    1370     */
    1371    @Deprecated
    1372    @Override
    1373    public synchronized long getSoftMinEvictableIdleTimeMillis() {
    1374        return softMinEvictableIdleDuration.toMillis();
    1375    }
    1376
    1377    /**
    1378     * Gets the {code testOnBorrow} property.
    1379     *
    1380     * @return true if objects are validated before being borrowed from the pool
    1381     *
    1382     * @see #setTestOnBorrow(boolean)
    1383     */
    1384    @Override
    1385    public synchronized boolean getTestOnBorrow() {
    1386        return this.testOnBorrow;
    1387    }
    1388
    1389    /**
    1390     * Gets the {code testOnCreate} property.
    1391     *
    1392     * @return true if objects are validated immediately after they are created by the pool
    1393     * @see #setTestOnCreate(boolean)
    1394     */
    1395    @Override
    1396    public synchronized boolean getTestOnCreate() {
    1397        return this.testOnCreate;
    1398    }
    1399
    1400    /**
    1401     * Gets the value of the {code testOnReturn} property.
    1402     *
    1403     * @return true if objects are validated before being returned to the pool
    1404     * @see #setTestOnReturn(boolean)
    1405     */
    1406    public synchronized boolean getTestOnReturn() {
    1407        return this.testOnReturn;
    1408    }
    1409
    1410    /**
    1411     * Gets the value of the {code testWhileIdle} property.
    1412     *
    1413     * @return true if objects examined by the idle object evictor are validated
    1414     * @see #setTestWhileIdle(boolean)
    1415     */
    1416    @Override
    1417    public synchronized boolean getTestWhileIdle() {
    1418        return this.testWhileIdle;
    1419    }
    1420
    1421    /**
    1422     * Gets the value of the {code durationBetweenEvictionRuns} property.
    1423     *
    1424     * @return the time (in milliseconds) between evictor runs
    1425     * @see #setDurationBetweenEvictionRuns(Duration)
    1426     * @deprecated Use {@link #getDurationBetweenEvictionRuns()}.
    1427     */
    1428    @Deprecated
    1429    @Override
    1430    public synchronized long getTimeBetweenEvictionRunsMillis() {
    1431        return this.durationBetweenEvictionRuns.toMillis();
    1432    }
    1433
    1434    /**
    1435     * Gets the JDBC connection {code connectionString} property.
    1436     *
    1437     * @return the {code connectionString} passed to the JDBC driver to establish connections
    1438     */
    1439    @Override
    1440    public synchronized String getUrl() {
    1441        return this.connectionString;
    1442    }
    1443
    1444    /**
    1445     * Gets the JDBC connection {code userName} property.
    1446     *
    1447     * @return the {code userName} passed to the JDBC driver to establish connections
    1448     * @deprecated
    1449     */
    1450    @Deprecated
    1451    @Override
    1452    public String getUsername() {
    1453        return this.userName;
    1454    }
    1455
    1456    /**
    1457     * Gets the validation query used to validate connections before returning them.
    1458     *
    1459     * @return the SQL validation query
    1460     * @see #setValidationQuery(String)
    1461     */
    1462    @Override
    1463    public String getValidationQuery() {
    1464        return this.validationQuery;
    1465    }
    1466
    1467    /**
    1468     * Gets the validation query timeout.
    1469     *
    1470     * @return the timeout in seconds before connection validation queries fail.
    1471     * @deprecated Use {@link #getValidationQueryTimeoutDuration()}.
    1472     */
    1473    @Deprecated
    1474    @Override
    1475    public int getValidationQueryTimeout() {
    1476        return (int) validationQueryTimeoutDuration.getSeconds();
    1477    }
    1478
    1479    /**
    1480     * Gets the validation query timeout.
    1481     *
    1482     * @return the timeout in seconds before connection validation queries fail.
    1483     */
    1484    public Duration getValidationQueryTimeoutDuration() {
    1485        return validationQueryTimeoutDuration;
    1486    }
    1487
    1488    /**
    1489     * Manually invalidates a connection, effectively requesting the pool to try to close it, remove it from the pool
    1490     * and reclaim pool capacity.
    1491     *
    1492     * @param connection The Connection to invalidate.
    1493     *
    1494     * @throws IllegalStateException if invalidating the connection failed.
    1495     * @since 2.1
    1496     */
    1497    @SuppressWarnings("resource")
    1498    public void invalidateConnection(final Connection connection) throws IllegalStateException {
    1499        if (connection == null) {
    1500            return;
    1501        }
    1502        if (connectionPool == null) {
    1503            throw new IllegalStateException("Cannot invalidate connection: ConnectionPool is null.");
    1504        }
    1505
    1506        final PoolableConnection poolableConnection;
    1507        try {
    1508            poolableConnection = connection.unwrap(PoolableConnection.class);
    1509            if (poolableConnection == null) {
    1510                throw new IllegalStateException(
    1511                        "Cannot invalidate connection: Connection is not a poolable connection.");
    1512            }
    1513        } catch (final SQLException e) {
    1514            throw new IllegalStateException("Cannot invalidate connection: Unwrapping poolable connection failed.", e);
    1515        }
    1516
    1517        try {
    1518            connectionPool.invalidateObject(poolableConnection);
    1519        } catch (final Exception e) {
    1520            throw new IllegalStateException("Invalidating connection threw unexpected exception", e);
    1521        }
    1522    }
    1523
    1524    /**
    1525     * Gets the value of the accessToUnderlyingConnectionAllowed property.
    1526     *
    1527     * @return true if access to the underlying connection is allowed, false otherwise.
    1528     */
    1529    @Override
    1530    public synchronized boolean isAccessToUnderlyingConnectionAllowed() {
    1531        return this.accessToUnderlyingConnectionAllowed;
    1532    }
    1533
    1534    /**
    1535     * Returns true if the statement pool is cleared when the connection is returned to its pool.
    1536     *
    1537     * @return true if the statement pool is cleared at connection return
    1538     * @since 2.8.0
    1539     */
    1540    @Override
    1541    public boolean isClearStatementPoolOnReturn() {
    1542        return clearStatementPoolOnReturn;
    1543    }
    1544
    1545    /**
    1546     * If true, this data source is closed and no more connections can be retrieved from this data source.
    1547     *
    1548     * @return true, if the data source is closed; false otherwise
    1549     */
    1550    @Override
    1551    public synchronized boolean isClosed() {
    1552        return closed;
    1553    }
    1554
    1555    /**
    1556     * Delegates in a null-safe manner to {@link String#isEmpty()}.
    1557     *
    1558     * @param value the string to test, may be null.
    1559     * @return boolean false if value is null, otherwise {@link String#isEmpty()}.
    1560     */
    1561    private boolean isEmpty(final String value) {
    1562        return value == null || value.trim().isEmpty();
    1563    }
    1564
    1565    /**
    1566     * Returns true if we are pooling statements.
    1567     *
    1568     * @return true if prepared and callable statements are pooled
    1569     */
    1570    @Override
    1571    public synchronized boolean isPoolPreparedStatements() {
    1572        return this.poolPreparedStatements;
    1573    }
    1574
    1575    @Override
    1576    public boolean isWrapperFor(final Class<?> iface) throws SQLException {
    1577        return iface != null && iface.isInstance(this);
    1578    }
    1579
    1580    private void jmxRegister() {
    1581        // Return immediately if this DataSource has already been registered
    1582        if (registeredJmxObjectName != null) {
    1583            return;
    1584        }
    1585        // Return immediately if no JMX name has been specified
    1586        final String requestedName = getJmxName();
    1587        if (requestedName == null) {
    1588            return;
    1589        }
    1590        registeredJmxObjectName = registerJmxObjectName(requestedName, null);
    1591        try {
    1592            final StandardMBean standardMBean = new StandardMBean(this, DataSourceMXBean.class);
    1593            registeredJmxObjectName.registerMBean(standardMBean);
    1594        } catch (final NotCompliantMBeanException e) {
    1595            log.warn("The requested JMX name [" + requestedName + "] was not valid and will be ignored.");
    1596        }
    1597    }
    1598
    1599    /**
    1600     * Logs the given message.
    1601     *
    1602     * @param message the message to log.
    1603     */
    1604    protected void log(final String message) {
    1605        if (logWriter != null) {
    1606            logWriter.println(message);
    1607        }
    1608    }
    1609
    1610    /**
    1611     * Logs the given throwable.
    1612     * @param message TODO
    1613     * @param throwable the throwable.
    1614     *
    1615     * @since 2.7.0
    1616     */
    1617    protected void log(final String message, final Throwable throwable) {
    1618        if (logWriter != null) {
    1619            logWriter.println(message);
    1620            throwable.printStackTrace(logWriter);
    1621        }
    1622    }
    1623
    1624    @Override
    1625    public void postDeregister() {
    1626        // NO-OP
    1627    }
    1628
    1629    @Override
    1630    public void postRegister(final Boolean registrationDone) {
    1631        // NO-OP
    1632    }
    1633
    1634    @Override
    1635    public void preDeregister() throws Exception {
    1636        // NO-OP
    1637    }
    1638
    1639    @Override
    1640    public ObjectName preRegister(final MBeanServer server, final ObjectName objectName) {
    1641        registeredJmxObjectName = registerJmxObjectName(getJmxName(), objectName);
    1642        return ObjectNameWrapper.unwrap(registeredJmxObjectName);
    1643    }
    1644
    1645    private ObjectNameWrapper registerJmxObjectName(final String requestedName, final ObjectName objectName) {
    1646        ObjectNameWrapper objectNameWrapper = null;
    1647        if (requestedName != null) {
    1648            try {
    1649                objectNameWrapper = ObjectNameWrapper.wrap(requestedName);
    1650            } catch (final MalformedObjectNameException e) {
    1651                log.warn("The requested JMX name '" + requestedName + "' was not valid and will be ignored.");
    1652            }
    1653        }
    1654        if (objectNameWrapper == null) {
    1655            objectNameWrapper = ObjectNameWrapper.wrap(objectName);
    1656        }
    1657        return objectNameWrapper;
    1658    }
    1659
    1660    /**
    1661     * Removes a custom connection property.
    1662     *
    1663     * @param name Name of the custom connection property to remove
    1664     * @see #addConnectionProperty(String, String)
    1665     */
    1666    public void removeConnectionProperty(final String name) {
    1667        connectionProperties.remove(name);
    1668    }
    1669
    1670    /**
    1671     * Restarts the datasource.
    1672     * <p>
    1673     * This method calls {@link #close()} and {@link #start()} in sequence within synchronized scope so any
    1674     * connection requests that come in while the datasource is shutting down will be served by the new pool.
    1675     * <p>
    1676     * Idle connections that are stored in the connection pool when this method is invoked are closed, but
    1677     * connections that are checked out to clients when this method is invoked are not affected. When client
    1678     * applications subsequently invoke {@link Connection#close()} to return these connections to the pool, the
    1679     * underlying JDBC connections are closed. These connections do not count in {@link #getMaxTotal()} or
    1680     * {@link #getNumActive()} after invoking this method. For example, if there are 3 connections checked out by
    1681     * clients when {@link #restart()} is invoked, after this method is called, {@link #getNumActive()} will
    1682     * return 0 and up to {@link #getMaxTotal()} + 3 connections may be open until the connections sourced from
    1683     * the original pool are returned.
    1684     * <p>
    1685     * The new connection pool created by this method is initialized with currently set configuration properties.
    1686     *
    1687     * @throws SQLException if an error occurs initializing the datasource
    1688     */
    1689    @Override
    1690    public synchronized void restart() throws SQLException {
    1691        close();
    1692        start();
    1693    }
    1694
    1695    private <T> void setAbandoned(final BiConsumer<AbandonedConfig, T> consumer, final T object) {
    1696        if (abandonedConfig == null) {
    1697            abandonedConfig = new AbandonedConfig();
    1698        }
    1699        consumer.accept(abandonedConfig, object);
    1700        final GenericObjectPool<?> gop = this.connectionPool;
    1701        if (gop != null) {
    1702            gop.setAbandonedConfig(abandonedConfig);
    1703        }
    1704    }
    1705
    1706    /**
    1707     * Sets the print writer to be used by this configuration to log information on abandoned objects.
    1708     *
    1709     * @param logWriter The new log writer
    1710     */
    1711    public void setAbandonedLogWriter(final PrintWriter logWriter) {
    1712        setAbandoned(AbandonedConfig::setLogWriter, logWriter);
    1713    }
    1714
    1715    /**
    1716     * If the connection pool implements {@link org.apache.commons.pool2.UsageTracking UsageTracking}, configure whether
    1717     * the connection pool should record a stack trace every time a method is called on a pooled connection and retain
    1718     * the most recent stack trace to aid debugging of abandoned connections.
    1719     *
    1720     * @param usageTracking A value of {@code true} will enable the recording of a stack trace on every use of a
    1721     *                      pooled connection
    1722     */
    1723    public void setAbandonedUsageTracking(final boolean usageTracking) {
    1724        setAbandoned(AbandonedConfig::setUseUsageTracking, usageTracking);
    1725    }
    1726
    1727    /**
    1728     * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to
    1729     * the underlying connection. (Default: false)
    1730     * <p>
    1731     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    1732     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    1733     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    1734     * </p>
    1735     *
    1736     * @param allow Access to the underlying connection is granted when true.
    1737     */
    1738    public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) {
    1739        this.accessToUnderlyingConnectionAllowed = allow;
    1740    }
    1741
    1742    /**
    1743     * Sets the value of the flag that controls whether or not connections being returned to the pool will be checked
    1744     * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
    1745     * setting is {@code false} when the connection is returned. It is {@code true} by default.
    1746     *
    1747     * @param autoCommitOnReturn Whether or not connections being returned to the pool will be checked and configured
    1748     *                           with auto-commit.
    1749     * @since 2.6.0
    1750     */
    1751    public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) {
    1752        this.autoCommitOnReturn = autoCommitOnReturn;
    1753    }
    1754
    1755    /**
    1756     * Sets the state caching flag.
    1757     *
    1758     * @param cacheState The new value for the state caching flag
    1759     */
    1760    public void setCacheState(final boolean cacheState) {
    1761        this.cacheState = cacheState;
    1762    }
    1763
    1764    /**
    1765     * Sets whether the pool of statements (which was enabled with {@link #setPoolPreparedStatements(boolean)}) should
    1766     * be cleared when the connection is returned to its pool. Default is false.
    1767     *
    1768     * @param clearStatementPoolOnReturn clear or not
    1769     * @since 2.8.0
    1770     */
    1771    public void setClearStatementPoolOnReturn(final boolean clearStatementPoolOnReturn) {
    1772        this.clearStatementPoolOnReturn = clearStatementPoolOnReturn;
    1773    }
    1774
    1775    /**
    1776     * Sets the ConnectionFactory class name.
    1777     *
    1778     * @param connectionFactoryClassName A class name.
    1779     * @since 2.7.0
    1780     */
    1781    public void setConnectionFactoryClassName(final String connectionFactoryClassName) {
    1782        this.connectionFactoryClassName = isEmpty(connectionFactoryClassName) ? null : connectionFactoryClassName;
    1783    }
    1784
    1785    /**
    1786     * Sets the collection of SQL statements to be executed when a physical connection is first created.
    1787     * <p>
    1788     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    1789     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    1790     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    1791     * </p>
    1792     *
    1793     * @param connectionInitSqls Collection of SQL statements to execute on connection creation
    1794     */
    1795    public void setConnectionInitSqls(final Collection<String> connectionInitSqls) {
    1796        final List<String> collect = Utils.isEmpty(connectionInitSqls) ? null
    1797                : connectionInitSqls.stream().filter(s -> !isEmpty(s)).collect(Collectors.toList());
    1798        this.connectionInitSqls = Utils.isEmpty(collect) ? null : collect;
    1799    }
    1800
    1801    /**
    1802     * Sets the list of SQL statements to be executed when a physical connection is first created.
    1803     * <p>
    1804     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    1805     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    1806     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    1807     * </p>
    1808     *
    1809     * @param connectionInitSqls List of SQL statements to execute on connection creation
    1810     * @since 2.12.0
    1811     */
    1812    public void setConnectionInitSqls(final List<String> connectionInitSqls) {
    1813        setConnectionInitSqls((Collection<String>) connectionInitSqls);
    1814    }
    1815
    1816    private <T> void setConnectionPool(final BiConsumer<GenericObjectPool<PoolableConnection>, T> consumer, final T object) {
    1817        if (connectionPool != null) {
    1818            consumer.accept(connectionPool, object);
    1819        }
    1820    }
    1821
    1822    /**
    1823     * Sets the connection properties passed to driver.connect(...).
    1824     * <p>
    1825     * Format of the string must be [propertyName=property;]*
    1826     * </p>
    1827     * <p>
    1828     * NOTE - The "user" and "password" properties will be added explicitly, so they do not need to be included here.
    1829     * </p>
    1830     *
    1831     * @param connectionProperties the connection properties used to create new connections
    1832     */
    1833    public void setConnectionProperties(final String connectionProperties) {
    1834        Objects.requireNonNull(connectionProperties, "connectionProperties");
    1835        final String[] entries = connectionProperties.split(";");
    1836        final Properties properties = new Properties();
    1837        Stream.of(entries).filter(e -> !e.isEmpty()).forEach(entry -> {
    1838            final int index = entry.indexOf('=');
    1839            if (index > 0) {
    1840                final String name = entry.substring(0, index);
    1841                final String value = entry.substring(index + 1);
    1842                properties.setProperty(name, value);
    1843            } else {
    1844                // no value is empty string which is how
    1845                // java.util.Properties works
    1846                properties.setProperty(entry, "");
    1847            }
    1848        });
    1849        this.connectionProperties = properties;
    1850    }
    1851
    1852    /**
    1853     * Sets default auto-commit state of connections returned by this datasource.
    1854     * <p>
    1855     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    1856     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    1857     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    1858     * </p>
    1859     *
    1860     * @param defaultAutoCommit default auto-commit value
    1861     */
    1862    public void setDefaultAutoCommit(final Boolean defaultAutoCommit) {
    1863        this.defaultAutoCommit = defaultAutoCommit;
    1864    }
    1865
    1866    /**
    1867     * Sets the default catalog.
    1868     * <p>
    1869     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    1870     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    1871     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    1872     * </p>
    1873     *
    1874     * @param defaultCatalog the default catalog
    1875     */
    1876    public void setDefaultCatalog(final String defaultCatalog) {
    1877        this.defaultCatalog = isEmpty(defaultCatalog) ? null : defaultCatalog;
    1878    }
    1879
    1880    /**
    1881     * Sets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
    1882     * connection. {@code null} means that the driver default will be used.
    1883     *
    1884     * @param defaultQueryTimeoutDuration The default query timeout Duration.
    1885     * @since 2.10.0
    1886     */
    1887    public void setDefaultQueryTimeout(final Duration defaultQueryTimeoutDuration) {
    1888        this.defaultQueryTimeoutDuration = defaultQueryTimeoutDuration;
    1889    }
    1890
    1891    /**
    1892     * Sets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
    1893     * connection. {@code null} means that the driver default will be used.
    1894     *
    1895     * @param defaultQueryTimeoutSeconds The default query timeout in seconds.
    1896     * @deprecated Use {@link #setDefaultQueryTimeout(Duration)}.
    1897     */
    1898    @Deprecated
    1899    public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) {
    1900        this.defaultQueryTimeoutDuration = defaultQueryTimeoutSeconds == null ? null : Duration.ofSeconds(defaultQueryTimeoutSeconds);
    1901    }
    1902
    1903    /**
    1904     * Sets defaultReadonly property.
    1905     * <p>
    1906     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    1907     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    1908     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    1909     * </p>
    1910     *
    1911     * @param defaultReadOnly default read-only value
    1912     */
    1913    public void setDefaultReadOnly(final Boolean defaultReadOnly) {
    1914        this.defaultReadOnly = defaultReadOnly;
    1915    }
    1916
    1917    /**
    1918     * Sets the default schema.
    1919     * <p>
    1920     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    1921     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    1922     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    1923     * </p>
    1924     *
    1925     * @param defaultSchema the default catalog
    1926     * @since 2.5.0
    1927     */
    1928    public void setDefaultSchema(final String defaultSchema) {
    1929        this.defaultSchema = isEmpty(defaultSchema) ? null : defaultSchema;
    1930    }
    1931
    1932    /**
    1933     * Sets the default transaction isolation state for returned connections.
    1934     * <p>
    1935     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    1936     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    1937     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    1938     * </p>
    1939     *
    1940     * @param defaultTransactionIsolation the default transaction isolation state
    1941     * @see Connection#getTransactionIsolation
    1942     */
    1943    public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) {
    1944        this.defaultTransactionIsolation = defaultTransactionIsolation;
    1945    }
    1946
    1947    /**
    1948     * Sets the SQL_STATE codes considered to signal fatal conditions.
    1949     * <p>
    1950     * Overrides the defaults in {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with
    1951     * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #getFastFailValidation()}
    1952     * is {@code true}, whenever connections created by this datasource generate exceptions with SQL_STATE codes in this
    1953     * list, they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at
    1954     * isValid or validation query).
    1955     * </p>
    1956     * <p>
    1957     * If {@link #getFastFailValidation()} is {@code false} setting this property has no effect.
    1958     * </p>
    1959     * <p>
    1960     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    1961     * time one of the following methods is invoked: {@code getConnection, setLogwriter,
    1962     * setLoginTimeout, getLoginTimeout, getLogWriter}.
    1963     * </p>
    1964     *
    1965     * @param disconnectionSqlCodes SQL_STATE codes considered to signal fatal conditions
    1966     * @since 2.1
    1967     */
    1968    public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) {
    1969        final Set<String> collect = Utils.isEmpty(disconnectionSqlCodes) ? null
    1970                : disconnectionSqlCodes.stream().filter(s -> !isEmpty(s)).collect(Collectors.toSet());
    1971        this.disconnectionSqlCodes = Utils.isEmpty(collect) ? null : collect;
    1972    }
    1973
    1974    /**
    1975     * Sets the JDBC Driver instance to use for this pool.
    1976     * <p>
    1977     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    1978     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    1979     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    1980     * </p>
    1981     *
    1982     * @param driver The JDBC Driver instance to use for this pool.
    1983     */
    1984    public synchronized void setDriver(final Driver driver) {
    1985        this.driver = driver;
    1986    }
    1987
    1988    /**
    1989     * Sets the class loader to be used to load the JDBC driver.
    1990     * <p>
    1991     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    1992     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    1993     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    1994     * </p>
    1995     *
    1996     * @param driverClassLoader the class loader with which to load the JDBC driver
    1997     */
    1998    public synchronized void setDriverClassLoader(final ClassLoader driverClassLoader) {
    1999        this.driverClassLoader = driverClassLoader;
    2000    }
    2001
    2002    /**
    2003     * Sets the JDBC driver class name.
    2004     * <p>
    2005     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    2006     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    2007     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    2008     * </p>
    2009     *
    2010     * @param driverClassName the class name of the JDBC driver
    2011     */
    2012    public synchronized void setDriverClassName(final String driverClassName) {
    2013        this.driverClassName = isEmpty(driverClassName) ? null : driverClassName;
    2014    }
    2015
    2016    /**
    2017     * Sets the {code durationBetweenEvictionRuns} property.
    2018     *
    2019     * @param timeBetweenEvictionRunsMillis the new time between evictor runs
    2020     * @see #setDurationBetweenEvictionRuns(Duration)
    2021     * @since 2.10.0
    2022     */
    2023    public synchronized void setDurationBetweenEvictionRuns(final Duration timeBetweenEvictionRunsMillis) {
    2024        this.durationBetweenEvictionRuns = timeBetweenEvictionRunsMillis;
    2025        setConnectionPool(GenericObjectPool::setDurationBetweenEvictionRuns, timeBetweenEvictionRunsMillis);
    2026    }
    2027
    2028    /**
    2029     * Sets the value of the flag that controls whether or not connections being returned to the pool will be checked
    2030     * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
    2031     * setting is {@code false} when the connection is returned. It is {@code true} by default.
    2032     *
    2033     * @param autoCommitOnReturn Whether or not connections being returned to the pool will be checked and configured
    2034     *                           with auto-commit.
    2035     * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}.
    2036     */
    2037    @Deprecated
    2038    public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) {
    2039        this.autoCommitOnReturn = autoCommitOnReturn;
    2040    }
    2041
    2042    /**
    2043     * Sets the EvictionPolicy implementation to use with this connection pool.
    2044     *
    2045     * @param evictionPolicyClassName The fully qualified class name of the EvictionPolicy implementation
    2046     */
    2047    public synchronized void setEvictionPolicyClassName(final String evictionPolicyClassName) {
    2048        setConnectionPool(GenericObjectPool::setEvictionPolicyClassName, evictionPolicyClassName);
    2049        this.evictionPolicyClassName = evictionPolicyClassName;
    2050    }
    2051
    2052    /**
    2053     * @see #getFastFailValidation()
    2054     * @param fastFailValidation true means connections created by this factory will fast fail validation
    2055     * @since 2.1
    2056     */
    2057    public void setFastFailValidation(final boolean fastFailValidation) {
    2058        this.fastFailValidation = fastFailValidation;
    2059    }
    2060
    2061    /**
    2062     * Sets the initial size of the connection pool.
    2063     * <p>
    2064     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    2065     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    2066     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    2067     * </p>
    2068     *
    2069     * @param initialSize the number of connections created when the pool is initialized
    2070     */
    2071    public synchronized void setInitialSize(final int initialSize) {
    2072        this.initialSize = initialSize;
    2073    }
    2074
    2075    /**
    2076     * Sets the JMX name that has been requested for this DataSource. If the requested name is not valid, an alternative
    2077     * may be chosen. This DataSource will attempt to register itself using this name. If another component registers
    2078     * this DataSource with JMX and this name is valid this name will be used in preference to any specified by the
    2079     * other component.
    2080     *
    2081     * @param jmxName The JMX name that has been requested for this DataSource
    2082     */
    2083    public void setJmxName(final String jmxName) {
    2084        this.jmxName = jmxName;
    2085    }
    2086
    2087    /**
    2088     * Sets the LIFO property. True means the pool behaves as a LIFO queue; false means FIFO.
    2089     *
    2090     * @param lifo the new value for the LIFO property
    2091     */
    2092    public synchronized void setLifo(final boolean lifo) {
    2093        this.lifo = lifo;
    2094        setConnectionPool(GenericObjectPool::setLifo, lifo);
    2095    }
    2096
    2097    /**
    2098     * @param logAbandoned new logAbandoned property value
    2099     */
    2100    public void setLogAbandoned(final boolean logAbandoned) {
    2101        setAbandoned(AbandonedConfig::setLogAbandoned, logAbandoned);
    2102    }
    2103
    2104    /**
    2105     * When {@link #getMaxConnDuration()} is set to limit connection lifetime, this property determines whether or
    2106     * not log messages are generated when the pool closes connections due to maximum lifetime exceeded. Set this
    2107     * property to false to suppress log messages when connections expire.
    2108     *
    2109     * @param logExpiredConnections Whether or not log messages are generated when the pool closes connections due to
    2110     *                              maximum lifetime exceeded.
    2111     */
    2112    public void setLogExpiredConnections(final boolean logExpiredConnections) {
    2113        this.logExpiredConnections = logExpiredConnections;
    2114    }
    2115
    2116    /**
    2117     * <strong>BasicDataSource does NOT support this method. </strong>
    2118     *
    2119     * <p>
    2120     * Sets the login timeout (in seconds) for connecting to the database.
    2121     * </p>
    2122     * <p>
    2123     * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool.
    2124     * </p>
    2125     *
    2126     * @param loginTimeout The new login timeout, or zero for no timeout
    2127     * @throws UnsupportedOperationException If the DataSource implementation does not support the login timeout
    2128     *                                       feature.
    2129     * @throws SQLException                  if a database access error occurs
    2130     */
    2131    @Override
    2132    public void setLoginTimeout(final int loginTimeout) throws SQLException {
    2133        // This method isn't supported by the PoolingDataSource returned by the
    2134        // createDataSource
    2135        throw new UnsupportedOperationException("Not supported by BasicDataSource");
    2136    }
    2137
    2138    /**
    2139     * Sets the log writer being used by this data source.
    2140     * <p>
    2141     * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool.
    2142     * </p>
    2143     *
    2144     * @param logWriter The new log writer
    2145     * @throws SQLException if a database access error occurs
    2146     */
    2147    @Override
    2148    public void setLogWriter(final PrintWriter logWriter) throws SQLException {
    2149        createDataSource().setLogWriter(logWriter);
    2150        this.logWriter = logWriter;
    2151    }
    2152
    2153    /**
    2154     * Sets the maximum permitted lifetime of a connection. A value of zero or less indicates an
    2155     * infinite lifetime.
    2156     * <p>
    2157     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    2158     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    2159     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    2160     * </p>
    2161     *
    2162     * @param maxConnDuration The maximum permitted lifetime of a connection.
    2163     * @since 2.10.0
    2164     */
    2165    public void setMaxConn(final Duration maxConnDuration) {
    2166        this.maxConnDuration = maxConnDuration;
    2167    }
    2168
    2169    /**
    2170     * Sets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an
    2171     * infinite lifetime.
    2172     * <p>
    2173     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    2174     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    2175     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    2176     * </p>
    2177     *
    2178     * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection in milliseconds.
    2179     * @deprecated Use {@link #setMaxConn(Duration)}.
    2180     */
    2181    @Deprecated
    2182    public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) {
    2183        this.maxConnDuration = Duration.ofMillis(maxConnLifetimeMillis);
    2184    }
    2185
    2186    /**
    2187     * Sets the maximum number of connections that can remain idle in the pool. Excess idle connections are destroyed on
    2188     * return to the pool.
    2189     *
    2190     * @see #getMaxIdle()
    2191     * @param maxIdle the new value for maxIdle
    2192     */
    2193    public synchronized void setMaxIdle(final int maxIdle) {
    2194        this.maxIdle = maxIdle;
    2195        setConnectionPool(GenericObjectPool::setMaxIdle, maxIdle);
    2196    }
    2197
    2198    /**
    2199     * Sets the value of the {@code maxOpenPreparedStatements} property.
    2200     * <p>
    2201     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    2202     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    2203     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    2204     * </p>
    2205     *
    2206     * @param maxOpenStatements the new maximum number of prepared statements
    2207     */
    2208    public synchronized void setMaxOpenPreparedStatements(final int maxOpenStatements) {
    2209        this.maxOpenPreparedStatements = maxOpenStatements;
    2210    }
    2211
    2212    /**
    2213     * Sets the maximum total number of idle and borrows connections that can be active at the same time. Use a negative
    2214     * value for no limit.
    2215     *
    2216     * @param maxTotal the new value for maxTotal
    2217     * @see #getMaxTotal()
    2218     */
    2219    public synchronized void setMaxTotal(final int maxTotal) {
    2220        this.maxTotal = maxTotal;
    2221        setConnectionPool(GenericObjectPool::setMaxTotal, maxTotal);
    2222    }
    2223
    2224    /**
    2225     * Sets the MaxWaitMillis property. Use -1 to make the pool wait indefinitely.
    2226     *
    2227     * @param maxWaitDuration the new value for MaxWaitMillis
    2228     * @see #getMaxWaitDuration()
    2229     * @since 2.10.0
    2230     */
    2231    public synchronized void setMaxWait(final Duration maxWaitDuration) {
    2232        this.maxWaitDuration = maxWaitDuration;
    2233        setConnectionPool(GenericObjectPool::setMaxWait, maxWaitDuration);
    2234    }
    2235
    2236    /**
    2237     * Sets the MaxWaitMillis property. Use -1 to make the pool wait indefinitely.
    2238     *
    2239     * @param maxWaitMillis the new value for MaxWaitMillis
    2240     * @see #getMaxWaitDuration()
    2241     * @deprecated {@link #setMaxWait(Duration)}.
    2242     */
    2243    @Deprecated
    2244    public synchronized void setMaxWaitMillis(final long maxWaitMillis) {
    2245        setMaxWait(Duration.ofMillis(maxWaitMillis));
    2246    }
    2247
    2248    /**
    2249     * Sets the {code minEvictableIdleDuration} property.
    2250     *
    2251     * @param minEvictableIdleDuration the minimum amount of time an object may sit idle in the pool
    2252     * @see #setMinEvictableIdle(Duration)
    2253     * @since 2.10.0
    2254     */
    2255    public synchronized void setMinEvictableIdle(final Duration minEvictableIdleDuration) {
    2256        this.minEvictableIdleDuration = minEvictableIdleDuration;
    2257        setConnectionPool(GenericObjectPool::setMinEvictableIdleDuration, minEvictableIdleDuration);
    2258    }
    2259
    2260    /**
    2261     * Sets the {code minEvictableIdleDuration} property.
    2262     *
    2263     * @param minEvictableIdleTimeMillis the minimum amount of time an object may sit idle in the pool
    2264     * @see #setMinEvictableIdle(Duration)
    2265     * @deprecated Use {@link #setMinEvictableIdle(Duration)}.
    2266     */
    2267    @Deprecated
    2268    public synchronized void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) {
    2269        setMinEvictableIdle(Duration.ofMillis(minEvictableIdleTimeMillis));
    2270    }
    2271
    2272    /**
    2273     * Sets the minimum number of idle connections in the pool. The pool attempts to ensure that minIdle connections are
    2274     * available when the idle object evictor runs. The value of this property has no effect unless
    2275     * {code durationBetweenEvictionRuns} has a positive value.
    2276     *
    2277     * @param minIdle the new value for minIdle
    2278     * @see GenericObjectPool#setMinIdle(int)
    2279     */
    2280    public synchronized void setMinIdle(final int minIdle) {
    2281        this.minIdle = minIdle;
    2282        setConnectionPool(GenericObjectPool::setMinIdle, minIdle);
    2283    }
    2284
    2285    /**
    2286     * Sets the value of the {code numTestsPerEvictionRun} property.
    2287     *
    2288     * @param numTestsPerEvictionRun the new {code numTestsPerEvictionRun} value
    2289     * @see #setNumTestsPerEvictionRun(int)
    2290     */
    2291    public synchronized void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
    2292        this.numTestsPerEvictionRun = numTestsPerEvictionRun;
    2293        setConnectionPool(GenericObjectPool::setNumTestsPerEvictionRun, numTestsPerEvictionRun);
    2294    }
    2295
    2296    /**
    2297     * Sets the {code password}.
    2298     * <p>
    2299     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    2300     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    2301     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    2302     * </p>
    2303     *
    2304     * @param password new value for the password
    2305     */
    2306    public void setPassword(final String password) {
    2307        this.password = password;
    2308    }
    2309
    2310    /**
    2311     * Sets whether to pool statements or not.
    2312     * <p>
    2313     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    2314     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    2315     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    2316     * </p>
    2317     *
    2318     * @param poolingStatements pooling on or off
    2319     */
    2320    public synchronized void setPoolPreparedStatements(final boolean poolingStatements) {
    2321        this.poolPreparedStatements = poolingStatements;
    2322    }
    2323
    2324    /**
    2325     * Sets if connection level JMX tracking is requested for this DataSource. If true, each connection will be
    2326     * registered for tracking with JMX.
    2327     *
    2328     * @param registerConnectionMBean connection tracking requested for this DataSource.
    2329     */
    2330    public void setRegisterConnectionMBean(final boolean registerConnectionMBean) {
    2331        this.registerConnectionMBean = registerConnectionMBean;
    2332    }
    2333
    2334    /**
    2335     * @param removeAbandonedOnBorrow true means abandoned connections may be removed when connections are borrowed from
    2336     *                                the pool.
    2337     * @see #getRemoveAbandonedOnBorrow()
    2338     */
    2339    public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) {
    2340        setAbandoned(AbandonedConfig::setRemoveAbandonedOnBorrow, removeAbandonedOnBorrow);
    2341    }
    2342
    2343    /**
    2344     * @param removeAbandonedOnMaintenance true means abandoned connections may be removed on pool maintenance.
    2345     * @see #getRemoveAbandonedOnMaintenance()
    2346     */
    2347    public void setRemoveAbandonedOnMaintenance(final boolean removeAbandonedOnMaintenance) {
    2348        setAbandoned(AbandonedConfig::setRemoveAbandonedOnMaintenance, removeAbandonedOnMaintenance);
    2349    }
    2350
    2351    /**
    2352     * Sets the timeout before an abandoned connection can be removed.
    2353     * <p>
    2354     * Setting this property has no effect if {@link #getRemoveAbandonedOnBorrow()} and
    2355     * {code getRemoveAbandonedOnMaintenance()} are false.
    2356     * </p>
    2357     *
    2358     * @param removeAbandonedTimeout new abandoned timeout
    2359     * @see #getRemoveAbandonedTimeoutDuration()
    2360     * @see #getRemoveAbandonedOnBorrow()
    2361     * @see #getRemoveAbandonedOnMaintenance()
    2362     * @since 2.10.0
    2363     */
    2364    public void setRemoveAbandonedTimeout(final Duration removeAbandonedTimeout) {
    2365        setAbandoned(AbandonedConfig::setRemoveAbandonedTimeout, removeAbandonedTimeout);
    2366    }
    2367
    2368    /**
    2369     * Sets the timeout in seconds before an abandoned connection can be removed.
    2370     * <p>
    2371     * Setting this property has no effect if {@link #getRemoveAbandonedOnBorrow()} and
    2372     * {@link #getRemoveAbandonedOnMaintenance()} are false.
    2373     * </p>
    2374     *
    2375     * @param removeAbandonedTimeout new abandoned timeout in seconds
    2376     * @see #getRemoveAbandonedTimeoutDuration()
    2377     * @see #getRemoveAbandonedOnBorrow()
    2378     * @see #getRemoveAbandonedOnMaintenance()
    2379     * @deprecated Use {@link #setRemoveAbandonedTimeout(Duration)}.
    2380     */
    2381    @Deprecated
    2382    public void setRemoveAbandonedTimeout(final int removeAbandonedTimeout) {
    2383        setAbandoned(AbandonedConfig::setRemoveAbandonedTimeout, Duration.ofSeconds(removeAbandonedTimeout));
    2384    }
    2385
    2386    /**
    2387     * Sets the flag that controls if a connection will be rolled back when it is returned to the pool if auto commit is
    2388     * not enabled and the connection is not read only.
    2389     *
    2390     * @param rollbackOnReturn whether a connection will be rolled back when it is returned to the pool.
    2391     */
    2392    public void setRollbackOnReturn(final boolean rollbackOnReturn) {
    2393        this.rollbackOnReturn = rollbackOnReturn;
    2394    }
    2395
    2396    /**
    2397     * Sets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the
    2398     * idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool.
    2399     *
    2400     * @param softMinEvictableIdleTimeMillis minimum amount of time a connection may sit idle in the pool before it is
    2401     *                                       eligible for eviction, assuming there are minIdle idle connections in the
    2402     *                                       pool.
    2403     * @see #getSoftMinEvictableIdleTimeMillis
    2404     * @since 2.10.0
    2405     */
    2406    public synchronized void setSoftMinEvictableIdle(final Duration softMinEvictableIdleTimeMillis) {
    2407        this.softMinEvictableIdleDuration = softMinEvictableIdleTimeMillis;
    2408        setConnectionPool(GenericObjectPool::setSoftMinEvictableIdleDuration, softMinEvictableIdleTimeMillis);
    2409    }
    2410
    2411    /**
    2412     * Sets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the
    2413     * idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool.
    2414     *
    2415     * @param softMinEvictableIdleTimeMillis minimum amount of time a connection may sit idle in the pool before it is
    2416     *                                       eligible for eviction, assuming there are minIdle idle connections in the
    2417     *                                       pool.
    2418     * @see #getSoftMinEvictableIdleTimeMillis
    2419     * @deprecated Use {@link #setSoftMinEvictableIdle(Duration)}.
    2420     */
    2421    @Deprecated
    2422    public synchronized void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) {
    2423        setSoftMinEvictableIdle(Duration.ofMillis(softMinEvictableIdleTimeMillis));
    2424    }
    2425
    2426    /**
    2427     * Sets the {code testOnBorrow} property. This property determines whether or not the pool will validate objects
    2428     * before they are borrowed from the pool.
    2429     *
    2430     * @param testOnBorrow new value for testOnBorrow property
    2431     */
    2432    public synchronized void setTestOnBorrow(final boolean testOnBorrow) {
    2433        this.testOnBorrow = testOnBorrow;
    2434        setConnectionPool(GenericObjectPool::setTestOnBorrow, testOnBorrow);
    2435    }
    2436
    2437    /**
    2438     * Sets the {code testOnCreate} property. This property determines whether or not the pool will validate objects
    2439     * immediately after they are created by the pool
    2440     *
    2441     * @param testOnCreate new value for testOnCreate property
    2442     */
    2443    public synchronized void setTestOnCreate(final boolean testOnCreate) {
    2444        this.testOnCreate = testOnCreate;
    2445        setConnectionPool(GenericObjectPool::setTestOnCreate, testOnCreate);
    2446    }
    2447
    2448    /**
    2449     * Sets the {@code testOnReturn} property. This property determines whether or not the pool will validate
    2450     * objects before they are returned to the pool.
    2451     *
    2452     * @param testOnReturn new value for testOnReturn property
    2453     */
    2454    public synchronized void setTestOnReturn(final boolean testOnReturn) {
    2455        this.testOnReturn = testOnReturn;
    2456        setConnectionPool(GenericObjectPool::setTestOnReturn, testOnReturn);
    2457    }
    2458
    2459    /**
    2460     * Sets the {@code testWhileIdle} property. This property determines whether or not the idle object evictor
    2461     * will validate connections.
    2462     *
    2463     * @param testWhileIdle new value for testWhileIdle property
    2464     */
    2465    public synchronized void setTestWhileIdle(final boolean testWhileIdle) {
    2466        this.testWhileIdle = testWhileIdle;
    2467        setConnectionPool(GenericObjectPool::setTestWhileIdle, testWhileIdle);
    2468    }
    2469
    2470    /**
    2471     * Sets the {code durationBetweenEvictionRuns} property.
    2472     *
    2473     * @param timeBetweenEvictionRunsMillis the new time between evictor runs
    2474     * @see #setDurationBetweenEvictionRuns(Duration)
    2475     * @deprecated Use {@link #setDurationBetweenEvictionRuns(Duration)}.
    2476     */
    2477    @Deprecated
    2478    public synchronized void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
    2479        setDurationBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRunsMillis));
    2480    }
    2481
    2482    /**
    2483     * Sets the {code connection string}.
    2484     * <p>
    2485     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    2486     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    2487     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    2488     * </p>
    2489     *
    2490     * @param connectionString the new value for the JDBC connection connectionString
    2491     */
    2492    public synchronized void setUrl(final String connectionString) {
    2493        this.connectionString = connectionString;
    2494    }
    2495
    2496    /**
    2497     * Sets the {code userName}.
    2498     * <p>
    2499     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    2500     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    2501     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    2502     * </p>
    2503     *
    2504     * @param userName the new value for the JDBC connection user name
    2505     */
    2506    public void setUsername(final String userName) {
    2507        this.userName = userName;
    2508    }
    2509
    2510    /**
    2511     * Sets the {code validationQuery}.
    2512     * <p>
    2513     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    2514     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    2515     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    2516     * </p>
    2517     *
    2518     * @param validationQuery the new value for the validation query
    2519     */
    2520    public void setValidationQuery(final String validationQuery) {
    2521        this.validationQuery = isEmpty(validationQuery) ? null : validationQuery;
    2522    }
    2523
    2524    /**
    2525     * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a
    2526     * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout.
    2527     * <p>
    2528     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    2529     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    2530     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    2531     * </p>
    2532     *
    2533     * @param validationQueryTimeoutDuration new validation query timeout value in seconds
    2534     * @since 2.10.0
    2535     */
    2536    public void setValidationQueryTimeout(final Duration validationQueryTimeoutDuration) {
    2537        this.validationQueryTimeoutDuration = validationQueryTimeoutDuration;
    2538    }
    2539
    2540    /**
    2541     * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a
    2542     * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout.
    2543     * <p>
    2544     * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
    2545     * time one of the following methods is invoked: <code>getConnection, setLogwriter,
    2546     * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
    2547     * </p>
    2548     *
    2549     * @param validationQueryTimeoutSeconds new validation query timeout value in seconds
    2550     * @deprecated Use {@link #setValidationQueryTimeout(Duration)}.
    2551     */
    2552    @Deprecated
    2553    public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) {
    2554        this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds);
    2555    }
    2556
    2557    /**
    2558     * Starts the datasource.
    2559     * <p>
    2560     * It is not necessary to call this method before using a newly created BasicDataSource instance, but
    2561     * calling it in that context causes the datasource to be immediately initialized (instead of waiting for
    2562     * the first {@link #getConnection()} request). Its primary use is to restart and reinitialize a
    2563     * datasource that has been closed.
    2564     * <p>
    2565     * When this method is called after {@link #close()}, connections checked out by clients
    2566     * before the datasource was stopped do not count in {@link #getMaxTotal()} or {@link #getNumActive()}.
    2567     * For example, if there are 3 connections checked out by clients when {@link #close()} is invoked and they are
    2568     * not returned before {@link #start()} is invoked, after this method is called, {@link #getNumActive()} will
    2569     * return 0.  These connections will be physically closed when they are returned, but they will not count against
    2570     * the maximum allowed in the newly started datasource.
    2571     *
    2572     * @throws SQLException if an error occurs initializing the datasource
    2573     */
    2574    @Override
    2575    public synchronized void start() throws SQLException {
    2576        closed = false;
    2577        createDataSource();
    2578    }
    2579
    2580    /**
    2581     * Starts the connection pool maintenance task, if configured.
    2582     */
    2583    protected void startPoolMaintenance() {
    2584        if (connectionPool != null && durationBetweenEvictionRuns.compareTo(Duration.ZERO) > 0) {
    2585            connectionPool.setDurationBetweenEvictionRuns(durationBetweenEvictionRuns);
    2586        }
    2587    }
    2588
    2589    @Override
    2590    public <T> T unwrap(final Class<T> iface) throws SQLException {
    2591        if (isWrapperFor(iface)) {
    2592            return iface.cast(this);
    2593        }
    2594        throw new SQLException(this + " is not a wrapper for " + iface);
    2595    }
    2596
    2597    private void updateJmxName(final GenericObjectPoolConfig<?> config) {
    2598        if (registeredJmxObjectName == null) {
    2599            return;
    2600        }
    2601        final StringBuilder base = new StringBuilder(registeredJmxObjectName.toString());
    2602        base.append(Constants.JMX_CONNECTION_POOL_BASE_EXT);
    2603        config.setJmxNameBase(base.toString());
    2604        config.setJmxNamePrefix(Constants.JMX_CONNECTION_POOL_PREFIX);
    2605    }
    2606
    2607}