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