1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.tomcat.dbcp.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.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.HashSet;
34 import java.util.List;
35 import java.util.Objects;
36 import java.util.Properties;
37 import java.util.Set;
38 import java.util.logging.Logger;
39
40 import javax.management.MBeanRegistration;
41 import javax.management.MBeanServer;
42 import javax.management.MalformedObjectNameException;
43 import javax.management.ObjectName;
44 import javax.sql.DataSource;
45
46 import org.apache.juli.logging.Log;
47 import org.apache.juli.logging.LogFactory;
48 import org.apache.tomcat.dbcp.pool2.PooledObject;
49 import org.apache.tomcat.dbcp.pool2.impl.AbandonedConfig;
50 import org.apache.tomcat.dbcp.pool2.impl.BaseObjectPoolConfig;
51 import org.apache.tomcat.dbcp.pool2.impl.GenericKeyedObjectPoolConfig;
52 import org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool;
53 import org.apache.tomcat.dbcp.pool2.impl.GenericObjectPoolConfig;
54
55 /**
56  * <p>
57  * Basic implementation of <code>javax.sql.DataSource</code> that is configured via JavaBeans properties. This is not
58  * the only way to combine the <em>commons-dbcp2</em> and <em>commons-pool2</em> packages, but provides a "one stop
59  * shopping" solution for basic requirements.
60  * </p>
61  *
62  * @since 2.0
63  */

64 public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBeanRegistration, AutoCloseable {
65
66     /**
67      * @since 2.0
68      */

69     private class PaGetConnection implements PrivilegedExceptionAction<Connection> {
70
71         @Override
72         public Connection run() throws SQLException {
73             return createDataSource().getConnection();
74         }
75     }
76
77     private static final Log log = LogFactory.getLog(BasicDataSource.class);
78
79     static {
80         // Attempt to prevent deadlocks - see DBCP - 272
81         DriverManager.getDrivers();
82         try {
83             // Load classes now to prevent AccessControlExceptions later
84             // A number of classes are loaded when getConnection() is called
85             // but the following classes are not loaded and therefore require
86             // explicit loading.
87             if (Utils.IS_SECURITY_ENABLED) {
88                 final ClassLoader loader = BasicDataSource.class.getClassLoader();
89                 final String dbcpPackageName = BasicDataSource.class.getPackage().getName();
90                 loader.loadClass(dbcpPackageName + ".BasicDataSource$PaGetConnection");
91                 loader.loadClass(dbcpPackageName + ".DelegatingCallableStatement");
92                 loader.loadClass(dbcpPackageName + ".DelegatingDatabaseMetaData");
93                 loader.loadClass(dbcpPackageName + ".DelegatingPreparedStatement");
94                 loader.loadClass(dbcpPackageName + ".DelegatingResultSet");
95                 loader.loadClass(dbcpPackageName + ".PoolableCallableStatement");
96                 loader.loadClass(dbcpPackageName + ".PoolablePreparedStatement");
97                 loader.loadClass(dbcpPackageName + ".PoolingConnection$StatementType");
98                 loader.loadClass(dbcpPackageName + ".PStmtKey");
99
100                 final String poolPackageName = PooledObject.class.getPackage().getName();
101                 loader.loadClass(poolPackageName + ".impl.LinkedBlockingDeque$Node");
102                 loader.loadClass(poolPackageName + ".impl.GenericKeyedObjectPool$ObjectDeque");
103             }
104         } catch (final ClassNotFoundException cnfe) {
105             throw new IllegalStateException("Unable to pre-load classes", cnfe);
106         }
107     }
108
109     @SuppressWarnings("resource")
110     protected static void validateConnectionFactory(final PoolableConnectionFactory connectionFactory)
111             throws Exception {
112         PoolableConnection conn = null;
113         PooledObject<PoolableConnection> p = null;
114         try {
115             p = connectionFactory.makeObject();
116             conn = p.getObject();
117             connectionFactory.activateObject(p);
118             connectionFactory.validateConnection(conn);
119             connectionFactory.passivateObject(p);
120         } finally {
121             if (p != null) {
122                 connectionFactory.destroyObject(p);
123             }
124         }
125     }
126
127     /**
128      * The default auto-commit state of connections created by this pool.
129      */

130     private volatile Boolean defaultAutoCommit;
131
132     /**
133      * The default read-only state of connections created by this pool.
134      */

135     private transient Boolean defaultReadOnly;
136
137     /**
138      * The default TransactionIsolation state of connections created by this pool.
139      */

140     private volatile int defaultTransactionIsolation = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION;
141
142     private Integer defaultQueryTimeoutSeconds;
143
144     /**
145      * The default "catalog" of connections created by this pool.
146      */

147     private volatile String defaultCatalog;
148
149     /**
150      * The default "schema" of connections created by this pool.
151      */

152     private volatile String defaultSchema;
153
154     /**
155      * The property that controls if the pooled connections cache some state rather than query the database for current
156      * state to improve performance.
157      */

158     private boolean cacheState = true;
159
160     /**
161      * The instance of the JDBC Driver to use.
162      */

163     private Driver driver;
164
165     /**
166      * The fully qualified Java class name of the JDBC driver to be used.
167      */

168     private String driverClassName;
169
170     /**
171      * The class loader instance to use to load the JDBC driver. If not specified, {@link Class#forName(String)} is used
172      * to load the JDBC driver. If specified, {@link Class#forName(String, boolean, ClassLoader)} is used.
173      */

174     private ClassLoader driverClassLoader;
175
176     /**
177      * True means that borrowObject returns the most recently used ("last in") connection in the pool (if there are idle
178      * connections available). False means that the pool behaves as a FIFO queue - connections are taken from the idle
179      * instance pool in the order that they are returned to the pool.
180      */

181     private boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO;
182
183     /**
184      * The maximum number of active connections that can be allocated from this pool at the same time, or negative for
185      * no limit.
186      */

187     private int maxTotal = GenericObjectPoolConfig.DEFAULT_MAX_TOTAL;
188
189     /**
190      * The maximum number of connections that can remain idle in the pool, without extra ones being destroyed, or
191      * negative for no limit. If maxIdle is set too low on heavily loaded systems it is possible you will see
192      * connections being closed and almost immediately new connections being opened. This is a result of the active
193      * threads momentarily closing connections faster than they are opening them, causing the number of idle connections
194      * to rise above maxIdle. The best value for maxIdle for heavily loaded system will vary but the default is a good
195      * starting point.
196      */

197     private int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
198
199     /**
200      * The minimum number of active connections that can remain idle in the pool, without extra ones being created when
201      * the evictor runs, or 0 to create none. The pool attempts to ensure that minIdle connections are available when
202      * the idle object evictor runs. The value of this property has no effect unless
203      * {@link #timeBetweenEvictionRunsMillis} has a positive value.
204      */

205     private int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
206
207     /**
208      * The initial number of connections that are created when the pool is started.
209      */

210     private int initialSize = 0;
211
212     /**
213      * The maximum number of milliseconds that the pool will wait (when there are no available connections) for a
214      * connection to be returned before throwing an exception, or <= 0 to wait indefinitely.
215      */

216     private long maxWaitMillis = BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS;
217
218     /**
219      * Prepared statement pooling for this pool. When this property is set to <code>true</code> both PreparedStatements
220      * and CallableStatements are pooled.
221      */

222     private boolean poolPreparedStatements = false;
223
224     /**
225      * <p>
226      * The maximum number of open statements that can be allocated from the statement pool at the same time, or negative
227      * for no limit. Since a connection usually only uses one or two statements at a time, this is mostly used to help
228      * detect resource leaks.
229      * </p>
230      * <p>
231      * Note: As of version 1.3, CallableStatements (those produced by {@link Connection#prepareCall}) are pooled along
232      * with PreparedStatements (produced by {@link Connection#prepareStatement}) and
233      * <code>maxOpenPreparedStatements</code> limits the total number of prepared or callable statements that may be in
234      * use at a given time.
235      * </p>
236      */

237     private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL;
238
239     /**
240      * The indication of whether objects will be validated as soon as they have been created by the pool. If the object
241      * fails to validate, the borrow operation that triggered the creation will fail.
242      */

243     private boolean testOnCreate = false;
244
245     /**
246      * The indication of whether objects will be validated before being borrowed from the pool. If the object fails to
247      * validate, it will be dropped from the pool, and we will attempt to borrow another.
248      */

249     private boolean testOnBorrow = true;
250
251     /**
252      * The indication of whether objects will be validated before being returned to the pool.
253      */

254     private boolean testOnReturn = false;
255
256     /**
257      * The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no idle
258      * object evictor thread will be run.
259      */

260     private long timeBetweenEvictionRunsMillis = BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
261
262     /**
263      * The number of objects to examine during each run of the idle object evictor thread (if any).
264      */

265     private int numTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
266
267     /**
268      * The minimum amount of time an object may sit idle in the pool before it is eligible for eviction by the idle
269      * object evictor (if any).
270      */

271     private long minEvictableIdleTimeMillis = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
272
273     /**
274      * The minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the idle
275      * object evictor, with the extra condition that at least "minIdle" connections remain in the pool. Note that
276      * {@code minEvictableIdleTimeMillis} takes precedence over this parameter. See
277      * {@link #getSoftMinEvictableIdleTimeMillis()}.
278      */

279     private long softMinEvictableIdleTimeMillis = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
280
281     private String evictionPolicyClassName = BaseObjectPoolConfig.DEFAULT_EVICTION_POLICY_CLASS_NAME;
282
283     /**
284      * The indication of whether objects will be validated by the idle object evictor (if any). If an object fails to
285      * validate, it will be dropped from the pool.
286      */

287     private boolean testWhileIdle = false;
288
289     /**
290      * The connection password to be passed to our JDBC driver to establish a connection.
291      */

292     private volatile String password;
293
294     /**
295      * The connection URL to be passed to our JDBC driver to establish a connection.
296      */

297     private String url;
298
299     /**
300      * The connection user name to be passed to our JDBC driver to establish a connection.
301      */

302     private String userName;
303
304     /**
305      * The SQL query that will be used to validate connections from this pool before returning them to the caller. If
306      * specified, this query <strong>MUST</strong> be an SQL SELECT statement that returns at least one row. If not
307      * specified, {@link Connection#isValid(int)} will be used to validate connections.
308      */

309     private volatile String validationQuery;
310
311     /**
312      * Timeout in seconds before connection validation queries fail.
313      */

314     private volatile int validationQueryTimeoutSeconds = -1;
315
316     /**
317      * The fully qualified Java class name of a {@link ConnectionFactory} implementation.
318      */

319     private String connectionFactoryClassName;
320
321     /**
322      * These SQL statements run once after a Connection is created.
323      * <p>
324      * This property can be used for example to run ALTER SESSION SET NLS_SORT=XCYECH in an Oracle Database only once
325      * after connection creation.
326      * </p>
327      */

328     private volatile List<String> connectionInitSqls;
329
330     /**
331      * Controls access to the underlying connection.
332      */

333     private boolean accessToUnderlyingConnectionAllowed = false;
334
335     private long maxConnLifetimeMillis = -1;
336
337     private boolean logExpiredConnections = true;
338
339     private String jmxName;
340
341     private boolean autoCommitOnReturn = true;
342
343     private boolean rollbackOnReturn = true;
344
345     private volatile Set<String> disconnectionSqlCodes;
346
347     private boolean fastFailValidation;
348
349     /**
350      * The object pool that internally manages our connections.
351      */

352     private volatile GenericObjectPool<PoolableConnection> connectionPool;
353
354     /**
355      * The connection properties that will be sent to our JDBC driver when establishing new connections.
356      * <strong>NOTE</strong> - The "user" and "password" properties will be passed explicitly, so they do not need to be
357      * included here.
358      */

359     private Properties connectionProperties = new Properties();
360
361     /**
362      * The data source we will use to manage connections. This object should be acquired <strong>ONLY</strong> by calls
363      * to the <code>createDataSource()</code> method.
364      */

365     private volatile DataSource dataSource;
366
367     /**
368      * The PrintWriter to which log messages should be directed.
369      */

370     private volatile PrintWriter logWriter = new PrintWriter(
371             new OutputStreamWriter(System.out, StandardCharsets.UTF_8));
372
373     private AbandonedConfig abandonedConfig;
374
375     private boolean closed;
376
377     /**
378      * Actual name under which this component has been registered.
379      */

380     private ObjectNameWrapper registeredJmxObjectName;
381
382     /**
383      * Adds a custom connection property to the set that will be passed to our JDBC driver. This <strong>MUST</strong>
384      * be called before the first connection is retrieved (along with all the other configuration property setters).
385      * Calls to this method after the connection pool has been initialized have no effect.
386      *
387      * @param name  Name of the custom connection property
388      * @param value Value of the custom connection property
389      */

390     public void addConnectionProperty(final String name, final String value) {
391         connectionProperties.put(name, value);
392     }
393
394     /**
395      * <p>
396      * Closes and releases all idle connections that are currently stored in the connection pool associated with this
397      * data source.
398      * </p>
399      * <p>
400      * Connections that are checked out to clients when this method is invoked are not affected. When client
401      * applications subsequently invoke {@link Connection#close()} to return these connections to the pool, the
402      * underlying JDBC connections are closed.
403      * </p>
404      * <p>
405      * Attempts to acquire connections using {@link #getConnection()} after this method has been invoked result in
406      * SQLExceptions.
407      * </p>
408      * <p>
409      * This method is idempotent - i.e., closing an already closed BasicDataSource has no effect and does not generate
410      * exceptions.
411      * </p>
412      *
413      * @throws SQLException if an error occurs closing idle connections
414      */

415     @Override
416     public synchronized void close() throws SQLException {
417         if (registeredJmxObjectName != null) {
418             registeredJmxObjectName.unregisterMBean();
419             registeredJmxObjectName = null;
420         }
421         closed = true;
422         final GenericObjectPool<?> oldPool = connectionPool;
423         connectionPool = null;
424         dataSource = null;
425         try {
426             if (oldPool != null) {
427                 oldPool.close();
428             }
429         } catch (final RuntimeException e) {
430             throw e;
431         } catch (final Exception e) {
432             throw new SQLException(Utils.getMessage("pool.close.fail"), e);
433         }
434     }
435
436     /**
437      * Closes the connection pool, silently swallowing any exception that occurs.
438      */

439     private void closeConnectionPool() {
440         final GenericObjectPool<?> oldPool = connectionPool;
441         connectionPool = null;
442         try {
443             if (oldPool != null) {
444                 oldPool.close();
445             }
446         } catch (final Exception e) {
447             /* Ignore */
448         }
449     }
450
451     /**
452      * Creates a JDBC connection factory for this datasource. The JDBC driver is loaded using the following algorithm:
453      * <ol>
454      * <li>If a Driver instance has been specified via {@link #setDriver(Driver)} use it</li>
455      * <li>If no Driver instance was specified and {@link #driverClassName} is specified that class is loaded using the
456      * {@link ClassLoader} of this class or, if {@link #driverClassLoader} is set, {@link #driverClassName} is loaded
457      * with the specified {@link ClassLoader}.</li>
458      * <li>If {@link #driverClassName} is specified and the previous attempt fails, the class is loaded using the
459      * context class loader of the current thread.</li>
460      * <li>If a driver still isn't loaded one is loaded via the {@link DriverManager} using the specified {@link #url}.
461      * </ol>
462      * <p>
463      * This method exists so subclasses can replace the implementation class.
464      * </p>
465      *
466      * @return A new connection factory.
467      *
468      * @throws SQLException If the connection factort cannot be created
469      */

470     protected ConnectionFactory createConnectionFactory() throws SQLException {
471         // Load the JDBC driver class
472         return ConnectionFactoryFactory.createConnectionFactory(this, DriverFactory.createDriver(this));
473     }
474
475     /**
476      * Creates a connection pool for this datasource. This method only exists so subclasses can replace the
477      * implementation class.
478      * <p>
479      * This implementation configures all pool properties other than timeBetweenEvictionRunsMillis. Setting that
480      * property is deferred to {@link #startPoolMaintenance()}, since setting timeBetweenEvictionRunsMillis to a
481      * positive value causes {@link GenericObjectPool}'s eviction timer to be started.
482      * </p>
483      *
484      * @param factory The factory to use to create new connections for this pool.
485      */

486     protected void createConnectionPool(final PoolableConnectionFactory factory) {
487         // Create an object pool to contain our active connections
488         final GenericObjectPoolConfig<PoolableConnection> config = new GenericObjectPoolConfig<>();
489         updateJmxName(config);
490         // Disable JMX on the underlying pool if the DS is not registered:
491         config.setJmxEnabled(registeredJmxObjectName != null);
492         final GenericObjectPool<PoolableConnection> gop = createObjectPool(factory, config, abandonedConfig);
493         gop.setMaxTotal(maxTotal);
494         gop.setMaxIdle(maxIdle);
495         gop.setMinIdle(minIdle);
496         gop.setMaxWaitMillis(maxWaitMillis);
497         gop.setTestOnCreate(testOnCreate);
498         gop.setTestOnBorrow(testOnBorrow);
499         gop.setTestOnReturn(testOnReturn);
500         gop.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
501         gop.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
502         gop.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis);
503         gop.setTestWhileIdle(testWhileIdle);
504         gop.setLifo(lifo);
505         gop.setSwallowedExceptionListener(new SwallowedExceptionLogger(log, logExpiredConnections));
506         gop.setEvictionPolicyClassName(evictionPolicyClassName);
507         factory.setPool(gop);
508         connectionPool = gop;
509     }
510
511     /**
512      * <p>
513      * Creates (if necessary) and return the internal data source we are using to manage our connections.
514      * </p>
515      *
516      * @return The current internal DataSource or a newly created instance if it has not yet been created.
517      * @throws SQLException if the object pool cannot be created.
518      */

