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