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