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