519     protected DataSource createDataSource() throws SQLException {
520         if (closed) {
521             throw new SQLException("Data source is closed");
522         }
523
524         // Return the pool if we have already created it
525         // This is double-checked locking. This is safe since dataSource is
526         // volatile and the code is targeted at Java 5 onwards.
527         if (dataSource != null) {
528             return dataSource;
529         }
530         synchronized (this) {
531             if (dataSource != null) {
532                 return dataSource;
533             }
534
535             jmxRegister();
536
537             // create factory which returns raw physical connections
538             final ConnectionFactory driverConnectionFactory = createConnectionFactory();
539
540             // Set up the poolable connection factory
541             boolean success = false;
542             PoolableConnectionFactory poolableConnectionFactory;
543             try {
544                 poolableConnectionFactory = createPoolableConnectionFactory(driverConnectionFactory);
545                 poolableConnectionFactory.setPoolStatements(poolPreparedStatements);
546                 poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements);
547                 success = true;
548             } catch (final SQLException se) {
549                 throw se;
550             } catch (final RuntimeException rte) {
551                 throw rte;
552             } catch (final Exception ex) {
553                 throw new SQLException("Error creating connection factory", ex);
554             }
555
556             if (success) {
557                 // create a pool for our connections
558                 createConnectionPool(poolableConnectionFactory);
559             }
560
561             // Create the pooling data source to manage connections
562             DataSource newDataSource;
563             success = false;
564             try {
565                 newDataSource = createDataSourceInstance();
566                 newDataSource.setLogWriter(logWriter);
567                 success = true;
568             } catch (final SQLException se) {
569                 throw se;
570             } catch (final RuntimeException rte) {
571                 throw rte;
572             } catch (final Exception ex) {
573                 throw new SQLException("Error creating datasource", ex);
574             } finally {
575                 if (!success) {
576                     closeConnectionPool();
577                 }
578             }
579
580             // If initialSize > 0, preload the pool
581             try {
582                 for (int i = 0; i < initialSize; i++) {
583                     connectionPool.addObject();
584                 }
585             } catch (final Exception e) {
586                 closeConnectionPool();
587                 throw new SQLException("Error preloading the connection pool", e);
588             }
589
590             // If timeBetweenEvictionRunsMillis > 0, start the pool's evictor
591             // task
592             startPoolMaintenance();
593
594             dataSource = newDataSource;
595             return dataSource;
596         }
597     }
598
599     /**
600      * Creates the actual data source instance. This method only exists so that subclasses can replace the
601      * implementation class.
602      *
603      * @throws SQLException if unable to create a datasource instance
604      *
605      * @return A new DataSource instance
606      */

