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