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