607     protected DataSource createDataSourceInstance() throws SQLException {
608         final PoolingDataSource<PoolableConnection> pds = new PoolingDataSource<>(connectionPool);
609         pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
610         return pds;
611     }
612
613     /**
614      * Creates an object pool used to provide pooling support for {@link Connection JDBC connections}.
615      *
616      * @param factory         the object factory
617      * @param poolConfig      the object pool configuration
618      * @param abandonedConfig the abandoned objects configuration
619      * @return a non-null instance
620      */

621     protected GenericObjectPool<PoolableConnection> createObjectPool(final PoolableConnectionFactory factory,
622             final GenericObjectPoolConfig<PoolableConnection> poolConfig, final AbandonedConfig abandonedConfig) {
623         GenericObjectPool<PoolableConnection> gop;
624         if (abandonedConfig != null && (abandonedConfig.getRemoveAbandonedOnBorrow()
625                 || abandonedConfig.getRemoveAbandonedOnMaintenance())) {
626             gop = new GenericObjectPool<>(factory, poolConfig, abandonedConfig);
627         } else {
628             gop = new GenericObjectPool<>(factory, poolConfig);
629         }
630         return gop;
631     }
632
633     /**
634      * Creates the PoolableConnectionFactory and attaches it to the connection pool. This method only exists so
635      * subclasses can replace the default implementation.
636      *
637      * @param driverConnectionFactory JDBC connection factory
638      * @throws SQLException if an error occurs creating the PoolableConnectionFactory
639      *
640      * @return A new PoolableConnectionFactory configured with the current configuration of this BasicDataSource
641      */

642     protected PoolableConnectionFactory createPoolableConnectionFactory(final ConnectionFactory driverConnectionFactory)
643             throws SQLException {
644         PoolableConnectionFactory connectionFactory = null;
645         try {
646             connectionFactory = new PoolableConnectionFactory(driverConnectionFactory,
647                     ObjectNameWrapper.unwrap(registeredJmxObjectName));
648             connectionFactory.setValidationQuery(validationQuery);
649             connectionFactory.setValidationQueryTimeout(validationQueryTimeoutSeconds);
650             connectionFactory.setConnectionInitSql(connectionInitSqls);
651             connectionFactory.setDefaultReadOnly(defaultReadOnly);
652             connectionFactory.setDefaultAutoCommit(defaultAutoCommit);
653             connectionFactory.setDefaultTransactionIsolation(defaultTransactionIsolation);
654             connectionFactory.setDefaultCatalog(defaultCatalog);
655             connectionFactory.setDefaultSchema(defaultSchema);
656             connectionFactory.setCacheState(cacheState);
657             connectionFactory.setPoolStatements(poolPreparedStatements);
658             connectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements);
659             connectionFactory.setMaxConnLifetimeMillis(maxConnLifetimeMillis);
660             connectionFactory.setRollbackOnReturn(getRollbackOnReturn());
661             connectionFactory.setAutoCommitOnReturn(getAutoCommitOnReturn());
662             connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeout());
663             connectionFactory.setFastFailValidation(fastFailValidation);
664             connectionFactory.setDisconnectionSqlCodes(disconnectionSqlCodes);
665             validateConnectionFactory(connectionFactory);
666         } catch (final RuntimeException e) {
667             throw e;
668         } catch (final Exception e) {
669             throw new SQLException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e);
670         }
671         return connectionFactory;
672     }
673
674     /**
675      * Manually evicts idle connections
676      *
677      * @throws Exception when there is a problem evicting idle objects.
678      */

679     public void evict() throws Exception {
680         if (connectionPool != null) {
681             connectionPool.evict();
682         }
683     }
684
685     /**
686      * Gets the print writer used by this configuration to log information on abandoned objects.
687      *
688      * @return The print writer used by this configuration to log information on abandoned objects.
689      */

690     public PrintWriter getAbandonedLogWriter() {
691         if (abandonedConfig != null) {
692             return abandonedConfig.getLogWriter();
693         }
694         return null;
695     }
696
697     /**
698      * If the connection pool implements {@link org.apache.tomcat.dbcp.pool2.UsageTracking UsageTracking}, should the
699      * connection pool record a stack trace every time a method is called on a pooled connection and retain the most
700      * recent stack trace to aid debugging of abandoned connections?
701      *
702      * @return <code>true</code> if usage tracking is enabled
703      */

704     @Override
705     public boolean getAbandonedUsageTracking() {
706         if (abandonedConfig != null) {
707             return abandonedConfig.getUseUsageTracking();
708         }
709         return false;
710     }
711
712     /**
713      * Returns the value of the flag that controls whether or not connections being returned to the pool will be checked
714      * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
715      * setting is {@code false} when the connection is returned. It is <code>true</code> by default.
716      *
717      * @return Whether or not connections being returned to the pool will be checked and configured with auto-commit.
718      */

719     public boolean getAutoCommitOnReturn() {
720         return autoCommitOnReturn;
721     }
722
723     /**
724      * Returns the state caching flag.
725      *
726      * @return the state caching flag
727      */

728     @Override
729     public boolean getCacheState() {
730         return cacheState;
731     }
732
733     /**
734      * Creates (if necessary) and return a connection to the database.
735      *
736      * @throws SQLException if a database access error occurs
737      * @return a database connection
738      */

739     @Override
740     public Connection getConnection() throws SQLException {
741         if (Utils.IS_SECURITY_ENABLED) {
742             final PrivilegedExceptionAction<Connection> action = new PaGetConnection();
743             try {
744                 return AccessController.doPrivileged(action);
745             } catch (final PrivilegedActionException e) {
746                 final Throwable cause = e.getCause();
747                 if (cause instanceof SQLException) {
748                     throw (SQLException) cause;
749                 }
750                 throw new SQLException(e);
751             }
752         }
753         return createDataSource().getConnection();
754     }
755
756     /**
757      * <strong>BasicDataSource does NOT support this method.</strong>
758      *
759      * @param user Database user on whose behalf the Connection is being made
760      * @param pass The database user's password
761      *
762      * @throws UnsupportedOperationException always thrown.
763      * @throws SQLException                  if a database access error occurs
764      * @return nothing - always throws UnsupportedOperationException
765      */

766     @Override
767     public Connection getConnection(final String user, final String pass) throws SQLException {
768         // This method isn't supported by the PoolingDataSource returned by the
769         // createDataSource
770         throw new UnsupportedOperationException("Not supported by BasicDataSource");
771     }
772
773     /**
774      * Returns the ConnectionFactoryClassName that has been configured for use by this pool.
775      * <p>
776      * Note: This getter only returns the last value set by a call to {@link #setConnectionFactoryClassName(String)}.
777      * </p>
778      *
779      * @return the ConnectionFactoryClassName that has been configured for use by this pool.
780      * @since 2.7.0
781      */

782     public String getConnectionFactoryClassName() {
783         return this.connectionFactoryClassName;
784     }
785
786     /**
787      * Returns the list of SQL statements executed when a physical connection is first created. Returns an empty list if
788      * there are no initialization statements configured.
789      *
790      * @return initialization SQL statements
791      */

792     public List<String> getConnectionInitSqls() {
793         final List<String> result = connectionInitSqls;
794         if (result == null) {
795             return Collections.emptyList();
796         }
797         return result;
798     }
799
800     /**
801      * Provides the same data as {@link #getConnectionInitSqls()} but in an array so it is accessible via JMX.
802      */

803     @Override
804     public String[] getConnectionInitSqlsAsArray() {
805         final Collection<String> result = getConnectionInitSqls();
806         return result.toArray(new String[result.size()]);
807     }
808
809     protected GenericObjectPool<PoolableConnection> getConnectionPool() {
810         return connectionPool;
811     }
812
813     Properties getConnectionProperties() {
814         return connectionProperties;
815     }
816
817     /**
818      * Returns the default auto-commit property.
819      *
820      * @return true if default auto-commit is enabled
821      */

822     @Override
823     public Boolean getDefaultAutoCommit() {
824         return defaultAutoCommit;
825     }
826
827     /**
828      * Returns the default catalog.
829      *
830      * @return the default catalog
831      */

832     @Override
833     public String getDefaultCatalog() {
834         return this.defaultCatalog;
835     }
836
837     /**
838      * Gets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
839      * connection. <code>null</code> means that the driver default will be used.
840      *
841      * @return The default query timeout in seconds.
842      */

843     public Integer getDefaultQueryTimeout() {
844         return defaultQueryTimeoutSeconds;
845     }
846
847     /**
848      * Returns the default readOnly property.
849      *
850      * @return true if connections are readOnly by default
851      */

852     @Override
853     public Boolean getDefaultReadOnly() {
854         return defaultReadOnly;
855     }
856
857     /**
858      * Returns the default schema.
859      *
860      * @return the default schema.
861      * @since 2.5.0
862      */

863     @Override
864     public String getDefaultSchema() {
865         return this.defaultSchema;
866     }
867
868     /**
869      * Returns the default transaction isolation state of returned connections.
870      *
871      * @return the default value for transaction isolation state
872      * @see Connection#getTransactionIsolation
873      */

874     @Override
875     public int getDefaultTransactionIsolation() {
876         return this.defaultTransactionIsolation;
877     }
878
879     /**
880      * Returns the set of SQL_STATE codes considered to signal fatal conditions.
881      *
882      * @return fatal disconnection state codes
883      * @see #setDisconnectionSqlCodes(Collection)
884      * @since 2.1
885      */

886     public Set<String> getDisconnectionSqlCodes() {
887         final Set<String> result = disconnectionSqlCodes;
888         if (result == null) {
889             return Collections.emptySet();
890         }
891         return result;
892     }
893
894     /**
895      * Provides the same data as {@link #getDisconnectionSqlCodes} but in an array so it is accessible via JMX.
896      *
897      * @since 2.1
898      */

