001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.dbcp2;
018
019import java.io.OutputStreamWriter;
020import java.io.PrintWriter;
021import java.nio.charset.StandardCharsets;
022import java.security.AccessController;
023import java.security.PrivilegedActionException;
024import java.security.PrivilegedExceptionAction;
025import java.sql.Connection;
026import java.sql.Driver;
027import java.sql.DriverManager;
028import java.sql.SQLException;
029import java.sql.SQLFeatureNotSupportedException;
030import java.util.ArrayList;
031import java.util.Collection;
032import java.util.Collections;
033import java.util.HashSet;
034import java.util.List;
035import java.util.Objects;
036import java.util.Properties;
037import java.util.Set;
038import java.util.logging.Logger;
039
040import javax.management.MBeanRegistration;
041import javax.management.MBeanServer;
042import javax.management.MalformedObjectNameException;
043import javax.management.ObjectName;
044import javax.sql.DataSource;
045
046import org.apache.commons.logging.Log;
047import org.apache.commons.logging.LogFactory;
048import org.apache.commons.pool2.PooledObject;
049import org.apache.commons.pool2.impl.AbandonedConfig;
050import org.apache.commons.pool2.impl.BaseObjectPoolConfig;
051import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
052import org.apache.commons.pool2.impl.GenericObjectPool;
053import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
054
055/**
056 * <p>
057 * Basic implementation of <code>javax.sql.DataSource</code> that is configured via JavaBeans properties. This is not
058 * the only way to combine the <em>commons-dbcp2</em> and <em>commons-pool2</em> packages, but provides a "one stop
059 * shopping" solution for basic requirements.
060 * </p>
061 *
062 * @since 2.0
063 */
064public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBeanRegistration, AutoCloseable {
065
066    /**
067     * @since 2.0
068     */
069    private class PaGetConnection implements PrivilegedExceptionAction<Connection> {
070
071        @Override
072        public Connection run() throws SQLException {
073            return createDataSource().getConnection();
074        }
075    }
076
077    private static final Log log = LogFactory.getLog(BasicDataSource.class);
078
079    static {
080        // Attempt to prevent deadlocks - see DBCP - 272
081        DriverManager.getDrivers();
082        try {
083            // Load classes now to prevent AccessControlExceptions later
084            // A number of classes are loaded when getConnection() is called
085            // but the following classes are not loaded and therefore require
086            // explicit loading.
087            if (Utils.IS_SECURITY_ENABLED) {
088                final ClassLoader loader = BasicDataSource.class.getClassLoader();
089                final String dbcpPackageName = BasicDataSource.class.getPackage().getName();
090                loader.loadClass(dbcpPackageName + ".BasicDataSource$PaGetConnection");
091                loader.loadClass(dbcpPackageName + ".DelegatingCallableStatement");
092                loader.loadClass(dbcpPackageName + ".DelegatingDatabaseMetaData");
093                loader.loadClass(dbcpPackageName + ".DelegatingPreparedStatement");
094                loader.loadClass(dbcpPackageName + ".DelegatingResultSet");
095                loader.loadClass(dbcpPackageName + ".PoolableCallableStatement");
096                loader.loadClass(dbcpPackageName + ".PoolablePreparedStatement");
097                loader.loadClass(dbcpPackageName + ".PoolingConnection$StatementType");
098                loader.loadClass(dbcpPackageName + ".PStmtKey");
099
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 data source. 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.commons.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 true, this data source is closed and no more connections can be retrieved from this data source.
1484     *
1485     * @return true, if 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.commons.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}