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