899     @Override
900     public String[] getDisconnectionSqlCodesAsArray() {
901         final Collection<String> result = getDisconnectionSqlCodes();
902         return result.toArray(new String[result.size()]);
903     }
904
905     /**
906      * Returns the JDBC Driver that has been configured for use by this pool.
907      * <p>
908      * Note: This getter only returns the last value set by a call to {@link #setDriver(Driver)}. It does not return any
909      * driver instance that may have been created from the value set via {@link #setDriverClassName(String)}.
910      * </p>
911      *
912      * @return the JDBC Driver that has been configured for use by this pool
913      */

914     public synchronized Driver getDriver() {
915         return driver;
916     }
917
918     /**
919      * Returns the class loader specified for loading the JDBC driver. Returns <code>null</code> if no class loader has
920      * been explicitly specified.
921      * <p>
922      * Note: This getter only returns the last value set by a call to {@link #setDriverClassLoader(ClassLoader)}. It
923      * does not return the class loader of any driver that may have been set via {@link #setDriver(Driver)}.
924      * </p>
925      *
926      * @return The class loader specified for loading the JDBC driver.
927      */

928     public synchronized ClassLoader getDriverClassLoader() {
929         return this.driverClassLoader;
930     }
931
932     /**
933      * Returns the JDBC driver class name.
934      * <p>
935      * Note: This getter only returns the last value set by a call to {@link #setDriverClassName(String)}. It does not
936      * return the class name of any driver that may have been set via {@link #setDriver(Driver)}.
937      * </p>
938      *
939      * @return the JDBC driver class name
940      */

941     @Override
942     public synchronized String getDriverClassName() {
943         return this.driverClassName;
944     }
945
946     /**
947      * Returns the value of the flag that controls whether or not connections being returned to the pool will be checked
948      * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
949      * setting is {@code false} when the connection is returned. It is <code>true</code> by default.
950      *
951      * @return Whether or not connections being returned to the pool will be checked and configured with auto-commit.
952      * @deprecated Use {@link #getAutoCommitOnReturn()}.
953      */

954     @Deprecated
955     public boolean getEnableAutoCommitOnReturn() {
956         return autoCommitOnReturn;
957     }
958
959     /**
960      * Gets the EvictionPolicy implementation in use with this connection pool.
961      *
962      * @return The EvictionPolicy implementation in use with this connection pool.
963      */

964     public synchronized String getEvictionPolicyClassName() {
965         return evictionPolicyClassName;
966     }
967
968     /**
969      * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with
970      * SQL_STATE indicating fatal disconnection errors.
971      *
972      * @return true if connections created by this datasource will fast fail validation.
973      * @see #setDisconnectionSqlCodes(Collection)
974      * @since 2.1
975      */

976     @Override
977     public boolean getFastFailValidation() {
978         return fastFailValidation;
979     }
980
981     /**
982      * Returns the initial size of the connection pool.
983      *
984      * @return the number of connections created when the pool is initialized
985      */

986     @Override
987     public synchronized int getInitialSize() {
988         return this.initialSize;
989     }
990
991     /**
992      * Returns the JMX name that has been requested for this DataSource. If the requested name is not valid, an
993      * alternative may be chosen.
994      *
995      * @return The JMX name that has been requested for this DataSource.
996      */

997     public String getJmxName() {
998         return jmxName;
999     }
1000
1001     /**
1002      * Returns the LIFO property.
1003      *
1004      * @return true if connection pool behaves as a LIFO queue.
1005      */

1006     @Override
1007     public synchronized boolean getLifo() {
1008         return this.lifo;
1009     }
1010
1011     /**
1012      * <p>
1013      * Flag to log stack traces for application code which abandoned a Statement or Connection.
1014      * </p>
1015      * <p>
1016      * Defaults to false.
1017      * </p>
1018      * <p>
1019      * Logging of abandoned Statements and Connections adds overhead for every Connection open or new Statement because
1020      * a stack trace has to be generated.
1021      * </p>
1022      */

1023     @Override
1024     public boolean getLogAbandoned() {
1025         if (abandonedConfig != null) {
1026             return abandonedConfig.getLogAbandoned();
1027         }
1028         return false;
1029     }
1030
1031     /**
1032      * When {@link #getMaxConnLifetimeMillis()} is set to limit connection lifetime, this property determines whether or
1033      * not log messages are generated when the pool closes connections due to maximum lifetime exceeded.
1034      *
1035      * @since 2.1
1036      */

1037     @Override
1038     public boolean getLogExpiredConnections() {
1039         return logExpiredConnections;
1040     }
1041
1042     /**
1043      * <strong>BasicDataSource does NOT support this method.</strong>
1044      *
1045      * <p>
1046      * Returns the login timeout (in seconds) for connecting to the database.
1047      * </p>
1048      * <p>
1049      * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool.
1050      * </p>
1051      *
1052      * @throws SQLException                  if a database access error occurs
1053      * @throws UnsupportedOperationException If the DataSource implementation does not support the login timeout
1054      *                                       feature.
1055      * @return login timeout in seconds
1056      */

1057     @Override
1058     public int getLoginTimeout() throws SQLException {
1059         // This method isn't supported by the PoolingDataSource returned by the
1060         // createDataSource
1061         throw new UnsupportedOperationException("Not supported by BasicDataSource");
1062     }
1063
1064     /**
1065      * <p>
1066      * Returns the log writer being used by this data source.
1067      * </p>
1068      * <p>
1069      * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool.
1070      * </p>
1071      *
1072      * @throws SQLException if a database access error occurs
1073      * @return log writer in use
1074      */

1075     @Override
1076     public PrintWriter getLogWriter() throws SQLException {
1077         return createDataSource().getLogWriter();
1078     }
1079
1080     /**
1081      * Returns the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an
1082      * infinite lifetime.
1083      */

1084     @Override
1085     public long getMaxConnLifetimeMillis() {
1086         return maxConnLifetimeMillis;
1087     }
1088
1089     /**
1090      * <p>
1091      * Returns the maximum number of connections that can remain idle in the pool. Excess idle connections are destroyed
1092      * on return to the pool.
1093      * </p>
1094      * <p>
1095      * A negative value indicates that there is no limit
1096      * </p>
1097      *
1098      * @return the maximum number of idle connections
1099      */

1100     @Override
1101     public synchronized int getMaxIdle() {
1102         return this.maxIdle;
1103     }
1104
1105     /**
1106      * Gets the value of the <code>maxOpenPreparedStatements</code> property.
1107      *
1108      * @return the maximum number of open statements
1109      */

1110     @Override
1111     public synchronized int getMaxOpenPreparedStatements() {
1112         return this.maxOpenPreparedStatements;
1113     }
1114
1115     /**
1116      * <p>
1117      * Returns the maximum number of active connections that can be allocated at the same time.
1118      * </p>
1119      * <p>
1120      * A negative number means that there is no limit.
1121      * </p>
1122      *
1123      * @return the maximum number of active connections
1124      */

1125     @Override
1126     public synchronized int getMaxTotal() {
1127         return this.maxTotal;
1128     }
1129
1130     /**
1131      * Returns the maximum number of milliseconds that the pool will wait for a connection to be returned before
1132      * throwing an exception. A value less than or equal to zero means the pool is set to wait indefinitely.
1133      *
1134      * @return the maxWaitMillis property value
1135      */

1136     @Override
1137     public synchronized long getMaxWaitMillis() {
1138         return this.maxWaitMillis;
1139     }
1140
1141     /**
1142      * Returns the {@link #minEvictableIdleTimeMillis} property.
1143      *
1144      * @return the value of the {@link #minEvictableIdleTimeMillis} property
1145      * @see #minEvictableIdleTimeMillis
1146      */

1147     @Override
1148     public synchronized long getMinEvictableIdleTimeMillis() {
1149         return this.minEvictableIdleTimeMillis;
1150     }
1151
1152     /**
1153      * Returns the minimum number of idle connections in the pool. The pool attempts to ensure that minIdle connections
1154      * are available when the idle object evictor runs. The value of this property has no effect unless
1155      * {@link #timeBetweenEvictionRunsMillis} has a positive value.
1156      *
1157      * @return the minimum number of idle connections
1158      * @see GenericObjectPool#getMinIdle()
1159      */

1160     @Override
1161     public synchronized int getMinIdle() {
1162         return this.minIdle;
1163     }
1164
1165     /**
1166      * [Read Only] The current number of active connections that have been allocated from this data source.
1167      *
1168      * @return the current number of active connections
1169      */

1170     @Override
1171     public int getNumActive() {
1172         // Copy reference to avoid NPE if close happens after null check
1173         final GenericObjectPool<PoolableConnection> pool = connectionPool;
1174         if (pool != null) {
1175             return pool.getNumActive();
1176         }
1177         return 0;
1178     }
1179
1180     /**
1181      * [Read Only] The current number of idle connections that are waiting to be allocated from this data source.
1182      *
1183      * @return the current number of idle connections
1184      */

1185     @Override
1186     public int getNumIdle() {
1187         // Copy reference to avoid NPE if close happens after null check
1188         final GenericObjectPool<PoolableConnection> pool = connectionPool;
1189         if (pool != null) {
1190             return pool.getNumIdle();
1191         }
1192         return 0;
1193     }
1194
1195     /**
1196      * Returns the value of the {@link #numTestsPerEvictionRun} property.
1197      *
1198      * @return the number of objects to examine during idle object evictor runs
1199      * @see #numTestsPerEvictionRun
1200      */

1201     @Override
1202     public synchronized int getNumTestsPerEvictionRun() {
1203         return this.numTestsPerEvictionRun;
1204     }
1205
1206     @Override
1207     public Logger getParentLogger() throws SQLFeatureNotSupportedException {
1208         throw new SQLFeatureNotSupportedException();
1209     }
1210
1211     /**
1212      * Returns the password passed to the JDBC driver to establish connections.
1213      *
1214      * @return the connection password
1215      */

