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