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