1216     @Override
1217     public String getPassword() {
1218         return this.password;
1219     }
1220
1221     protected ObjectName getRegisteredJmxName() {
1222         return ObjectNameWrapper.unwrap(registeredJmxObjectName);
1223     }
1224
1225     /**
1226      * <p>
1227      * Flag to remove abandoned connections if they exceed the removeAbandonedTimeout when borrowObject is invoked.
1228      * </p>
1229      * <p>
1230      * The default value is false.
1231      * </p>
1232      * <p>
1233      * If set to true a connection is considered abandoned and eligible for removal if it has not been used for more
1234      * than {@link #getRemoveAbandonedTimeout() removeAbandonedTimeout} seconds.
1235      * </p>
1236      * <p>
1237      * Abandoned connections are identified and removed when {@link #getConnection()} is invoked and all of the
1238      * following conditions hold:
1239      * </p>
1240      * <ul>
1241      * <li>{@link #getRemoveAbandonedOnBorrow()}</li>
1242      * <li>{@link #getNumActive()} &gt; {@link #getMaxTotal()} - 3</li>
1243      * <li>{@link #getNumIdle()} &lt; 2</li>
1244      * </ul>
1245      *
1246      * @see #getRemoveAbandonedTimeout()
1247      */

1248     @Override
1249     public boolean getRemoveAbandonedOnBorrow() {
1250         if (abandonedConfig != null) {
1251             return abandonedConfig.getRemoveAbandonedOnBorrow();
1252         }
1253         return false;
1254     }
1255
1256     /**
1257      * <p>
1258      * Flag to remove abandoned connections if they exceed the removeAbandonedTimeout during pool maintenance.
1259      * </p>
1260      *
1261      * <p>
1262      * The default value is false.
1263      * </p>
1264      *
1265      * <p>
1266      * If set to true a connection is considered abandoned and eligible for removal if it has not been used for more
1267      * than {@link #getRemoveAbandonedTimeout() removeAbandonedTimeout} seconds.
1268      * </p>
1269      *
1270      * @see #getRemoveAbandonedTimeout()
1271      */

1272     @Override
1273     public boolean getRemoveAbandonedOnMaintenance() {
1274         if (abandonedConfig != null) {
1275             return abandonedConfig.getRemoveAbandonedOnMaintenance();
1276         }
1277         return false;
1278     }
1279
1280     /**
1281      * <p>
1282      * Timeout in seconds before an abandoned connection can be removed.
1283      * </p>
1284      * <p>
1285      * Creating a Statement, PreparedStatement or CallableStatement or using one of these to execute a query (using one
1286      * of the execute methods) resets the lastUsed property of the parent connection.
1287      * </p>
1288      * <p>
1289      * Abandoned connection cleanup happens when:
1290      * </p>
1291      * <ul>
1292      * <li>{@link #getRemoveAbandonedOnBorrow()} or {@link #getRemoveAbandonedOnMaintenance()} = true</li>
1293      * <li>{@link #getNumIdle() numIdle} &lt; 2</li>
1294      * <li>{@link #getNumActive() numActive} &gt; {@link #getMaxTotal() maxTotal} - 3</li>
1295      * </ul>
1296      * <p>
1297      * The default value is 300 seconds.
1298      * </p>
1299      */

1300     @Override
1301     public int getRemoveAbandonedTimeout() {
1302         if (abandonedConfig != null) {
1303             return abandonedConfig.getRemoveAbandonedTimeout();
1304         }
1305         return 300;
1306     }
1307
1308     /**
1309      * Gets the current value of the flag that controls whether a connection will be rolled back when it is returned to
1310      * the pool if auto commit is not enabled and the connection is not read only.
1311      *
1312      * @return whether a connection will be rolled back when it is returned to the pool.
1313      */

1314     public boolean getRollbackOnReturn() {
1315         return rollbackOnReturn;
1316     }
1317
1318     /**
1319      * <p>
1320      * Returns the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by
1321      * the idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool.
1322      * </p>
1323      *
1324      * <p>
1325      * When {@link #getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} is set to a positive value,
1326      * minEvictableIdleTimeMillis is examined first by the idle connection evictor - i.e. when idle connections are
1327      * visited by the evictor, idle time is first compared against {@code minEvictableIdleTimeMillis} (without
1328      * considering the number of idle connections in the pool) and then against {@code softMinEvictableIdleTimeMillis},
1329      * including the {@code minIdle}, constraint.
1330      * </p>
1331      *
1332      * @return minimum amount of time a connection may sit idle in the pool before it is eligible for eviction, assuming
1333      *         there are minIdle idle connections in the pool
1334      */

1335     @Override
1336     public synchronized long getSoftMinEvictableIdleTimeMillis() {
1337         return softMinEvictableIdleTimeMillis;
1338     }
1339
1340     /**
1341      * Returns the {@link #testOnBorrow} property.
1342      *
1343      * @return true if objects are validated before being borrowed from the pool
1344      *
1345      * @see #testOnBorrow
1346      */

1347     @Override
1348     public synchronized boolean getTestOnBorrow() {
1349         return this.testOnBorrow;
1350     }
1351
1352     /**
1353      * Returns the {@link #testOnCreate} property.
1354      *
1355      * @return true if objects are validated immediately after they are created by the pool
1356      * @see #testOnCreate
1357      */

1358     @Override
1359     public synchronized boolean getTestOnCreate() {
1360         return this.testOnCreate;
1361     }
1362
1363     /**
1364      * Returns the value of the {@link #testOnReturn} property.
1365      *
1366      * @return true if objects are validated before being returned to the pool
1367      * @see #testOnReturn
1368      */

1369     public synchronized boolean getTestOnReturn() {
1370         return this.testOnReturn;
1371     }
1372
1373     /**
1374      * Returns the value of the {@link #testWhileIdle} property.
1375      *
1376      * @return true if objects examined by the idle object evictor are validated
1377      * @see #testWhileIdle
1378      */

1379     @Override
1380     public synchronized boolean getTestWhileIdle() {
1381         return this.testWhileIdle;
1382     }
1383
1384     /**
1385      * Returns the value of the {@link #timeBetweenEvictionRunsMillis} property.
1386      *
1387      * @return the time (in milliseconds) between evictor runs
1388      * @see #timeBetweenEvictionRunsMillis
1389      */

1390     @Override
1391     public synchronized long getTimeBetweenEvictionRunsMillis() {
1392         return this.timeBetweenEvictionRunsMillis;
1393     }
1394
1395     /**
1396      * Returns the JDBC connection {@link #url} property.
1397      *
1398      * @return the {@link #url} passed to the JDBC driver to establish connections
1399      */

1400     @Override
1401     public synchronized String getUrl() {
1402         return this.url;
1403     }
1404
1405     /**
1406      * Returns the JDBC connection {@link #userName} property.
1407      *
1408      * @return the {@link #userName} passed to the JDBC driver to establish connections
1409      */

1410     @Override
1411     public String getUsername() {
1412         return this.userName;
1413     }
1414
1415     /**
1416      * Returns the validation query used to validate connections before returning them.
1417      *
1418      * @return the SQL validation query
1419      * @see #validationQuery
1420      */

1421     @Override
1422     public String getValidationQuery() {
1423         return this.validationQuery;
1424     }
1425
1426     /**
1427      * Returns the validation query timeout.
1428      *
1429      * @return the timeout in seconds before connection validation queries fail.
1430      */

1431     @Override
1432     public int getValidationQueryTimeout() {
1433         return validationQueryTimeoutSeconds;
1434     }
1435
1436     /**
1437      * Manually invalidates a connection, effectively requesting the pool to try to close it, remove it from the pool
1438      * and reclaim pool capacity.
1439      *
1440      * @param connection The Connection to invalidate.
1441      *
1442      * @throws IllegalStateException if invalidating the connection failed.
1443      * @since 2.1
1444      */

1445     @SuppressWarnings("resource")
1446     public void invalidateConnection(final Connection connection) throws IllegalStateException {
1447         if (connection == null) {
1448             return;
1449         }
1450         if (connectionPool == null) {
1451             throw new IllegalStateException("Cannot invalidate connection: ConnectionPool is null.");
1452         }
1453
1454         final PoolableConnection poolableConnection;
1455         try {
1456             poolableConnection = connection.unwrap(PoolableConnection.class);
1457             if (poolableConnection == null) {
1458                 throw new IllegalStateException(
1459                         "Cannot invalidate connection: Connection is not a poolable connection.");
1460             }
1461         } catch (final SQLException e) {
1462             throw new IllegalStateException("Cannot invalidate connection: Unwrapping poolable connection failed.", e);
1463         }
1464
1465         try {
1466             connectionPool.invalidateObject(poolableConnection);
1467         } catch (final Exception e) {
1468             throw new IllegalStateException("Invalidating connection threw unexpected exception", e);
1469         }
1470     }
1471
1472     /**
1473      * Returns the value of the accessToUnderlyingConnectionAllowed property.
1474      *
1475      * @return true if access to the underlying connection is allowed, false otherwise.
1476      */

1477     @Override
1478     public synchronized boolean isAccessToUnderlyingConnectionAllowed() {
1479         return this.accessToUnderlyingConnectionAllowed;
1480     }
1481
1482     /**
1483      * If truethis data source is closed and no more connections can be retrieved from this datasource.
1484      *
1485      * @return trueif the data source is closed; false otherwise
1486      */

1487     @Override
1488     public synchronized boolean isClosed() {
1489         return closed;
1490     }
1491
1492     /**
1493      * Delegates in a null-safe manner to {@link String#isEmpty()}.
1494      *
1495      * @param value the string to test, may be null.
1496      * @return boolean false if value is null, otherwise {@link String#isEmpty()}.
1497      */

1498     private boolean isEmpty(String value) {
1499         return value == null ? true : value.trim().isEmpty();
1500     }
1501
1502     /**
1503      * Returns true if we are pooling statements.
1504      *
1505      * @return true if prepared and callable statements are pooled
1506      */

1507     @Override
1508     public synchronized boolean isPoolPreparedStatements() {
1509         return this.poolPreparedStatements;
1510     }
1511
1512     @Override
1513     public boolean isWrapperFor(final Class<?> iface) throws SQLException {
1514         return false;
1515     }
1516
1517     private void jmxRegister() {
1518         // Return immediately if this DataSource has already been registered
1519         if (registeredJmxObjectName != null) {
1520             return;
1521         }
1522         // Return immediately if no JMX name has been specified
1523         final String requestedName = getJmxName();
1524         if (requestedName == null) {
1525             return;
1526         }
1527         try {
1528             ObjectNameWrapper.wrap(requestedName).registerMBean(this);
1529         } catch (final MalformedObjectNameException e) {
1530             log.warn("The requested JMX name [" + requestedName + "] was not valid and will be ignored.");
1531         }
1532     }
1533
1534     protected void log(final String message) {
1535         if (logWriter != null) {
1536             logWriter.println(message);
1537         }
1538     }
1539
1540     /**
1541      * Logs the given throwable.
1542      * @param message TODO
1543      * @param throwable the throwable.
1544      *
1545      * @since 2.7.0
1546      */

