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