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