1547     protected void log(String message, Throwable throwable) {
1548         if (logWriter != null) {
1549             logWriter.println(message);
1550             throwable.printStackTrace(logWriter);
1551         }
1552     }
1553
1554     @Override
1555     public void postDeregister() {
1556         // NO-OP
1557     }
1558
1559     @Override
1560     public void postRegister(final Boolean registrationDone) {
1561         // NO-OP
1562     }
1563
1564     @Override
1565     public void preDeregister() throws Exception {
1566         // NO-OP
1567     }
1568
1569     @Override
1570     public ObjectName preRegister(final MBeanServer server, final ObjectName objectName) {
1571         final String requestedName = getJmxName();
1572         if (requestedName != null) {
1573             try {
1574                 registeredJmxObjectName = ObjectNameWrapper.wrap(requestedName);
1575             } catch (final MalformedObjectNameException e) {
1576                 log.warn("The requested JMX name [" + requestedName + "] was not valid and will be ignored.");
1577             }
1578         }
1579         if (registeredJmxObjectName == null) {
1580             registeredJmxObjectName = ObjectNameWrapper.wrap(objectName);
1581         }
1582         return ObjectNameWrapper.unwrap(registeredJmxObjectName);
1583     }
1584
1585     /**
1586      * Removes a custom connection property.
1587      *
1588      * @param name Name of the custom connection property to remove
1589      * @see #addConnectionProperty(String, String)
1590      */

1591     public void removeConnectionProperty(final String name) {
1592         connectionProperties.remove(name);
1593     }
1594
1595     /**
1596      * Sets the print writer to be used by this configuration to log information on abandoned objects.
1597      *
1598      * @param logWriter The new log writer
1599      */

1600     public void setAbandonedLogWriter(final PrintWriter logWriter) {
1601         if (abandonedConfig == null) {
1602             abandonedConfig = new AbandonedConfig();
1603         }
1604         abandonedConfig.setLogWriter(logWriter);
1605         final GenericObjectPool<?> gop = this.connectionPool;
1606         if (gop != null) {
1607             gop.setAbandonedConfig(abandonedConfig);
1608         }
1609     }
1610
1611     /**
1612      * If the connection pool implements {@link org.apache.tomcat.dbcp.pool2.UsageTracking UsageTracking}, configure whether
1613      * the connection pool should record a stack trace every time a method is called on a pooled connection and retain
1614      * the most recent stack trace to aid debugging of abandoned connections.
1615      *
1616      * @param usageTracking A value of <code>true</code> will enable the recording of a stack trace on every use of a
1617      *                      pooled connection
1618      */

1619     public void setAbandonedUsageTracking(final boolean usageTracking) {
1620         if (abandonedConfig == null) {
1621             abandonedConfig = new AbandonedConfig();
1622         }
1623         abandonedConfig.setUseUsageTracking(usageTracking);
1624         final GenericObjectPool<?> gop = this.connectionPool;
1625         if (gop != null) {
1626             gop.setAbandonedConfig(abandonedConfig);
1627         }
1628     }
1629
1630     /**
1631      * <p>
1632      * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to
1633      * the underlying connection. (Default: false)
1634      * </p>
1635      * <p>
1636      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
1637      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
1638      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
1639      * </p>
1640      *
1641      * @param allow Access to the underlying connection is granted when true.
1642      */

1643     public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) {
1644         this.accessToUnderlyingConnectionAllowed = allow;
1645     }
1646
1647     /**
1648      * Sets the value of the flag that controls whether or not connections being returned to the pool will be checked
1649      * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
1650      * setting is {@code false} when the connection is returned. It is <code>true</code> by default.
1651      *
1652      * @param autoCommitOnReturn Whether or not connections being returned to the pool will be checked and configured
1653      *                           with auto-commit.
1654      * @since 2.6.0
1655      */

1656     public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) {
1657         this.autoCommitOnReturn = autoCommitOnReturn;
1658     }
1659
1660     // ----------------------------------------------------- DataSource Methods
1661
1662     /**
1663      * Sets the state caching flag.
1664      *
1665      * @param cacheState The new value for the state caching flag
1666      */

1667     public void setCacheState(final boolean cacheState) {
1668         this.cacheState = cacheState;
1669     }
1670
1671     /**
1672      * Sets the ConnectionFactory class name.
1673      *
1674      * @param connectionFactoryClassName A class name.
1675      * @since 2.7.0
1676      */

1677     public void setConnectionFactoryClassName(final String connectionFactoryClassName) {
1678         if (isEmpty(connectionFactoryClassName)) {
1679             this.connectionFactoryClassName = null;
1680         } else {
1681             this.connectionFactoryClassName = connectionFactoryClassName;
1682         }
1683     }
1684
1685     /**
1686      * Sets the list of SQL statements to be executed when a physical connection is first created.
1687      * <p>
1688      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
1689      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
1690      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
1691      * </p>
1692      *
1693      * @param connectionInitSqls Collection of SQL statements to execute on connection creation
1694      */

1695     public void setConnectionInitSqls(final Collection<String> connectionInitSqls) {
1696         if (connectionInitSqls != null && connectionInitSqls.size() > 0) {
1697             ArrayList<String> newVal = null;
1698             for (final String s : connectionInitSqls) {
1699                 if (!isEmpty(s)) {
1700                     if (newVal == null) {
1701                         newVal = new ArrayList<>();
1702                     }
1703                     newVal.add(s);
1704                 }
1705             }
1706             this.connectionInitSqls = newVal;
1707         } else {
1708             this.connectionInitSqls = null;
1709         }
1710     }
1711
1712     /**
1713      * Sets the connection properties passed to driver.connect(...).
1714      * <p>
1715      * Format of the string must be [propertyName=property;]*
1716      * </p>
1717      * <p>
1718      * NOTE - The "user" and "password" properties will be added explicitly, so they do not need to be included here.
1719      * </p>
1720      *
1721      * @param connectionProperties the connection properties used to create new connections
1722      */

1723     public void setConnectionProperties(final String connectionProperties) {
1724         Objects.requireNonNull(connectionProperties, "connectionProperties is null");
1725         final String[] entries = connectionProperties.split(";");
1726         final Properties properties = new Properties();
1727         for (final String entry : entries) {
1728             if (entry.length() > 0) {
1729                 final int index = entry.indexOf('=');
1730                 if (index > 0) {
1731                     final String name = entry.substring(0, index);
1732                     final String value = entry.substring(index + 1);
1733                     properties.setProperty(name, value);
1734                 } else {
1735                     // no value is empty string which is how
1736                     // java.util.Properties works
1737                     properties.setProperty(entry, "");
1738                 }
1739             }
1740         }
1741         this.connectionProperties = properties;
1742     }
1743
1744     /**
1745      * <p>
1746      * Sets default auto-commit state of connections returned by this datasource.
1747      * </p>
1748      * <p>
1749      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
1750      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
1751      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
1752      * </p>
1753      *
1754      * @param defaultAutoCommit default auto-commit value
1755      */

1756     public void setDefaultAutoCommit(final Boolean defaultAutoCommit) {
1757         this.defaultAutoCommit = defaultAutoCommit;
1758     }
1759
1760     /**
1761      * <p>
1762      * Sets the default catalog.
1763      * </p>
1764      * <p>
1765      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
1766      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
1767      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
1768      * </p>
1769      *
1770      * @param defaultCatalog the default catalog
1771      */

1772     public void setDefaultCatalog(final String defaultCatalog) {
1773         if (isEmpty(defaultCatalog)) {
1774             this.defaultCatalog = null;
1775         } else {
1776             this.defaultCatalog = defaultCatalog;
1777         }
1778     }
1779
1780     /**
1781      * Sets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this
1782      * connection. <code>null</code> means that the driver default will be used.
1783      *
1784      * @param defaultQueryTimeoutSeconds The default query timeout in seconds.
1785      */

1786     public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) {
1787         this.defaultQueryTimeoutSeconds = defaultQueryTimeoutSeconds;
1788     }
1789
1790     /**
1791      * <p>
1792      * Sets defaultReadonly property.
1793      * </p>
1794      * <p>
1795      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
1796      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
1797      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
1798      * </p>
1799      *
1800      * @param defaultReadOnly default read-only value
1801      */

1802     public void setDefaultReadOnly(final Boolean defaultReadOnly) {
1803         this.defaultReadOnly = defaultReadOnly;
1804     }
1805
1806     /**
1807      * <p>
1808      * Sets the default schema.
1809      * </p>
1810      * <p>
1811      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
1812      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
1813      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
1814      * </p>
1815      *
1816      * @param defaultSchema the default catalog
1817      * @since 2.5.0
1818      */

1819     public void setDefaultSchema(final String defaultSchema) {
1820         if (isEmpty(defaultSchema)) {
1821             this.defaultSchema = null;
1822         } else {
1823             this.defaultSchema = defaultSchema;
1824         }
1825     }
1826
1827     /**
1828      * <p>
1829      * Sets the default transaction isolation state for returned connections.
1830      * </p>
1831      * <p>
1832      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
1833      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
1834      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
1835      * </p>
1836      *
1837      * @param defaultTransactionIsolation the default transaction isolation state
1838      * @see Connection#getTransactionIsolation
1839      */

1840     public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) {
1841         this.defaultTransactionIsolation = defaultTransactionIsolation;
1842     }
1843
1844     /**
1845      * Sets the SQL_STATE codes considered to signal fatal conditions.
1846      * <p>
1847      * Overrides the defaults in {@link Utils#DISCONNECTION_SQL_CODES} (plus anything starting with
1848      * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #getFastFailValidation()}
1849      * is {@code true}, whenever connections created by this datasource generate exceptions with SQL_STATE codes in this
1850      * list, they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at
1851      * isValid or validation query).
1852      * </p>
1853      * <p>
1854      * If {@link #getFastFailValidation()} is {@code false} setting this property has no effect.
1855      * </p>
1856      * <p>
1857      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
1858      * time one of the following methods is invoked: {@code getConnection, setLogwriter,
1859      * setLoginTimeout, getLoginTimeout, getLogWriter}.
1860      * </p>
1861      *
1862      * @param disconnectionSqlCodes SQL_STATE codes considered to signal fatal conditions
1863      * @since 2.1
1864      */

