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