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