1865     public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) {
1866         if (disconnectionSqlCodes != null && disconnectionSqlCodes.size() > 0) {
1867             HashSet<String> newVal = null;
1868             for (final String s : disconnectionSqlCodes) {
1869                 if (!isEmpty(s)) {
1870                     if (newVal == null) {
1871                         newVal = new HashSet<>();
1872                     }
1873                     newVal.add(s);
1874                 }
1875             }
1876             this.disconnectionSqlCodes = newVal;
1877         } else {
1878             this.disconnectionSqlCodes = null;
1879         }
1880     }
1881
1882     /**
1883      * Sets the JDBC Driver instance to use for this pool.
1884      * <p>
1885      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
1886      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
1887      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
1888      * </p>
1889      *
1890      * @param driver The JDBC Driver instance to use for this pool.
1891      */

1892     public synchronized void setDriver(final Driver driver) {
1893         this.driver = driver;
1894     }
1895
1896     /**
1897      * <p>
1898      * Sets the class loader to be used to load the JDBC driver.
1899      * </p>
1900      * <p>
1901      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
1902      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
1903      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
1904      * </p>
1905      *
1906      * @param driverClassLoader the class loader with which to load the JDBC driver
1907      */

1908     public synchronized void setDriverClassLoader(final ClassLoader driverClassLoader) {
1909         this.driverClassLoader = driverClassLoader;
1910     }
1911
1912     /**
1913      * <p>
1914      * Sets the JDBC driver class name.
1915      * </p>
1916      * <p>
1917      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
1918      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
1919      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
1920      * </p>
1921      *
1922      * @param driverClassName the class name of the JDBC driver
1923      */

1924     public synchronized void setDriverClassName(final String driverClassName) {
1925         if (isEmpty(driverClassName)) {
1926             this.driverClassName = null;
1927         } else {
1928             this.driverClassName = driverClassName;
1929         }
1930     }
1931
1932     /**
1933      * Sets the value of the flag that controls whether or not connections being returned to the pool will be checked
1934      * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit
1935      * setting is {@code false} when the connection is returned. It is <code>true</code> by default.
1936      *
1937      * @param autoCommitOnReturn Whether or not connections being returned to the pool will be checked and configured
1938      *                           with auto-commit.
1939      * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}.
1940      */

1941     @Deprecated
1942     public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) {
1943         this.autoCommitOnReturn = autoCommitOnReturn;
1944     }
1945
1946     /**
1947      * Sets the EvictionPolicy implementation to use with this connection pool.
1948      *
1949      * @param evictionPolicyClassName The fully qualified class name of the EvictionPolicy implementation
1950      */

1951     public synchronized void setEvictionPolicyClassName(final String evictionPolicyClassName) {
1952         if (connectionPool != null) {
1953             connectionPool.setEvictionPolicyClassName(evictionPolicyClassName);
1954         }
1955         this.evictionPolicyClassName = evictionPolicyClassName;
1956     }
1957
1958     /**
1959      * @see #getFastFailValidation()
1960      * @param fastFailValidation true means connections created by this factory will fast fail validation
1961      * @since 2.1
1962      */

1963     public void setFastFailValidation(final boolean fastFailValidation) {
1964         this.fastFailValidation = fastFailValidation;
1965     }
1966
1967     /**
1968      * <p>
1969      * Sets the initial size of the connection pool.
1970      * </p>
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: <code>getConnection, setLogwriter,
1974      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
1975      * </p>
1976      *
1977      * @param initialSize the number of connections created when the pool is initialized
1978      */

1979     public synchronized void setInitialSize(final int initialSize) {
1980         this.initialSize = initialSize;
1981     }
1982
1983     /**
1984      * Sets the JMX name that has been requested for this DataSource. If the requested name is not valid, an alternative
1985      * may be chosen. This DataSource will attempt to register itself using this name. If another component registers
1986      * this DataSource with JMX and this name is valid this name will be used in preference to any specified by the
1987      * other component.
1988      *
1989      * @param jmxName The JMX name that has been requested for this DataSource
1990      */

1991     public void setJmxName(final String jmxName) {
1992         this.jmxName = jmxName;
1993     }
1994
1995     /**
1996      * Sets the LIFO property. True means the pool behaves as a LIFO queue; false means FIFO.
1997      *
1998      * @param lifo the new value for the LIFO property
1999      */

2000     public synchronized void setLifo(final boolean lifo) {
2001         this.lifo = lifo;
2002         if (connectionPool != null) {
2003             connectionPool.setLifo(lifo);
2004         }
2005     }
2006
2007     /**
2008      * @param logAbandoned new logAbandoned property value
2009      */

2010     public void setLogAbandoned(final boolean logAbandoned) {
2011         if (abandonedConfig == null) {
2012             abandonedConfig = new AbandonedConfig();
2013         }
2014         abandonedConfig.setLogAbandoned(logAbandoned);
2015         final GenericObjectPool<?> gop = this.connectionPool;
2016         if (gop != null) {
2017             gop.setAbandonedConfig(abandonedConfig);
2018         }
2019     }
2020
2021     /**
2022      * When {@link #getMaxConnLifetimeMillis()} is set to limit connection lifetime, this property determines whether or
2023      * not log messages are generated when the pool closes connections due to maximum lifetime exceeded. Set this
2024      * property to false to suppress log messages when connections expire.
2025      *
2026      * @param logExpiredConnections Whether or not log messages are generated when the pool closes connections due to
2027      *                              maximum lifetime exceeded.
2028      */

2029     public void setLogExpiredConnections(final boolean logExpiredConnections) {
2030         this.logExpiredConnections = logExpiredConnections;
2031     }
2032
2033     /**
2034      * <strong>BasicDataSource does NOT support this method. </strong>
2035      *
2036      * <p>
2037      * Set the login timeout (in seconds) for connecting to the database.
2038      * </p>
2039      * <p>
2040      * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool.
2041      * </p>
2042      *
2043      * @param loginTimeout The new login timeout, or zero for no timeout
2044      * @throws UnsupportedOperationException If the DataSource implementation does not support the login timeout
2045      *                                       feature.
2046      * @throws SQLException                  if a database access error occurs
2047      */

2048     @Override
2049     public void setLoginTimeout(final int loginTimeout) throws SQLException {
2050         // This method isn't supported by the PoolingDataSource returned by the
2051         // createDataSource
2052         throw new UnsupportedOperationException("Not supported by BasicDataSource");
2053     }
2054
2055     /**
2056      * <p>
2057      * Sets the log writer being used by this data source.
2058      * </p>
2059      * <p>
2060      * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool.
2061      * </p>
2062      *
2063      * @param logWriter The new log writer
2064      * @throws SQLException if a database access error occurs
2065      */

2066     @Override
2067     public void setLogWriter(final PrintWriter logWriter) throws SQLException {
2068         createDataSource().setLogWriter(logWriter);
2069         this.logWriter = logWriter;
2070     }
2071
2072     /**
2073      * <p>
2074      * Sets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an
2075      * infinite lifetime.
2076      * </p>
2077      * <p>
2078      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
2079      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
2080      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
2081      * </p>
2082      *
2083      * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection in milliseconds.
2084      */

2085     public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) {
2086         this.maxConnLifetimeMillis = maxConnLifetimeMillis;
2087     }
2088
2089     /**
2090      * Sets the maximum number of connections that can remain idle in the pool. Excess idle connections are destroyed on
2091      * return to the pool.
2092      *
2093      * @see #getMaxIdle()
2094      * @param maxIdle the new value for maxIdle
2095      */

2096     public synchronized void setMaxIdle(final int maxIdle) {
2097         this.maxIdle = maxIdle;
2098         if (connectionPool != null) {
2099             connectionPool.setMaxIdle(maxIdle);
2100         }
2101     }
2102
2103     /**
2104      * <p>
2105      * Sets the value of the <code>maxOpenPreparedStatements</code> property.
2106      * </p>
2107      * <p>
2108      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
2109      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
2110      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
2111      * </p>
2112      *
2113      * @param maxOpenStatements the new maximum number of prepared statements
2114      */

2115     public synchronized void setMaxOpenPreparedStatements(final int maxOpenStatements) {
2116         this.maxOpenPreparedStatements = maxOpenStatements;
2117     }
2118
2119     /**
2120      * Sets the maximum total number of idle and borrows connections that can be active at the same time. Use a negative
2121      * value for no limit.
2122      *
2123      * @param maxTotal the new value for maxTotal
2124      * @see #getMaxTotal()
2125      */

2126     public synchronized void setMaxTotal(final int maxTotal) {
2127         this.maxTotal = maxTotal;
2128         if (connectionPool != null) {
2129             connectionPool.setMaxTotal(maxTotal);
2130         }
2131     }
2132
2133     /**
2134      * Sets the MaxWaitMillis property. Use -1 to make the pool wait indefinitely.
2135      *
2136      * @param maxWaitMillis the new value for MaxWaitMillis
2137      * @see #getMaxWaitMillis()
2138      */

2139     public synchronized void setMaxWaitMillis(final long maxWaitMillis) {
2140         this.maxWaitMillis = maxWaitMillis;
2141         if (connectionPool != null) {
2142             connectionPool.setMaxWaitMillis(maxWaitMillis);
2143         }
2144     }
2145
2146     /**
2147      * Sets the {@link #minEvictableIdleTimeMillis} property.
2148      *
2149      * @param minEvictableIdleTimeMillis the minimum amount of time an object may sit idle in the pool
2150      * @see #minEvictableIdleTimeMillis
2151      */

2152     public synchronized void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) {
2153         this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
2154         if (connectionPool != null) {
2155             connectionPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
2156         }
2157     }
2158
2159     // ------------------------------------------------------ Protected Methods
2160
2161     /**
2162      * Sets the minimum number of idle connections in the pool. The pool attempts to ensure that minIdle connections are
2163      * available when the idle object evictor runs. The value of this property has no effect unless
2164      * {@link #timeBetweenEvictionRunsMillis} has a positive value.
2165      *
2166      * @param minIdle the new value for minIdle
2167      * @see GenericObjectPool#setMinIdle(int)
2168      */

2169     public synchronized void setMinIdle(final int minIdle) {
2170         this.minIdle = minIdle;
2171         if (connectionPool != null) {
2172             connectionPool.setMinIdle(minIdle);
2173         }
2174     }
2175
2176     /**
2177      * Sets the value of the {@link #numTestsPerEvictionRun} property.
2178      *
2179      * @param numTestsPerEvictionRun the new {@link #numTestsPerEvictionRun} value
2180      * @see #numTestsPerEvictionRun
2181      */

2182     public synchronized void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
2183         this.numTestsPerEvictionRun = numTestsPerEvictionRun;
2184         if (connectionPool != null) {
2185             connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
2186         }
2187     }
2188
2189     /**
2190      * <p>
2191      * Sets the {@link #password}.
2192      * </p>
2193      * <p>
2194      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
2195      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
2196      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
2197      * </p>
2198      *
2199      * @param password new value for the password
2200      */

2201     public void setPassword(final String password) {
2202         this.password = password;
2203     }
2204
2205     /**
2206      * <p>
2207      * Sets whether to pool statements or not.
2208      * </p>
2209      * <p>
2210      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
2211      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
2212      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
2213      * </p>
2214      *
2215      * @param poolingStatements pooling on or off
2216      */

2217     public synchronized void setPoolPreparedStatements(final boolean poolingStatements) {
2218         this.poolPreparedStatements = poolingStatements;
2219     }
2220
2221     /**
2222      * @param removeAbandonedOnBorrow true means abandoned connections may be removed when connections are borrowed from
2223      *                                the pool.
2224      * @see #getRemoveAbandonedOnBorrow()
2225      */

2226     public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) {
2227         if (abandonedConfig == null) {
2228             abandonedConfig = new AbandonedConfig();
2229         }
2230         abandonedConfig.setRemoveAbandonedOnBorrow(removeAbandonedOnBorrow);
2231         final GenericObjectPool<?> gop = this.connectionPool;
2232         if (gop != null) {
2233             gop.setAbandonedConfig(abandonedConfig);
2234         }
2235     }
2236
2237     /**
2238      * @param removeAbandonedOnMaintenance true means abandoned connections may be removed on pool maintenance.
2239      * @see #getRemoveAbandonedOnMaintenance()
2240      */

2241     public void setRemoveAbandonedOnMaintenance(final boolean removeAbandonedOnMaintenance) {
2242         if (abandonedConfig == null) {
2243             abandonedConfig = new AbandonedConfig();
2244         }
2245         abandonedConfig.setRemoveAbandonedOnMaintenance(removeAbandonedOnMaintenance);
2246         final GenericObjectPool<?> gop = this.connectionPool;
2247         if (gop != null) {
2248             gop.setAbandonedConfig(abandonedConfig);
2249         }
2250     }
2251
2252     /**
2253      * <p>
2254      * Sets the timeout in seconds before an abandoned connection can be removed.
2255      * </p>
2256      *
2257      * <p>
2258      * Setting this property has no effect if {@link #getRemoveAbandonedOnBorrow()} and
2259      * {@link #getRemoveAbandonedOnMaintenance()} are false.
2260      * </p>
2261      *
2262      * @param removeAbandonedTimeout new abandoned timeout in seconds
2263      * @see #getRemoveAbandonedTimeout()
2264      * @see #getRemoveAbandonedOnBorrow()
2265      * @see #getRemoveAbandonedOnMaintenance()
2266      */

2267     public void setRemoveAbandonedTimeout(final int removeAbandonedTimeout) {
2268         if (abandonedConfig == null) {
2269             abandonedConfig = new AbandonedConfig();
2270         }
2271         abandonedConfig.setRemoveAbandonedTimeout(removeAbandonedTimeout);
2272         final GenericObjectPool<?> gop = this.connectionPool;
2273         if (gop != null) {
2274             gop.setAbandonedConfig(abandonedConfig);
2275         }
2276     }
2277
2278     /**
2279      * Sets the flag that controls if a connection will be rolled back when it is returned to the pool if auto commit is
2280      * not enabled and the connection is not read only.
2281      *
2282      * @param rollbackOnReturn whether a connection will be rolled back when it is returned to the pool.
2283      */

2284     public void setRollbackOnReturn(final boolean rollbackOnReturn) {
2285         this.rollbackOnReturn = rollbackOnReturn;
2286     }
2287
2288     /**
2289      * Sets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the
2290      * idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool.
2291      *
2292      * @param softMinEvictableIdleTimeMillis minimum amount of time a connection may sit idle in the pool before it is
2293      *                                       eligible for eviction, assuming there are minIdle idle connections in the
2294      *                                       pool.
2295      * @see #getSoftMinEvictableIdleTimeMillis
2296      */

2297     public synchronized void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) {
2298         this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
2299         if (connectionPool != null) {
2300             connectionPool.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis);
2301         }
2302     }
2303
2304     /**
2305      * Sets the {@link #testOnBorrow} property. This property determines whether or not the pool will validate objects
2306      * before they are borrowed from the pool.
2307      *
2308      * @param testOnBorrow new value for testOnBorrow property
2309      */

2310     public synchronized void setTestOnBorrow(final boolean testOnBorrow) {
2311         this.testOnBorrow = testOnBorrow;
2312         if (connectionPool != null) {
2313             connectionPool.setTestOnBorrow(testOnBorrow);
2314         }
2315     }
2316
2317     /**
2318      * Sets the {@link #testOnCreate} property. This property determines whether or not the pool will validate objects
2319      * immediately after they are created by the pool
2320      *
2321      * @param testOnCreate new value for testOnCreate property
2322      */

2323     public synchronized void setTestOnCreate(final boolean testOnCreate) {
2324         this.testOnCreate = testOnCreate;
2325         if (connectionPool != null) {
2326             connectionPool.setTestOnCreate(testOnCreate);
2327         }
2328     }
2329
2330     /**
2331      * Sets the <code>testOnReturn</code> property. This property determines whether or not the pool will validate
2332      * objects before they are returned to the pool.
2333      *
2334      * @param testOnReturn new value for testOnReturn property
2335      */

2336     public synchronized void setTestOnReturn(final boolean testOnReturn) {
2337         this.testOnReturn = testOnReturn;
2338         if (connectionPool != null) {
2339             connectionPool.setTestOnReturn(testOnReturn);
2340         }
2341     }
2342
2343     /**
2344      * Sets the <code>testWhileIdle</code> property. This property determines whether or not the idle object evictor
2345      * will validate connections.
2346      *
2347      * @param testWhileIdle new value for testWhileIdle property
2348      */

2349     public synchronized void setTestWhileIdle(final boolean testWhileIdle) {
2350         this.testWhileIdle = testWhileIdle;
2351         if (connectionPool != null) {
2352             connectionPool.setTestWhileIdle(testWhileIdle);
2353         }
2354     }
2355
2356     /**
2357      * Sets the {@link #timeBetweenEvictionRunsMillis} property.
2358      *
2359      * @param timeBetweenEvictionRunsMillis the new time between evictor runs
2360      * @see #timeBetweenEvictionRunsMillis
2361      */

2362     public synchronized void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
2363         this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
2364         if (connectionPool != null) {
2365             connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
2366         }
2367     }
2368
2369     /**
2370      * <p>
2371      * Sets the {@link #url}.
2372      * </p>
2373      * <p>
2374      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
2375      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
2376      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
2377      * </p>
2378      *
2379      * @param url the new value for the JDBC connection url
2380      */

2381     public synchronized void setUrl(final String url) {
2382         this.url = url;
2383     }
2384
2385     /**
2386      * <p>
2387      * Sets the {@link #userName}.
2388      * </p>
2389      * <p>
2390      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
2391      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
2392      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
2393      * </p>
2394      *
2395      * @param userName the new value for the JDBC connection user name
2396      */

2397     public void setUsername(final String userName) {
2398         this.userName = userName;
2399     }
2400
2401     /**
2402      * <p>
2403      * Sets the {@link #validationQuery}.
2404      * </p>
2405      * <p>
2406      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
2407      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
2408      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
2409      * </p>
2410      *
2411      * @param validationQuery the new value for the validation query
2412      */

2413     public void setValidationQuery(final String validationQuery) {
2414         if (isEmpty(validationQuery)) {
2415             this.validationQuery = null;
2416         } else {
2417             this.validationQuery = validationQuery;
2418         }
2419     }
2420
2421     /**
2422      * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a
2423      * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout.
2424      * <p>
2425      * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first
2426      * time one of the following methods is invoked: <code>getConnection, setLogwriter,
2427      * setLoginTimeout, getLoginTimeout, getLogWriter.</code>
2428      * </p>
2429      *
2430      * @param validationQueryTimeoutSeconds new validation query timeout value in seconds
2431      */

2432     public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) {
2433         this.validationQueryTimeoutSeconds = validationQueryTimeoutSeconds;
2434     }
2435
2436     /**
2437      * Starts the connection pool maintenance task, if configured.
2438      */

2439     protected void startPoolMaintenance() {
2440         if (connectionPool != null && timeBetweenEvictionRunsMillis > 0) {
2441             connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
2442         }
2443     }
2444
2445     @Override
2446     public <T> T unwrap(final Class<T> iface) throws SQLException {
2447         throw new SQLException("BasicDataSource is not a wrapper.");
2448     }
2449
2450     private void updateJmxName(final GenericObjectPoolConfig<?> config) {
2451         if (registeredJmxObjectName == null) {
2452             return;
2453         }
2454         final StringBuilder base = new StringBuilder(registeredJmxObjectName.toString());
2455         base.append(Constants.JMX_CONNECTION_POOL_BASE_EXT);
2456         config.setJmxNameBase(base.toString());
2457         config.setJmxNamePrefix(Constants.JMX_CONNECTION_POOL_PREFIX);
2458     }
2459
2460 }
2461