| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.dbcp2; |
| |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.nio.charset.StandardCharsets; |
| import java.security.AccessController; |
| import java.security.PrivilegedActionException; |
| import java.security.PrivilegedExceptionAction; |
| import java.sql.Connection; |
| import java.sql.Driver; |
| import java.sql.DriverManager; |
| import java.sql.SQLException; |
| import java.sql.SQLFeatureNotSupportedException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Objects; |
| import java.util.Properties; |
| import java.util.Set; |
| import java.util.logging.Logger; |
| |
| import javax.management.MBeanRegistration; |
| import javax.management.MBeanServer; |
| import javax.management.MalformedObjectNameException; |
| import javax.management.ObjectName; |
| import javax.sql.DataSource; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.commons.pool2.PooledObject; |
| import org.apache.commons.pool2.impl.AbandonedConfig; |
| import org.apache.commons.pool2.impl.BaseObjectPoolConfig; |
| import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; |
| import org.apache.commons.pool2.impl.GenericObjectPool; |
| import org.apache.commons.pool2.impl.GenericObjectPoolConfig; |
| |
| /** |
| * <p> |
| * Basic implementation of <code>javax.sql.DataSource</code> that is configured via JavaBeans properties. This is not |
| * the only way to combine the <em>commons-dbcp2</em> and <em>commons-pool2</em> packages, but provides a "one stop |
| * shopping" solution for basic requirements. |
| * </p> |
| * |
| * @since 2.0 |
| */ |
| public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBeanRegistration, AutoCloseable { |
| |
| /** |
| * @since 2.0 |
| */ |
| private class PaGetConnection implements PrivilegedExceptionAction<Connection> { |
| |
| @Override |
| public Connection run() throws SQLException { |
| return createDataSource().getConnection(); |
| } |
| } |
| |
| private static final Log log = LogFactory.getLog(BasicDataSource.class); |
| |
| static { |
| // Attempt to prevent deadlocks - see DBCP - 272 |
| DriverManager.getDrivers(); |
| try { |
| // Load classes now to prevent AccessControlExceptions later |
| // A number of classes are loaded when getConnection() is called |
| // but the following classes are not loaded and therefore require |
| // explicit loading. |
| if (Utils.IS_SECURITY_ENABLED) { |
| final ClassLoader loader = BasicDataSource.class.getClassLoader(); |
| final String dbcpPackageName = BasicDataSource.class.getPackage().getName(); |
| loader.loadClass(dbcpPackageName + ".BasicDataSource$PaGetConnection"); |
| loader.loadClass(dbcpPackageName + ".DelegatingCallableStatement"); |
| loader.loadClass(dbcpPackageName + ".DelegatingDatabaseMetaData"); |
| loader.loadClass(dbcpPackageName + ".DelegatingPreparedStatement"); |
| loader.loadClass(dbcpPackageName + ".DelegatingResultSet"); |
| loader.loadClass(dbcpPackageName + ".PoolableCallableStatement"); |
| loader.loadClass(dbcpPackageName + ".PoolablePreparedStatement"); |
| loader.loadClass(dbcpPackageName + ".PoolingConnection$StatementType"); |
| loader.loadClass(dbcpPackageName + ".PStmtKey"); |
| |
| final String poolPackageName = PooledObject.class.getPackage().getName(); |
| loader.loadClass(poolPackageName + ".impl.LinkedBlockingDeque$Node"); |
| loader.loadClass(poolPackageName + ".impl.GenericKeyedObjectPool$ObjectDeque"); |
| } |
| } catch (final ClassNotFoundException cnfe) { |
| throw new IllegalStateException("Unable to pre-load classes", cnfe); |
| } |
| } |
| |
| protected static void validateConnectionFactory(final PoolableConnectionFactory connectionFactory) |
| throws Exception { |
| PoolableConnection conn = null; |
| PooledObject<PoolableConnection> p = null; |
| try { |
| p = connectionFactory.makeObject(); |
| conn = p.getObject(); |
| connectionFactory.activateObject(p); |
| connectionFactory.validateConnection(conn); |
| connectionFactory.passivateObject(p); |
| } finally { |
| if (p != null) { |
| connectionFactory.destroyObject(p); |
| } |
| } |
| } |
| |
| /** |
| * The default auto-commit state of connections created by this pool. |
| */ |
| private volatile Boolean defaultAutoCommit; |
| |
| /** |
| * The default read-only state of connections created by this pool. |
| */ |
| private transient Boolean defaultReadOnly; |
| |
| /** |
| * The default TransactionIsolation state of connections created by this pool. |
| */ |
| private volatile int defaultTransactionIsolation = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION; |
| |
| private Integer defaultQueryTimeoutSeconds; |
| |
| /** |
| * The default "catalog" of connections created by this pool. |
| */ |
| private volatile String defaultCatalog; |
| |
| /** |
| * The default "schema" of connections created by this pool. |
| */ |
| private volatile String defaultSchema; |
| |
| /** |
| * The property that controls if the pooled connections cache some state rather than query the database for current |
| * state to improve performance. |
| */ |
| private boolean cacheState = true; |
| |
| /** |
| * The instance of the JDBC Driver to use. |
| */ |
| private Driver driver; |
| |
| /** |
| * The fully qualified Java class name of the JDBC driver to be used. |
| */ |
| private String driverClassName; |
| |
| /** |
| * The class loader instance to use to load the JDBC driver. If not specified, {@link Class#forName(String)} is used |
| * to load the JDBC driver. If specified, {@link Class#forName(String, boolean, ClassLoader)} is used. |
| */ |
| private ClassLoader driverClassLoader; |
| |
| /** |
| * True means that borrowObject returns the most recently used ("last in") connection in the pool (if there are idle |
| * connections available). False means that the pool behaves as a FIFO queue - connections are taken from the idle |
| * instance pool in the order that they are returned to the pool. |
| */ |
| private boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO; |
| |
| /** |
| * The maximum number of active connections that can be allocated from this pool at the same time, or negative for |
| * no limit. |
| */ |
| private int maxTotal = GenericObjectPoolConfig.DEFAULT_MAX_TOTAL; |
| |
| /** |
| * The maximum number of connections that can remain idle in the pool, without extra ones being destroyed, or |
| * negative for no limit. If maxIdle is set too low on heavily loaded systems it is possible you will see |
| * connections being closed and almost immediately new connections being opened. This is a result of the active |
| * threads momentarily closing connections faster than they are opening them, causing the number of idle connections |
| * to rise above maxIdle. The best value for maxIdle for heavily loaded system will vary but the default is a good |
| * starting point. |
| */ |
| private int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE; |
| |
| /** |
| * The minimum number of active connections that can remain idle in the pool, without extra ones being created when |
| * the evictor runs, or 0 to create none. The pool attempts to ensure that minIdle connections are available when |
| * the idle object evictor runs. The value of this property has no effect unless |
| * {@link #timeBetweenEvictionRunsMillis} has a positive value. |
| */ |
| private int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE; |
| |
| /** |
| * The initial number of connections that are created when the pool is started. |
| */ |
| private int initialSize = 0; |
| |
| /** |
| * The maximum number of milliseconds that the pool will wait (when there are no available connections) for a |
| * connection to be returned before throwing an exception, or <= 0 to wait indefinitely. |
| */ |
| private long maxWaitMillis = BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS; |
| |
| /** |
| * Prepared statement pooling for this pool. When this property is set to <code>true</code> both PreparedStatements |
| * and CallableStatements are pooled. |
| */ |
| private boolean poolPreparedStatements = false; |
| |
| /** |
| * <p> |
| * The maximum number of open statements that can be allocated from the statement pool at the same time, or negative |
| * for no limit. Since a connection usually only uses one or two statements at a time, this is mostly used to help |
| * detect resource leaks. |
| * </p> |
| * <p> |
| * Note: As of version 1.3, CallableStatements (those produced by {@link Connection#prepareCall}) are pooled along |
| * with PreparedStatements (produced by {@link Connection#prepareStatement}) and |
| * <code>maxOpenPreparedStatements</code> limits the total number of prepared or callable statements that may be in |
| * use at a given time. |
| * </p> |
| */ |
| private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; |
| |
| /** |
| * The indication of whether objects will be validated as soon as they have been created by the pool. If the object |
| * fails to validate, the borrow operation that triggered the creation will fail. |
| */ |
| private boolean testOnCreate = false; |
| |
| /** |
| * The indication of whether objects will be validated before being borrowed from the pool. If the object fails to |
| * validate, it will be dropped from the pool, and we will attempt to borrow another. |
| */ |
| private boolean testOnBorrow = true; |
| |
| /** |
| * The indication of whether objects will be validated before being returned to the pool. |
| */ |
| private boolean testOnReturn = false; |
| |
| /** |
| * The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no idle |
| * object evictor thread will be run. |
| */ |
| private long timeBetweenEvictionRunsMillis = BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; |
| |
| /** |
| * The number of objects to examine during each run of the idle object evictor thread (if any). |
| */ |
| private int numTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; |
| |
| /** |
| * The minimum amount of time an object may sit idle in the pool before it is eligible for eviction by the idle |
| * object evictor (if any). |
| */ |
| private long minEvictableIdleTimeMillis = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; |
| |
| /** |
| * The minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the idle |
| * object evictor, with the extra condition that at least "minIdle" connections remain in the pool. Note that |
| * {@code minEvictableIdleTimeMillis} takes precedence over this parameter. See |
| * {@link #getSoftMinEvictableIdleTimeMillis()}. |
| */ |
| private long softMinEvictableIdleTimeMillis = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS; |
| |
| private String evictionPolicyClassName = BaseObjectPoolConfig.DEFAULT_EVICTION_POLICY_CLASS_NAME; |
| |
| /** |
| * The indication of whether objects will be validated by the idle object evictor (if any). If an object fails to |
| * validate, it will be dropped from the pool. |
| */ |
| private boolean testWhileIdle = false; |
| |
| /** |
| * The connection password to be passed to our JDBC driver to establish a connection. |
| */ |
| private volatile String password; |
| |
| /** |
| * The connection URL to be passed to our JDBC driver to establish a connection. |
| */ |
| private String url; |
| |
| /** |
| * The connection user name to be passed to our JDBC driver to establish a connection. |
| */ |
| private String userName; |
| |
| /** |
| * The SQL query that will be used to validate connections from this pool before returning them to the caller. If |
| * specified, this query <strong>MUST</strong> be an SQL SELECT statement that returns at least one row. If not |
| * specified, {@link Connection#isValid(int)} will be used to validate connections. |
| */ |
| private volatile String validationQuery; |
| |
| /** |
| * Timeout in seconds before connection validation queries fail. |
| */ |
| private volatile int validationQueryTimeoutSeconds = -1; |
| |
| /** |
| * These SQL statements run once after a Connection is created. |
| * <p> |
| * This property can be used for example to run ALTER SESSION SET NLS_SORT=XCYECH in an Oracle Database only once |
| * after connection creation. |
| * </p> |
| */ |
| private volatile List<String> connectionInitSqls; |
| |
| /** |
| * Controls access to the underlying connection. |
| */ |
| private boolean accessToUnderlyingConnectionAllowed = false; |
| |
| private long maxConnLifetimeMillis = -1; |
| |
| private boolean logExpiredConnections = true; |
| |
| private String jmxName; |
| |
| private boolean autoCommitOnReturn = true; |
| |
| private boolean rollbackOnReturn = true; |
| |
| private volatile Set<String> disconnectionSqlCodes; |
| |
| private boolean fastFailValidation; |
| |
| /** |
| * The object pool that internally manages our connections. |
| */ |
| private volatile GenericObjectPool<PoolableConnection> connectionPool; |
| |
| /** |
| * The connection properties that will be sent to our JDBC driver when establishing new connections. |
| * <strong>NOTE</strong> - The "user" and "password" properties will be passed explicitly, so they do not need to be |
| * included here. |
| */ |
| private Properties connectionProperties = new Properties(); |
| |
| /** |
| * The data source we will use to manage connections. This object should be acquired <strong>ONLY</strong> by calls |
| * to the <code>createDataSource()</code> method. |
| */ |
| private volatile DataSource dataSource; |
| |
| /** |
| * The PrintWriter to which log messages should be directed. |
| */ |
| private volatile PrintWriter logWriter = new PrintWriter( |
| new OutputStreamWriter(System.out, StandardCharsets.UTF_8)); |
| |
| private AbandonedConfig abandonedConfig; |
| |
| private boolean closed; |
| |
| /** |
| * Actual name under which this component has been registered. |
| */ |
| private ObjectNameWrapper registeredJmxObjectName; |
| |
| /** |
| * Adds a custom connection property to the set that will be passed to our JDBC driver. This <strong>MUST</strong> |
| * be called before the first connection is retrieved (along with all the other configuration property setters). |
| * Calls to this method after the connection pool has been initialized have no effect. |
| * |
| * @param name |
| * Name of the custom connection property |
| * @param value |
| * Value of the custom connection property |
| */ |
| public void addConnectionProperty(final String name, final String value) { |
| connectionProperties.put(name, value); |
| } |
| |
| /** |
| * <p> |
| * Closes and releases all idle connections that are currently stored in the connection pool associated with this |
| * data source. |
| * </p> |
| * <p> |
| * Connections that are checked out to clients when this method is invoked are not affected. When client |
| * applications subsequently invoke {@link Connection#close()} to return these connections to the pool, the |
| * underlying JDBC connections are closed. |
| * </p> |
| * <p> |
| * Attempts to acquire connections using {@link #getConnection()} after this method has been invoked result in |
| * SQLExceptions. |
| * </p> |
| * <p> |
| * This method is idempotent - i.e., closing an already closed BasicDataSource has no effect and does not generate |
| * exceptions. |
| * </p> |
| * |
| * @throws SQLException |
| * if an error occurs closing idle connections |
| */ |
| @Override |
| public synchronized void close() throws SQLException { |
| if (registeredJmxObjectName != null) { |
| registeredJmxObjectName.unregisterMBean(); |
| registeredJmxObjectName = null; |
| } |
| closed = true; |
| final GenericObjectPool<?> oldpool = connectionPool; |
| connectionPool = null; |
| dataSource = null; |
| try { |
| if (oldpool != null) { |
| oldpool.close(); |
| } |
| } catch (final RuntimeException e) { |
| throw e; |
| } catch (final Exception e) { |
| throw new SQLException(Utils.getMessage("pool.close.fail"), e); |
| } |
| } |
| |
| /** |
| * Closes the connection pool, silently swallowing any exception that occurs. |
| */ |
| private void closeConnectionPool() { |
| final GenericObjectPool<?> oldPool = connectionPool; |
| connectionPool = null; |
| try { |
| if (oldPool != null) { |
| oldPool.close(); |
| } |
| } catch (final Exception e) { |
| /* Ignore */ |
| } |
| } |
| |
| /** |
| * Creates a JDBC connection factory for this data source. The JDBC driver is loaded using the following algorithm: |
| * <ol> |
| * <li>If a Driver instance has been specified via {@link #setDriver(Driver)} use it</li> |
| * <li>If no Driver instance was specified and {@link #driverClassName} is specified that class is loaded using the |
| * {@link ClassLoader} of this class or, if {@link #driverClassLoader} is set, {@link #driverClassName} is loaded |
| * with the specified {@link ClassLoader}.</li> |
| * <li>If {@link #driverClassName} is specified and the previous attempt fails, the class is loaded using the |
| * context class loader of the current thread.</li> |
| * <li>If a driver still isn't loaded one is loaded via the {@link DriverManager} using the specified {@link #url}. |
| * </ol> |
| * <p> |
| * This method exists so subclasses can replace the implementation class. |
| * </p> |
| * |
| * @return A new connection factory. |
| * |
| * @throws SQLException |
| * If the connection factort cannot be created |
| */ |
| protected ConnectionFactory createConnectionFactory() throws SQLException { |
| // Load the JDBC driver class |
| Driver driverToUse = this.driver; |
| |
| if (driverToUse == null) { |
| Class<?> driverFromCCL = null; |
| if (driverClassName != null) { |
| try { |
| try { |
| if (driverClassLoader == null) { |
| driverFromCCL = Class.forName(driverClassName); |
| } else { |
| driverFromCCL = Class.forName(driverClassName, true, driverClassLoader); |
| } |
| } catch (final ClassNotFoundException cnfe) { |
| driverFromCCL = Thread.currentThread().getContextClassLoader().loadClass(driverClassName); |
| } |
| } catch (final Exception t) { |
| final String message = "Cannot load JDBC driver class '" + driverClassName + "'"; |
| logWriter.println(message); |
| t.printStackTrace(logWriter); |
| throw new SQLException(message, t); |
| } |
| } |
| |
| try { |
| if (driverFromCCL == null) { |
| driverToUse = DriverManager.getDriver(url); |
| } else { |
| // Usage of DriverManager is not possible, as it does not |
| // respect the ContextClassLoader |
| // N.B. This cast may cause ClassCastException which is handled below |
| driverToUse = (Driver) driverFromCCL.getConstructor().newInstance(); |
| if (!driverToUse.acceptsURL(url)) { |
| throw new SQLException("No suitable driver", "08001"); |
| } |
| } |
| } catch (final Exception t) { |
| final String message = "Cannot create JDBC driver of class '" |
| + (driverClassName != null ? driverClassName : "") + "' for connect URL '" + url + "'"; |
| logWriter.println(message); |
| t.printStackTrace(logWriter); |
| throw new SQLException(message, t); |
| } |
| } |
| |
| // Set up the driver connection factory we will use |
| final String user = userName; |
| if (user != null) { |
| connectionProperties.put("user", user); |
| } else { |
| log("DBCP DataSource configured without a 'username'"); |
| } |
| |
| final String pwd = password; |
| if (pwd != null) { |
| connectionProperties.put("password", pwd); |
| } else { |
| log("DBCP DataSource configured without a 'password'"); |
| } |
| |
| final ConnectionFactory driverConnectionFactory = new DriverConnectionFactory(driverToUse, url, |
| connectionProperties); |
| return driverConnectionFactory; |
| } |
| |
| /** |
| * Creates a connection pool for this datasource. This method only exists so subclasses can replace the |
| * implementation class. |
| * <p> |
| * This implementation configures all pool properties other than timeBetweenEvictionRunsMillis. Setting that |
| * property is deferred to {@link #startPoolMaintenance()}, since setting timeBetweenEvictionRunsMillis to a |
| * positive value causes {@link GenericObjectPool}'s eviction timer to be started. |
| * </p> |
| * |
| * @param factory |
| * The factory to use to create new connections for this pool. |
| */ |
| protected void createConnectionPool(final PoolableConnectionFactory factory) { |
| // Create an object pool to contain our active connections |
| final GenericObjectPoolConfig<PoolableConnection> config = new GenericObjectPoolConfig<>(); |
| updateJmxName(config); |
| // Disable JMX on the underlying pool if the DS is not registered: |
| config.setJmxEnabled(registeredJmxObjectName != null); |
| final GenericObjectPool<PoolableConnection> gop = createObjectPool(factory, config, abandonedConfig); |
| gop.setMaxTotal(maxTotal); |
| gop.setMaxIdle(maxIdle); |
| gop.setMinIdle(minIdle); |
| gop.setMaxWaitMillis(maxWaitMillis); |
| gop.setTestOnCreate(testOnCreate); |
| gop.setTestOnBorrow(testOnBorrow); |
| gop.setTestOnReturn(testOnReturn); |
| gop.setNumTestsPerEvictionRun(numTestsPerEvictionRun); |
| gop.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); |
| gop.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis); |
| gop.setTestWhileIdle(testWhileIdle); |
| gop.setLifo(lifo); |
| gop.setSwallowedExceptionListener(new SwallowedExceptionLogger(log, logExpiredConnections)); |
| gop.setEvictionPolicyClassName(evictionPolicyClassName); |
| factory.setPool(gop); |
| connectionPool = gop; |
| } |
| |
| /** |
| * <p> |
| * Creates (if necessary) and return the internal data source we are using to manage our connections. |
| * </p> |
| * |
| * @return The current internal DataSource or a newly created instance if it has not yet been created. |
| * @throws SQLException |
| * if the object pool cannot be created. |
| */ |
| protected DataSource createDataSource() throws SQLException { |
| if (closed) { |
| throw new SQLException("Data source is closed"); |
| } |
| |
| // Return the pool if we have already created it |
| // This is double-checked locking. This is safe since dataSource is |
| // volatile and the code is targeted at Java 5 onwards. |
| if (dataSource != null) { |
| return dataSource; |
| } |
| synchronized (this) { |
| if (dataSource != null) { |
| return dataSource; |
| } |
| |
| jmxRegister(); |
| |
| // create factory which returns raw physical connections |
| final ConnectionFactory driverConnectionFactory = createConnectionFactory(); |
| |
| // Set up the poolable connection factory |
| boolean success = false; |
| PoolableConnectionFactory poolableConnectionFactory; |
| try { |
| poolableConnectionFactory = createPoolableConnectionFactory(driverConnectionFactory); |
| poolableConnectionFactory.setPoolStatements(poolPreparedStatements); |
| poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements); |
| success = true; |
| } catch (final SQLException se) { |
| throw se; |
| } catch (final RuntimeException rte) { |
| throw rte; |
| } catch (final Exception ex) { |
| throw new SQLException("Error creating connection factory", ex); |
| } |
| |
| if (success) { |
| // create a pool for our connections |
| createConnectionPool(poolableConnectionFactory); |
| } |
| |
| // Create the pooling data source to manage connections |
| DataSource newDataSource; |
| success = false; |
| try { |
| newDataSource = createDataSourceInstance(); |
| newDataSource.setLogWriter(logWriter); |
| success = true; |
| } catch (final SQLException se) { |
| throw se; |
| } catch (final RuntimeException rte) { |
| throw rte; |
| } catch (final Exception ex) { |
| throw new SQLException("Error creating datasource", ex); |
| } finally { |
| if (!success) { |
| closeConnectionPool(); |
| } |
| } |
| |
| // If initialSize > 0, preload the pool |
| try { |
| for (int i = 0; i < initialSize; i++) { |
| connectionPool.addObject(); |
| } |
| } catch (final Exception e) { |
| closeConnectionPool(); |
| throw new SQLException("Error preloading the connection pool", e); |
| } |
| |
| // If timeBetweenEvictionRunsMillis > 0, start the pool's evictor task |
| startPoolMaintenance(); |
| |
| dataSource = newDataSource; |
| return dataSource; |
| } |
| } |
| |
| /** |
| * Creates the actual data source instance. This method only exists so that subclasses can replace the |
| * implementation class. |
| * |
| * @throws SQLException |
| * if unable to create a datasource instance |
| * |
| * @return A new DataSource instance |
| */ |
| protected DataSource createDataSourceInstance() throws SQLException { |
| final PoolingDataSource<PoolableConnection> pds = new PoolingDataSource<>(connectionPool); |
| pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed()); |
| return pds; |
| } |
| |
| /** |
| * Creates an object pool used to provide pooling support for {@link Connection JDBC connections}. |
| * |
| * @param factory |
| * the object factory |
| * @param poolConfig |
| * the object pool configuration |
| * @param abandonedConfig |
| * the abandoned objects configuration |
| * @return a non-null instance |
| */ |
| protected GenericObjectPool<PoolableConnection> createObjectPool(final PoolableConnectionFactory factory, |
| final GenericObjectPoolConfig<PoolableConnection> poolConfig, final AbandonedConfig abandonedConfig) { |
| GenericObjectPool<PoolableConnection> gop; |
| if (abandonedConfig != null && (abandonedConfig.getRemoveAbandonedOnBorrow() |
| || abandonedConfig.getRemoveAbandonedOnMaintenance())) { |
| gop = new GenericObjectPool<>(factory, poolConfig, abandonedConfig); |
| } else { |
| gop = new GenericObjectPool<>(factory, poolConfig); |
| } |
| return gop; |
| } |
| |
| /** |
| * Creates the PoolableConnectionFactory and attaches it to the connection pool. This method only exists so |
| * subclasses can replace the default implementation. |
| * |
| * @param driverConnectionFactory |
| * JDBC connection factory |
| * @throws SQLException |
| * if an error occurs creating the PoolableConnectionFactory |
| * |
| * @return A new PoolableConnectionFactory configured with the current configuration of this BasicDataSource |
| */ |
| protected PoolableConnectionFactory createPoolableConnectionFactory(final ConnectionFactory driverConnectionFactory) |
| throws SQLException { |
| PoolableConnectionFactory connectionFactory = null; |
| try { |
| connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, |
| ObjectNameWrapper.unwrap(registeredJmxObjectName)); |
| connectionFactory.setValidationQuery(validationQuery); |
| connectionFactory.setValidationQueryTimeout(validationQueryTimeoutSeconds); |
| connectionFactory.setConnectionInitSql(connectionInitSqls); |
| connectionFactory.setDefaultReadOnly(defaultReadOnly); |
| connectionFactory.setDefaultAutoCommit(defaultAutoCommit); |
| connectionFactory.setDefaultTransactionIsolation(defaultTransactionIsolation); |
| connectionFactory.setDefaultCatalog(defaultCatalog); |
| connectionFactory.setDefaultSchema(defaultSchema); |
| connectionFactory.setCacheState(cacheState); |
| connectionFactory.setPoolStatements(poolPreparedStatements); |
| connectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements); |
| connectionFactory.setMaxConnLifetimeMillis(maxConnLifetimeMillis); |
| connectionFactory.setRollbackOnReturn(getRollbackOnReturn()); |
| connectionFactory.setAutoCommitOnReturn(getAutoCommitOnReturn()); |
| connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeout()); |
| connectionFactory.setFastFailValidation(fastFailValidation); |
| connectionFactory.setDisconnectionSqlCodes(disconnectionSqlCodes); |
| validateConnectionFactory(connectionFactory); |
| } catch (final RuntimeException e) { |
| throw e; |
| } catch (final Exception e) { |
| throw new SQLException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e); |
| } |
| return connectionFactory; |
| } |
| |
| /** |
| * Gets the print writer used by this configuration to log information on abandoned objects. |
| * |
| * @return The print writer used by this configuration to log information on abandoned objects. |
| */ |
| public PrintWriter getAbandonedLogWriter() { |
| if (abandonedConfig != null) { |
| return abandonedConfig.getLogWriter(); |
| } |
| return null; |
| } |
| |
| /** |
| * If the connection pool implements {@link org.apache.commons.pool2.UsageTracking UsageTracking}, should the |
| * connection pool record a stack trace every time a method is called on a pooled connection and retain the most |
| * recent stack trace to aid debugging of abandoned connections? |
| * |
| * @return <code>true</code> if usage tracking is enabled |
| */ |
| @Override |
| public boolean getAbandonedUsageTracking() { |
| if (abandonedConfig != null) { |
| return abandonedConfig.getUseUsageTracking(); |
| } |
| return false; |
| } |
| |
| /** |
| * Returns the value of the flag that controls whether or not connections being returned to the pool will be checked |
| * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit |
| * setting is {@code false} when the connection is returned. It is <code>true</code> by default. |
| * |
| * @return Whether or not connections being returned to the pool will be checked and configured with auto-commit. |
| */ |
| public boolean getAutoCommitOnReturn() { |
| return autoCommitOnReturn; |
| } |
| |
| /** |
| * Returns the state caching flag. |
| * |
| * @return the state caching flag |
| */ |
| @Override |
| public boolean getCacheState() { |
| return cacheState; |
| } |
| |
| /** |
| * Creates (if necessary) and return a connection to the database. |
| * |
| * @throws SQLException |
| * if a database access error occurs |
| * @return a database connection |
| */ |
| @Override |
| public Connection getConnection() throws SQLException { |
| if (Utils.IS_SECURITY_ENABLED) { |
| final PrivilegedExceptionAction<Connection> action = new PaGetConnection(); |
| try { |
| return AccessController.doPrivileged(action); |
| } catch (final PrivilegedActionException e) { |
| final Throwable cause = e.getCause(); |
| if (cause instanceof SQLException) { |
| throw (SQLException) cause; |
| } |
| throw new SQLException(e); |
| } |
| } |
| return createDataSource().getConnection(); |
| } |
| |
| /** |
| * <strong>BasicDataSource does NOT support this method.</strong> |
| * |
| * @param user |
| * Database user on whose behalf the Connection is being made |
| * @param pass |
| * The database user's password |
| * |
| * @throws UnsupportedOperationException |
| * always thrown. |
| * @throws SQLException |
| * if a database access error occurs |
| * @return nothing - always throws UnsupportedOperationException |
| */ |
| @Override |
| public Connection getConnection(final String user, final String pass) throws SQLException { |
| // This method isn't supported by the PoolingDataSource returned by the createDataSource |
| throw new UnsupportedOperationException("Not supported by BasicDataSource"); |
| } |
| |
| /** |
| * Returns the list of SQL statements executed when a physical connection is first created. Returns an empty list if |
| * there are no initialization statements configured. |
| * |
| * @return initialization SQL statements |
| */ |
| public List<String> getConnectionInitSqls() { |
| final List<String> result = connectionInitSqls; |
| if (result == null) { |
| return Collections.emptyList(); |
| } |
| return result; |
| } |
| |
| /** |
| * Provides the same data as {@link #getConnectionInitSqls()} but in an array so it is accessible via JMX. |
| */ |
| @Override |
| public String[] getConnectionInitSqlsAsArray() { |
| final Collection<String> result = getConnectionInitSqls(); |
| return result.toArray(new String[result.size()]); |
| } |
| |
| protected GenericObjectPool<PoolableConnection> getConnectionPool() { |
| return connectionPool; |
| } |
| |
| // For unit testing |
| Properties getConnectionProperties() { |
| return connectionProperties; |
| } |
| |
| /** |
| * Returns the default auto-commit property. |
| * |
| * @return true if default auto-commit is enabled |
| */ |
| @Override |
| public Boolean getDefaultAutoCommit() { |
| return defaultAutoCommit; |
| } |
| |
| /** |
| * Returns the default catalog. |
| * |
| * @return the default catalog |
| */ |
| @Override |
| public String getDefaultCatalog() { |
| return this.defaultCatalog; |
| } |
| |
| /** |
| * Gets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this |
| * connection. <code>null</code> means that the driver default will be used. |
| * |
| * @return The default query timeout in seconds. |
| */ |
| public Integer getDefaultQueryTimeout() { |
| return defaultQueryTimeoutSeconds; |
| } |
| |
| /** |
| * Returns the default readOnly property. |
| * |
| * @return true if connections are readOnly by default |
| */ |
| @Override |
| public Boolean getDefaultReadOnly() { |
| return defaultReadOnly; |
| } |
| |
| /** |
| * Returns the default schema. |
| * |
| * @return the default schema. |
| * @since 2.5.0 |
| */ |
| @Override |
| public String getDefaultSchema() { |
| return this.defaultSchema; |
| } |
| |
| /** |
| * Returns the default transaction isolation state of returned connections. |
| * |
| * @return the default value for transaction isolation state |
| * @see Connection#getTransactionIsolation |
| */ |
| @Override |
| public int getDefaultTransactionIsolation() { |
| return this.defaultTransactionIsolation; |
| } |
| |
| /** |
| * Returns the set of SQL_STATE codes considered to signal fatal conditions. |
| * |
| * @return fatal disconnection state codes |
| * @see #setDisconnectionSqlCodes(Collection) |
| * @since 2.1 |
| */ |
| public Set<String> getDisconnectionSqlCodes() { |
| final Set<String> result = disconnectionSqlCodes; |
| if (result == null) { |
| return Collections.emptySet(); |
| } |
| return result; |
| } |
| |
| /** |
| * Provides the same data as {@link #getDisconnectionSqlCodes} but in an array so it is accessible via JMX. |
| * |
| * @since 2.1 |
| */ |
| @Override |
| public String[] getDisconnectionSqlCodesAsArray() { |
| final Collection<String> result = getDisconnectionSqlCodes(); |
| return result.toArray(new String[result.size()]); |
| } |
| |
| /** |
| * Returns the JDBC Driver that has been configured for use by this pool. |
| * <p> |
| * Note: This getter only returns the last value set by a call to {@link #setDriver(Driver)}. It does not return any |
| * driver instance that may have been created from the value set via {@link #setDriverClassName(String)}. |
| * </p> |
| * |
| * @return the JDBC Driver that has been configured for use by this pool |
| */ |
| public synchronized Driver getDriver() { |
| return driver; |
| } |
| |
| /** |
| * Returns the class loader specified for loading the JDBC driver. Returns <code>null</code> if no class loader has |
| * been explicitly specified. |
| * <p> |
| * Note: This getter only returns the last value set by a call to {@link #setDriverClassLoader(ClassLoader)}. It |
| * does not return the class loader of any driver that may have been set via {@link #setDriver(Driver)}. |
| * </p> |
| * |
| * @return The class loader specified for loading the JDBC driver. |
| */ |
| public synchronized ClassLoader getDriverClassLoader() { |
| return this.driverClassLoader; |
| } |
| |
| /** |
| * Returns the JDBC driver class name. |
| * <p> |
| * Note: This getter only returns the last value set by a call to {@link #setDriverClassName(String)}. It does not |
| * return the class name of any driver that may have been set via {@link #setDriver(Driver)}. |
| * </p> |
| * |
| * @return the JDBC driver class name |
| */ |
| @Override |
| public synchronized String getDriverClassName() { |
| return this.driverClassName; |
| } |
| |
| /** |
| * Returns the value of the flag that controls whether or not connections being returned to the pool will be checked |
| * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit |
| * setting is {@code false} when the connection is returned. It is <code>true</code> by default. |
| * |
| * @return Whether or not connections being returned to the pool will be checked and configured with auto-commit. |
| * @deprecated Use {@link #getAutoCommitOnReturn()}. |
| */ |
| @Deprecated |
| public boolean getEnableAutoCommitOnReturn() { |
| return autoCommitOnReturn; |
| } |
| |
| /** |
| * Gets the EvictionPolicy implementation in use with this connection pool. |
| * |
| * @return The EvictionPolicy implementation in use with this connection pool. |
| */ |
| public synchronized String getEvictionPolicyClassName() { |
| return evictionPolicyClassName; |
| } |
| |
| /** |
| * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with |
| * SQL_STATE indicating fatal disconnection errors. |
| * |
| * @return true if connections created by this datasource will fast fail validation. |
| * @see #setDisconnectionSqlCodes(Collection) |
| * @since 2.1 |
| */ |
| @Override |
| public boolean getFastFailValidation() { |
| return fastFailValidation; |
| } |
| |
| /** |
| * Returns the initial size of the connection pool. |
| * |
| * @return the number of connections created when the pool is initialized |
| */ |
| @Override |
| public synchronized int getInitialSize() { |
| return this.initialSize; |
| } |
| |
| /** |
| * Returns the JMX name that has been requested for this DataSource. If the requested name is not valid, an |
| * alternative may be chosen. |
| * |
| * @return The JMX name that has been requested for this DataSource. |
| */ |
| public String getJmxName() { |
| return jmxName; |
| } |
| |
| /** |
| * Returns the LIFO property. |
| * |
| * @return true if connection pool behaves as a LIFO queue. |
| */ |
| @Override |
| public synchronized boolean getLifo() { |
| return this.lifo; |
| } |
| |
| /** |
| * <p> |
| * Flag to log stack traces for application code which abandoned a Statement or Connection. |
| * </p> |
| * <p> |
| * Defaults to false. |
| * </p> |
| * <p> |
| * Logging of abandoned Statements and Connections adds overhead for every Connection open or new Statement because |
| * a stack trace has to be generated. |
| * </p> |
| */ |
| @Override |
| public boolean getLogAbandoned() { |
| if (abandonedConfig != null) { |
| return abandonedConfig.getLogAbandoned(); |
| } |
| return false; |
| } |
| |
| /** |
| * When {@link #getMaxConnLifetimeMillis()} is set to limit connection lifetime, this property determines whether or |
| * not log messages are generated when the pool closes connections due to maximum lifetime exceeded. |
| * |
| * @since 2.1 |
| */ |
| @Override |
| public boolean getLogExpiredConnections() { |
| return logExpiredConnections; |
| } |
| |
| /** |
| * <strong>BasicDataSource does NOT support this method.</strong> |
| * |
| * <p> |
| * Returns the login timeout (in seconds) for connecting to the database. |
| * </p> |
| * <p> |
| * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool. |
| * </p> |
| * |
| * @throws SQLException |
| * if a database access error occurs |
| * @throws UnsupportedOperationException |
| * If the DataSource implementation does not support the login timeout feature. |
| * @return login timeout in seconds |
| */ |
| @Override |
| public int getLoginTimeout() throws SQLException { |
| // This method isn't supported by the PoolingDataSource returned by the createDataSource |
| throw new UnsupportedOperationException("Not supported by BasicDataSource"); |
| } |
| |
| /** |
| * <p> |
| * Returns the log writer being used by this data source. |
| * </p> |
| * <p> |
| * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool. |
| * </p> |
| * |
| * @throws SQLException |
| * if a database access error occurs |
| * @return log writer in use |
| */ |
| @Override |
| public PrintWriter getLogWriter() throws SQLException { |
| return createDataSource().getLogWriter(); |
| } |
| |
| /** |
| * Returns the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an |
| * infinite lifetime. |
| */ |
| @Override |
| public long getMaxConnLifetimeMillis() { |
| return maxConnLifetimeMillis; |
| } |
| |
| /** |
| * <p> |
| * Returns the maximum number of connections that can remain idle in the pool. Excess idle connections are destroyed |
| * on return to the pool. |
| * </p> |
| * <p> |
| * A negative value indicates that there is no limit |
| * </p> |
| * |
| * @return the maximum number of idle connections |
| */ |
| @Override |
| public synchronized int getMaxIdle() { |
| return this.maxIdle; |
| } |
| |
| /** |
| * Gets the value of the <code>maxOpenPreparedStatements</code> property. |
| * |
| * @return the maximum number of open statements |
| */ |
| @Override |
| public synchronized int getMaxOpenPreparedStatements() { |
| return this.maxOpenPreparedStatements; |
| } |
| |
| /** |
| * <p> |
| * Returns the maximum number of active connections that can be allocated at the same time. |
| * </p> |
| * <p> |
| * A negative number means that there is no limit. |
| * </p> |
| * |
| * @return the maximum number of active connections |
| */ |
| @Override |
| public synchronized int getMaxTotal() { |
| return this.maxTotal; |
| } |
| |
| /** |
| * Returns the maximum number of milliseconds that the pool will wait for a connection to be returned before |
| * throwing an exception. A value less than or equal to zero means the pool is set to wait indefinitely. |
| * |
| * @return the maxWaitMillis property value |
| */ |
| @Override |
| public synchronized long getMaxWaitMillis() { |
| return this.maxWaitMillis; |
| } |
| |
| /** |
| * Returns the {@link #minEvictableIdleTimeMillis} property. |
| * |
| * @return the value of the {@link #minEvictableIdleTimeMillis} property |
| * @see #minEvictableIdleTimeMillis |
| */ |
| @Override |
| public synchronized long getMinEvictableIdleTimeMillis() { |
| return this.minEvictableIdleTimeMillis; |
| } |
| |
| /** |
| * Returns the minimum number of idle connections in the pool. The pool attempts to ensure that minIdle connections |
| * are available when the idle object evictor runs. The value of this property has no effect unless |
| * {@link #timeBetweenEvictionRunsMillis} has a positive value. |
| * |
| * @return the minimum number of idle connections |
| * @see GenericObjectPool#getMinIdle() |
| */ |
| @Override |
| public synchronized int getMinIdle() { |
| return this.minIdle; |
| } |
| |
| /** |
| * [Read Only] The current number of active connections that have been allocated from this data source. |
| * |
| * @return the current number of active connections |
| */ |
| @Override |
| public int getNumActive() { |
| // Copy reference to avoid NPE if close happens after null check |
| final GenericObjectPool<PoolableConnection> pool = connectionPool; |
| if (pool != null) { |
| return pool.getNumActive(); |
| } |
| return 0; |
| } |
| |
| /** |
| * [Read Only] The current number of idle connections that are waiting to be allocated from this data source. |
| * |
| * @return the current number of idle connections |
| */ |
| @Override |
| public int getNumIdle() { |
| // Copy reference to avoid NPE if close happens after null check |
| final GenericObjectPool<PoolableConnection> pool = connectionPool; |
| if (pool != null) { |
| return pool.getNumIdle(); |
| } |
| return 0; |
| } |
| |
| /** |
| * Returns the value of the {@link #numTestsPerEvictionRun} property. |
| * |
| * @return the number of objects to examine during idle object evictor runs |
| * @see #numTestsPerEvictionRun |
| */ |
| @Override |
| public synchronized int getNumTestsPerEvictionRun() { |
| return this.numTestsPerEvictionRun; |
| } |
| |
| @Override |
| public Logger getParentLogger() throws SQLFeatureNotSupportedException { |
| throw new SQLFeatureNotSupportedException(); |
| } |
| |
| /** |
| * Returns the password passed to the JDBC driver to establish connections. |
| * |
| * @return the connection password |
| */ |
| @Override |
| public String getPassword() { |
| return this.password; |
| } |
| |
| protected ObjectName getRegisteredJmxName() { |
| return ObjectNameWrapper.unwrap(registeredJmxObjectName); |
| } |
| |
| /** |
| * <p> |
| * Flag to remove abandoned connections if they exceed the removeAbandonedTimeout when borrowObject is invoked. |
| * </p> |
| * <p> |
| * The default value is false. |
| * </p> |
| * <p> |
| * If set to true a connection is considered abandoned and eligible for removal if it has not been used for more |
| * than {@link #getRemoveAbandonedTimeout() removeAbandonedTimeout} seconds. |
| * </p> |
| * <p> |
| * Abandoned connections are identified and removed when {@link #getConnection()} is invoked and all of the |
| * following conditions hold: |
| * </p> |
| * <ul> |
| * <li>{@link #getRemoveAbandonedOnBorrow()}</li> |
| * <li>{@link #getNumActive()} > {@link #getMaxTotal()} - 3</li> |
| * <li>{@link #getNumIdle()} < 2</li> |
| * </ul> |
| * |
| * @see #getRemoveAbandonedTimeout() |
| */ |
| @Override |
| public boolean getRemoveAbandonedOnBorrow() { |
| if (abandonedConfig != null) { |
| return abandonedConfig.getRemoveAbandonedOnBorrow(); |
| } |
| return false; |
| } |
| |
| /** |
| * <p> |
| * Flag to remove abandoned connections if they exceed the removeAbandonedTimeout during pool maintenance. |
| * </p> |
| * |
| * <p> |
| * The default value is false. |
| * </p> |
| * |
| * <p> |
| * If set to true a connection is considered abandoned and eligible for removal if it has not been used for more |
| * than {@link #getRemoveAbandonedTimeout() removeAbandonedTimeout} seconds. |
| * </p> |
| * |
| * @see #getRemoveAbandonedTimeout() |
| */ |
| @Override |
| public boolean getRemoveAbandonedOnMaintenance() { |
| if (abandonedConfig != null) { |
| return abandonedConfig.getRemoveAbandonedOnMaintenance(); |
| } |
| return false; |
| } |
| |
| /** |
| * <p> |
| * Timeout in seconds before an abandoned connection can be removed. |
| * </p> |
| * <p> |
| * Creating a Statement, PreparedStatement or CallableStatement or using one of these to execute a query (using one |
| * of the execute methods) resets the lastUsed property of the parent connection. |
| * </p> |
| * <p> |
| * Abandoned connection cleanup happens when: |
| * </p> |
| * <ul> |
| * <li>{@link #getRemoveAbandonedOnBorrow()} or {@link #getRemoveAbandonedOnMaintenance()} = true</li> |
| * <li>{@link #getNumIdle() numIdle} < 2</li> |
| * <li>{@link #getNumActive() numActive} > {@link #getMaxTotal() maxTotal} - 3</li> |
| * </ul> |
| * <p> |
| * The default value is 300 seconds. |
| * </p> |
| */ |
| @Override |
| public int getRemoveAbandonedTimeout() { |
| if (abandonedConfig != null) { |
| return abandonedConfig.getRemoveAbandonedTimeout(); |
| } |
| return 300; |
| } |
| |
| /** |
| * Gets the current value of the flag that controls whether a connection will be rolled back when it is returned to |
| * the pool if auto commit is not enabled and the connection is not read only. |
| * |
| * @return whether a connection will be rolled back when it is returned to the pool. |
| */ |
| public boolean getRollbackOnReturn() { |
| return rollbackOnReturn; |
| } |
| |
| /** |
| * <p> |
| * Returns the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by |
| * the idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool. |
| * </p> |
| * |
| * <p> |
| * When {@link #getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} is set to a positive value, |
| * minEvictableIdleTimeMillis is examined first by the idle connection evictor - i.e. when idle connections are |
| * visited by the evictor, idle time is first compared against {@code minEvictableIdleTimeMillis} (without |
| * considering the number of idle connections in the pool) and then against {@code softMinEvictableIdleTimeMillis}, |
| * including the {@code minIdle}, constraint. |
| * </p> |
| * |
| * @return minimum amount of time a connection may sit idle in the pool before it is eligible for eviction, assuming |
| * there are minIdle idle connections in the pool |
| */ |
| @Override |
| public synchronized long getSoftMinEvictableIdleTimeMillis() { |
| return softMinEvictableIdleTimeMillis; |
| } |
| |
| /** |
| * Returns the {@link #testOnBorrow} property. |
| * |
| * @return true if objects are validated before being borrowed from the pool |
| * |
| * @see #testOnBorrow |
| */ |
| @Override |
| public synchronized boolean getTestOnBorrow() { |
| return this.testOnBorrow; |
| } |
| |
| /** |
| * Returns the {@link #testOnCreate} property. |
| * |
| * @return true if objects are validated immediately after they are created by the pool |
| * @see #testOnCreate |
| */ |
| @Override |
| public synchronized boolean getTestOnCreate() { |
| return this.testOnCreate; |
| } |
| |
| /** |
| * Returns the value of the {@link #testOnReturn} property. |
| * |
| * @return true if objects are validated before being returned to the pool |
| * @see #testOnReturn |
| */ |
| public synchronized boolean getTestOnReturn() { |
| return this.testOnReturn; |
| } |
| |
| /** |
| * Returns the value of the {@link #testWhileIdle} property. |
| * |
| * @return true if objects examined by the idle object evictor are validated |
| * @see #testWhileIdle |
| */ |
| @Override |
| public synchronized boolean getTestWhileIdle() { |
| return this.testWhileIdle; |
| } |
| |
| /** |
| * Returns the value of the {@link #timeBetweenEvictionRunsMillis} property. |
| * |
| * @return the time (in milliseconds) between evictor runs |
| * @see #timeBetweenEvictionRunsMillis |
| */ |
| @Override |
| public synchronized long getTimeBetweenEvictionRunsMillis() { |
| return this.timeBetweenEvictionRunsMillis; |
| } |
| |
| /** |
| * Returns the JDBC connection {@link #url} property. |
| * |
| * @return the {@link #url} passed to the JDBC driver to establish connections |
| */ |
| @Override |
| public synchronized String getUrl() { |
| return this.url; |
| } |
| |
| /** |
| * Returns the JDBC connection {@link #userName} property. |
| * |
| * @return the {@link #userName} passed to the JDBC driver to establish connections |
| */ |
| @Override |
| public String getUsername() { |
| return this.userName; |
| } |
| |
| /** |
| * Returns the validation query used to validate connections before returning them. |
| * |
| * @return the SQL validation query |
| * @see #validationQuery |
| */ |
| @Override |
| public String getValidationQuery() { |
| return this.validationQuery; |
| } |
| |
| /** |
| * Returns the validation query timeout. |
| * |
| * @return the timeout in seconds before connection validation queries fail. |
| */ |
| @Override |
| public int getValidationQueryTimeout() { |
| return validationQueryTimeoutSeconds; |
| } |
| |
| /** |
| * Manually invalidates a connection, effectively requesting the pool to try to close it, remove it from the pool |
| * and reclaim pool capacity. |
| * |
| * @param connection |
| * The Connection to invalidate. |
| * |
| * @throws IllegalStateException |
| * if invalidating the connection failed. |
| * @since 2.1 |
| */ |
| public void invalidateConnection(final Connection connection) throws IllegalStateException { |
| if (connection == null) { |
| return; |
| } |
| if (connectionPool == null) { |
| throw new IllegalStateException("Cannot invalidate connection: ConnectionPool is null."); |
| } |
| |
| final PoolableConnection poolableConnection; |
| try { |
| poolableConnection = connection.unwrap(PoolableConnection.class); |
| if (poolableConnection == null) { |
| throw new IllegalStateException( |
| "Cannot invalidate connection: Connection is not a poolable connection."); |
| } |
| } catch (final SQLException e) { |
| throw new IllegalStateException("Cannot invalidate connection: Unwrapping poolable connection failed.", e); |
| } |
| |
| try { |
| connectionPool.invalidateObject(poolableConnection); |
| } catch (final Exception e) { |
| throw new IllegalStateException("Invalidating connection threw unexpected exception", e); |
| } |
| } |
| |
| /** |
| * Manually evicts idle connections |
| * |
| * @throws Exception when there is a problem evicting idle objects. |
| */ |
| public void evict() throws Exception { |
| if (connectionPool != null) { |
| connectionPool.evict(); |
| } |
| } |
| |
| /** |
| * Returns the value of the accessToUnderlyingConnectionAllowed property. |
| * |
| * @return true if access to the underlying connection is allowed, false otherwise. |
| */ |
| @Override |
| public synchronized boolean isAccessToUnderlyingConnectionAllowed() { |
| return this.accessToUnderlyingConnectionAllowed; |
| } |
| |
| /** |
| * If true, this data source is closed and no more connections can be retrieved from this datasource. |
| * |
| * @return true, if the data source is closed; false otherwise |
| */ |
| @Override |
| public synchronized boolean isClosed() { |
| return closed; |
| } |
| |
| /** |
| * Returns true if we are pooling statements. |
| * |
| * @return true if prepared and callable statements are pooled |
| */ |
| @Override |
| public synchronized boolean isPoolPreparedStatements() { |
| return this.poolPreparedStatements; |
| } |
| |
| @Override |
| public boolean isWrapperFor(final Class<?> iface) throws SQLException { |
| return false; |
| } |
| |
| private void jmxRegister() { |
| // Return immediately if this DataSource has already been registered |
| if (registeredJmxObjectName != null) { |
| return; |
| } |
| // Return immediately if no JMX name has been specified |
| final String requestedName = getJmxName(); |
| if (requestedName == null) { |
| return; |
| } |
| try { |
| ObjectNameWrapper.wrap(requestedName).registerMBean(this); |
| } catch (final MalformedObjectNameException e) { |
| log.warn("The requested JMX name [" + requestedName + "] was not valid and will be ignored."); |
| } |
| } |
| |
| protected void log(final String message) { |
| if (logWriter != null) { |
| logWriter.println(message); |
| } |
| } |
| |
| @Override |
| public void postDeregister() { |
| // NO-OP |
| } |
| |
| @Override |
| public void postRegister(final Boolean registrationDone) { |
| // NO-OP |
| } |
| |
| @Override |
| public void preDeregister() throws Exception { |
| // NO-OP |
| } |
| |
| @Override |
| public ObjectName preRegister(final MBeanServer server, final ObjectName objectName) { |
| final String requestedName = getJmxName(); |
| if (requestedName != null) { |
| try { |
| registeredJmxObjectName = ObjectNameWrapper.wrap(requestedName); |
| } catch (final MalformedObjectNameException e) { |
| log.warn("The requested JMX name [" + requestedName + "] was not valid and will be ignored."); |
| } |
| } |
| if (registeredJmxObjectName == null) { |
| registeredJmxObjectName = ObjectNameWrapper.wrap(objectName); |
| } |
| return ObjectNameWrapper.unwrap(registeredJmxObjectName); |
| } |
| |
| /** |
| * Removes a custom connection property. |
| * |
| * @param name |
| * Name of the custom connection property to remove |
| * @see #addConnectionProperty(String, String) |
| */ |
| public void removeConnectionProperty(final String name) { |
| connectionProperties.remove(name); |
| } |
| |
| /** |
| * Sets the print writer to be used by this configuration to log information on abandoned objects. |
| * |
| * @param logWriter |
| * The new log writer |
| */ |
| public void setAbandonedLogWriter(final PrintWriter logWriter) { |
| if (abandonedConfig == null) { |
| abandonedConfig = new AbandonedConfig(); |
| } |
| abandonedConfig.setLogWriter(logWriter); |
| final GenericObjectPool<?> gop = this.connectionPool; |
| if (gop != null) { |
| gop.setAbandonedConfig(abandonedConfig); |
| } |
| } |
| |
| /** |
| * If the connection pool implements {@link org.apache.commons.pool2.UsageTracking UsageTracking}, configure whether |
| * the connection pool should record a stack trace every time a method is called on a pooled connection and retain |
| * the most recent stack trace to aid debugging of abandoned connections. |
| * |
| * @param usageTracking |
| * A value of <code>true</code> will enable the recording of a stack trace on every use of a pooled |
| * connection |
| */ |
| public void setAbandonedUsageTracking(final boolean usageTracking) { |
| if (abandonedConfig == null) { |
| abandonedConfig = new AbandonedConfig(); |
| } |
| abandonedConfig.setUseUsageTracking(usageTracking); |
| final GenericObjectPool<?> gop = this.connectionPool; |
| if (gop != null) { |
| gop.setAbandonedConfig(abandonedConfig); |
| } |
| } |
| |
| /** |
| * <p> |
| * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to |
| * the underlying connection. (Default: false) |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param allow |
| * Access to the underlying connection is granted when true. |
| */ |
| public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) { |
| this.accessToUnderlyingConnectionAllowed = allow; |
| } |
| |
| /** |
| * Sets the value of the flag that controls whether or not connections being returned to the pool will be checked |
| * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit |
| * setting is {@code false} when the connection is returned. It is <code>true</code> by default. |
| * |
| * @param autoCommitOnReturn |
| * Whether or not connections being returned to the pool will be checked and configured with auto-commit. |
| * @since 2.6.0 |
| */ |
| public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) { |
| this.autoCommitOnReturn = autoCommitOnReturn; |
| } |
| |
| /** |
| * Sets the state caching flag. |
| * |
| * @param cacheState |
| * The new value for the state caching flag |
| */ |
| public void setCacheState(final boolean cacheState) { |
| this.cacheState = cacheState; |
| } |
| |
| /** |
| * Sets the list of SQL statements to be executed when a physical connection is first created. |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param connectionInitSqls |
| * Collection of SQL statements to execute on connection creation |
| */ |
| public void setConnectionInitSqls(final Collection<String> connectionInitSqls) { |
| if (connectionInitSqls != null && connectionInitSqls.size() > 0) { |
| ArrayList<String> newVal = null; |
| for (final String s : connectionInitSqls) { |
| if (s != null && s.trim().length() > 0) { |
| if (newVal == null) { |
| newVal = new ArrayList<>(); |
| } |
| newVal.add(s); |
| } |
| } |
| this.connectionInitSqls = newVal; |
| } else { |
| this.connectionInitSqls = null; |
| } |
| } |
| |
| // ----------------------------------------------------- DataSource Methods |
| |
| /** |
| * Sets the connection properties passed to driver.connect(...). |
| * <p> |
| * Format of the string must be [propertyName=property;]* |
| * </p> |
| * <p> |
| * NOTE - The "user" and "password" properties will be added explicitly, so they do not need to be included here. |
| * </p> |
| * |
| * @param connectionProperties |
| * the connection properties used to create new connections |
| */ |
| public void setConnectionProperties(final String connectionProperties) { |
| Objects.requireNonNull(connectionProperties, "connectionProperties is null"); |
| final String[] entries = connectionProperties.split(";"); |
| final Properties properties = new Properties(); |
| for (final String entry : entries) { |
| if (entry.length() > 0) { |
| final int index = entry.indexOf('='); |
| if (index > 0) { |
| final String name = entry.substring(0, index); |
| final String value = entry.substring(index + 1); |
| properties.setProperty(name, value); |
| } else { |
| // no value is empty string which is how java.util.Properties works |
| properties.setProperty(entry, ""); |
| } |
| } |
| } |
| this.connectionProperties = properties; |
| } |
| |
| /** |
| * <p> |
| * Sets default auto-commit state of connections returned by this datasource. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param defaultAutoCommit |
| * default auto-commit value |
| */ |
| public void setDefaultAutoCommit(final Boolean defaultAutoCommit) { |
| this.defaultAutoCommit = defaultAutoCommit; |
| } |
| |
| /** |
| * <p> |
| * Sets the default catalog. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param defaultCatalog |
| * the default catalog |
| */ |
| public void setDefaultCatalog(final String defaultCatalog) { |
| if (defaultCatalog != null && defaultCatalog.trim().length() > 0) { |
| this.defaultCatalog = defaultCatalog; |
| } else { |
| this.defaultCatalog = null; |
| } |
| } |
| |
| /** |
| * Sets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this |
| * connection. <code>null</code> means that the driver default will be used. |
| * |
| * @param defaultQueryTimeoutSeconds |
| * The default query timeout in seconds. |
| */ |
| public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) { |
| this.defaultQueryTimeoutSeconds = defaultQueryTimeoutSeconds; |
| } |
| |
| /** |
| * <p> |
| * Sets defaultReadonly property. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param defaultReadOnly |
| * default read-only value |
| */ |
| public void setDefaultReadOnly(final Boolean defaultReadOnly) { |
| this.defaultReadOnly = defaultReadOnly; |
| } |
| |
| /** |
| * <p> |
| * Sets the default schema. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param defaultSchema |
| * the default catalog |
| * @since 2.5.0 |
| */ |
| public void setDefaultSchema(final String defaultSchema) { |
| if (defaultSchema != null && defaultSchema.trim().length() > 0) { |
| this.defaultSchema = defaultSchema; |
| } else { |
| this.defaultSchema = null; |
| } |
| } |
| |
| /** |
| * <p> |
| * Sets the default transaction isolation state for returned connections. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param defaultTransactionIsolation |
| * the default transaction isolation state |
| * @see Connection#getTransactionIsolation |
| */ |
| public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) { |
| this.defaultTransactionIsolation = defaultTransactionIsolation; |
| } |
| |
| /** |
| * Sets the SQL_STATE codes considered to signal fatal conditions. |
| * <p> |
| * Overrides the defaults in {@link Utils#DISCONNECTION_SQL_CODES} (plus anything starting with |
| * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #getFastFailValidation()} |
| * is {@code true}, whenever connections created by this datasource generate exceptions with SQL_STATE codes in this |
| * list, they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at |
| * isValid or validation query). |
| * </p> |
| * <p> |
| * If {@link #getFastFailValidation()} is {@code false} setting this property has no effect. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: {@code getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter}. |
| * </p> |
| * |
| * @param disconnectionSqlCodes |
| * SQL_STATE codes considered to signal fatal conditions |
| * @since 2.1 |
| */ |
| public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) { |
| if (disconnectionSqlCodes != null && disconnectionSqlCodes.size() > 0) { |
| HashSet<String> newVal = null; |
| for (final String s : disconnectionSqlCodes) { |
| if (s != null && s.trim().length() > 0) { |
| if (newVal == null) { |
| newVal = new HashSet<>(); |
| } |
| newVal.add(s); |
| } |
| } |
| this.disconnectionSqlCodes = newVal; |
| } else { |
| this.disconnectionSqlCodes = null; |
| } |
| } |
| |
| /** |
| * Sets the JDBC Driver instance to use for this pool. |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param driver |
| * The JDBC Driver instance to use for this pool. |
| */ |
| public synchronized void setDriver(final Driver driver) { |
| this.driver = driver; |
| } |
| |
| /** |
| * <p> |
| * Sets the class loader to be used to load the JDBC driver. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param driverClassLoader |
| * the class loader with which to load the JDBC driver |
| */ |
| public synchronized void setDriverClassLoader(final ClassLoader driverClassLoader) { |
| this.driverClassLoader = driverClassLoader; |
| } |
| |
| /** |
| * <p> |
| * Sets the JDBC driver class name. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param driverClassName |
| * the class name of the JDBC driver |
| */ |
| public synchronized void setDriverClassName(final String driverClassName) { |
| if (driverClassName != null && driverClassName.trim().length() > 0) { |
| this.driverClassName = driverClassName; |
| } else { |
| this.driverClassName = null; |
| } |
| } |
| |
| /** |
| * Sets the value of the flag that controls whether or not connections being returned to the pool will be checked |
| * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit |
| * setting is {@code false} when the connection is returned. It is <code>true</code> by default. |
| * |
| * @param autoCommitOnReturn |
| * Whether or not connections being returned to the pool will be checked and configured with auto-commit. |
| * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}. |
| */ |
| @Deprecated |
| public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) { |
| this.autoCommitOnReturn = autoCommitOnReturn; |
| } |
| |
| /** |
| * Sets the EvictionPolicy implementation to use with this connection pool. |
| * |
| * @param evictionPolicyClassName |
| * The fully qualified class name of the EvictionPolicy implementation |
| */ |
| public synchronized void setEvictionPolicyClassName(final String evictionPolicyClassName) { |
| if (connectionPool != null) { |
| connectionPool.setEvictionPolicyClassName(evictionPolicyClassName); |
| } |
| this.evictionPolicyClassName = evictionPolicyClassName; |
| } |
| |
| /** |
| * @see #getFastFailValidation() |
| * @param fastFailValidation |
| * true means connections created by this factory will fast fail validation |
| * @since 2.1 |
| */ |
| public void setFastFailValidation(final boolean fastFailValidation) { |
| this.fastFailValidation = fastFailValidation; |
| } |
| |
| /** |
| * <p> |
| * Sets the initial size of the connection pool. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param initialSize |
| * the number of connections created when the pool is initialized |
| */ |
| public synchronized void setInitialSize(final int initialSize) { |
| this.initialSize = initialSize; |
| } |
| |
| /** |
| * Sets the JMX name that has been requested for this DataSource. If the requested name is not valid, an alternative |
| * may be chosen. This DataSource will attempt to register itself using this name. If another component registers |
| * this DataSource with JMX and this name is valid this name will be used in preference to any specified by the |
| * other component. |
| * |
| * @param jmxName |
| * The JMX name that has been requested for this DataSource |
| */ |
| public void setJmxName(final String jmxName) { |
| this.jmxName = jmxName; |
| } |
| |
| /** |
| * Sets the LIFO property. True means the pool behaves as a LIFO queue; false means FIFO. |
| * |
| * @param lifo |
| * the new value for the LIFO property |
| */ |
| public synchronized void setLifo(final boolean lifo) { |
| this.lifo = lifo; |
| if (connectionPool != null) { |
| connectionPool.setLifo(lifo); |
| } |
| } |
| |
| /** |
| * @param logAbandoned |
| * new logAbandoned property value |
| */ |
| public void setLogAbandoned(final boolean logAbandoned) { |
| if (abandonedConfig == null) { |
| abandonedConfig = new AbandonedConfig(); |
| } |
| abandonedConfig.setLogAbandoned(logAbandoned); |
| final GenericObjectPool<?> gop = this.connectionPool; |
| if (gop != null) { |
| gop.setAbandonedConfig(abandonedConfig); |
| } |
| } |
| |
| /** |
| * When {@link #getMaxConnLifetimeMillis()} is set to limit connection lifetime, this property determines whether or |
| * not log messages are generated when the pool closes connections due to maximum lifetime exceeded. Set this |
| * property to false to suppress log messages when connections expire. |
| * |
| * @param logExpiredConnections |
| * Whether or not log messages are generated when the pool closes connections due to maximum lifetime |
| * exceeded. |
| */ |
| public void setLogExpiredConnections(final boolean logExpiredConnections) { |
| this.logExpiredConnections = logExpiredConnections; |
| } |
| |
| /** |
| * <strong>BasicDataSource does NOT support this method. </strong> |
| * |
| * <p> |
| * Set the login timeout (in seconds) for connecting to the database. |
| * </p> |
| * <p> |
| * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool. |
| * </p> |
| * |
| * @param loginTimeout |
| * The new login timeout, or zero for no timeout |
| * @throws UnsupportedOperationException |
| * If the DataSource implementation does not support the login timeout feature. |
| * @throws SQLException |
| * if a database access error occurs |
| */ |
| @Override |
| public void setLoginTimeout(final int loginTimeout) throws SQLException { |
| // This method isn't supported by the PoolingDataSource returned by the createDataSource |
| throw new UnsupportedOperationException("Not supported by BasicDataSource"); |
| } |
| |
| /** |
| * <p> |
| * Sets the log writer being used by this data source. |
| * </p> |
| * <p> |
| * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool. |
| * </p> |
| * |
| * @param logWriter |
| * The new log writer |
| * @throws SQLException |
| * if a database access error occurs |
| */ |
| @Override |
| public void setLogWriter(final PrintWriter logWriter) throws SQLException { |
| createDataSource().setLogWriter(logWriter); |
| this.logWriter = logWriter; |
| } |
| |
| /** |
| * <p> |
| * Sets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an |
| * infinite lifetime. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param maxConnLifetimeMillis |
| * The maximum permitted lifetime of a connection in milliseconds. |
| */ |
| public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { |
| this.maxConnLifetimeMillis = maxConnLifetimeMillis; |
| } |
| |
| /** |
| * Sets the maximum number of connections that can remain idle in the pool. Excess idle connections are destroyed on |
| * return to the pool. |
| * |
| * @see #getMaxIdle() |
| * @param maxIdle |
| * the new value for maxIdle |
| */ |
| public synchronized void setMaxIdle(final int maxIdle) { |
| this.maxIdle = maxIdle; |
| if (connectionPool != null) { |
| connectionPool.setMaxIdle(maxIdle); |
| } |
| } |
| |
| /** |
| * <p> |
| * Sets the value of the <code>maxOpenPreparedStatements</code> property. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param maxOpenStatements |
| * the new maximum number of prepared statements |
| */ |
| public synchronized void setMaxOpenPreparedStatements(final int maxOpenStatements) { |
| this.maxOpenPreparedStatements = maxOpenStatements; |
| } |
| |
| /** |
| * Sets the maximum total number of idle and borrows connections that can be active at the same time. Use a negative |
| * value for no limit. |
| * |
| * @param maxTotal |
| * the new value for maxTotal |
| * @see #getMaxTotal() |
| */ |
| public synchronized void setMaxTotal(final int maxTotal) { |
| this.maxTotal = maxTotal; |
| if (connectionPool != null) { |
| connectionPool.setMaxTotal(maxTotal); |
| } |
| } |
| |
| /** |
| * Sets the MaxWaitMillis property. Use -1 to make the pool wait indefinitely. |
| * |
| * @param maxWaitMillis |
| * the new value for MaxWaitMillis |
| * @see #getMaxWaitMillis() |
| */ |
| public synchronized void setMaxWaitMillis(final long maxWaitMillis) { |
| this.maxWaitMillis = maxWaitMillis; |
| if (connectionPool != null) { |
| connectionPool.setMaxWaitMillis(maxWaitMillis); |
| } |
| } |
| |
| /** |
| * Sets the {@link #minEvictableIdleTimeMillis} property. |
| * |
| * @param minEvictableIdleTimeMillis |
| * the minimum amount of time an object may sit idle in the pool |
| * @see #minEvictableIdleTimeMillis |
| */ |
| public synchronized void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) { |
| this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; |
| if (connectionPool != null) { |
| connectionPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); |
| } |
| } |
| |
| /** |
| * Sets the minimum number of idle connections in the pool. The pool attempts to ensure that minIdle connections are |
| * available when the idle object evictor runs. The value of this property has no effect unless |
| * {@link #timeBetweenEvictionRunsMillis} has a positive value. |
| * |
| * @param minIdle |
| * the new value for minIdle |
| * @see GenericObjectPool#setMinIdle(int) |
| */ |
| public synchronized void setMinIdle(final int minIdle) { |
| this.minIdle = minIdle; |
| if (connectionPool != null) { |
| connectionPool.setMinIdle(minIdle); |
| } |
| } |
| |
| /** |
| * Sets the value of the {@link #numTestsPerEvictionRun} property. |
| * |
| * @param numTestsPerEvictionRun |
| * the new {@link #numTestsPerEvictionRun} value |
| * @see #numTestsPerEvictionRun |
| */ |
| public synchronized void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) { |
| this.numTestsPerEvictionRun = numTestsPerEvictionRun; |
| if (connectionPool != null) { |
| connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun); |
| } |
| } |
| |
| // ------------------------------------------------------ Protected Methods |
| |
| /** |
| * <p> |
| * Sets the {@link #password}. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param password |
| * new value for the password |
| */ |
| public void setPassword(final String password) { |
| this.password = password; |
| } |
| |
| /** |
| * <p> |
| * Sets whether to pool statements or not. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param poolingStatements |
| * pooling on or off |
| */ |
| public synchronized void setPoolPreparedStatements(final boolean poolingStatements) { |
| this.poolPreparedStatements = poolingStatements; |
| } |
| |
| /** |
| * @param removeAbandonedOnBorrow |
| * true means abandoned connections may be removed when connections are borrowed from the pool. |
| * @see #getRemoveAbandonedOnBorrow() |
| */ |
| public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) { |
| if (abandonedConfig == null) { |
| abandonedConfig = new AbandonedConfig(); |
| } |
| abandonedConfig.setRemoveAbandonedOnBorrow(removeAbandonedOnBorrow); |
| final GenericObjectPool<?> gop = this.connectionPool; |
| if (gop != null) { |
| gop.setAbandonedConfig(abandonedConfig); |
| } |
| } |
| |
| /** |
| * @param removeAbandonedOnMaintenance |
| * true means abandoned connections may be removed on pool maintenance. |
| * @see #getRemoveAbandonedOnMaintenance() |
| */ |
| public void setRemoveAbandonedOnMaintenance(final boolean removeAbandonedOnMaintenance) { |
| if (abandonedConfig == null) { |
| abandonedConfig = new AbandonedConfig(); |
| } |
| abandonedConfig.setRemoveAbandonedOnMaintenance(removeAbandonedOnMaintenance); |
| final GenericObjectPool<?> gop = this.connectionPool; |
| if (gop != null) { |
| gop.setAbandonedConfig(abandonedConfig); |
| } |
| } |
| |
| /** |
| * <p> |
| * Sets the timeout in seconds before an abandoned connection can be removed. |
| * </p> |
| * |
| * <p> |
| * Setting this property has no effect if {@link #getRemoveAbandonedOnBorrow()} and |
| * {@link #getRemoveAbandonedOnMaintenance()} are false. |
| * </p> |
| * |
| * @param removeAbandonedTimeout |
| * new abandoned timeout in seconds |
| * @see #getRemoveAbandonedTimeout() |
| * @see #getRemoveAbandonedOnBorrow() |
| * @see #getRemoveAbandonedOnMaintenance() |
| */ |
| public void setRemoveAbandonedTimeout(final int removeAbandonedTimeout) { |
| if (abandonedConfig == null) { |
| abandonedConfig = new AbandonedConfig(); |
| } |
| abandonedConfig.setRemoveAbandonedTimeout(removeAbandonedTimeout); |
| final GenericObjectPool<?> gop = this.connectionPool; |
| if (gop != null) { |
| gop.setAbandonedConfig(abandonedConfig); |
| } |
| } |
| |
| /** |
| * Sets the flag that controls if a connection will be rolled back when it is returned to the pool if auto commit is |
| * not enabled and the connection is not read only. |
| * |
| * @param rollbackOnReturn |
| * whether a connection will be rolled back when it is returned to the pool. |
| */ |
| public void setRollbackOnReturn(final boolean rollbackOnReturn) { |
| this.rollbackOnReturn = rollbackOnReturn; |
| } |
| |
| /** |
| * Sets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the |
| * idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool. |
| * |
| * @param softMinEvictableIdleTimeMillis |
| * minimum amount of time a connection may sit idle in the pool before it is eligible for eviction, |
| * assuming there are minIdle idle connections in the pool. |
| * @see #getSoftMinEvictableIdleTimeMillis |
| */ |
| public synchronized void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) { |
| this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis; |
| if (connectionPool != null) { |
| connectionPool.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis); |
| } |
| } |
| |
| /** |
| * Sets the {@link #testOnBorrow} property. This property determines whether or not the pool will validate objects |
| * before they are borrowed from the pool. |
| * |
| * @param testOnBorrow |
| * new value for testOnBorrow property |
| */ |
| public synchronized void setTestOnBorrow(final boolean testOnBorrow) { |
| this.testOnBorrow = testOnBorrow; |
| if (connectionPool != null) { |
| connectionPool.setTestOnBorrow(testOnBorrow); |
| } |
| } |
| |
| /** |
| * Sets the {@link #testOnCreate} property. This property determines whether or not the pool will validate objects |
| * immediately after they are created by the pool |
| * |
| * @param testOnCreate |
| * new value for testOnCreate property |
| */ |
| public synchronized void setTestOnCreate(final boolean testOnCreate) { |
| this.testOnCreate = testOnCreate; |
| if (connectionPool != null) { |
| connectionPool.setTestOnCreate(testOnCreate); |
| } |
| } |
| |
| /** |
| * Sets the <code>testOnReturn</code> property. This property determines whether or not the pool will validate |
| * objects before they are returned to the pool. |
| * |
| * @param testOnReturn |
| * new value for testOnReturn property |
| */ |
| public synchronized void setTestOnReturn(final boolean testOnReturn) { |
| this.testOnReturn = testOnReturn; |
| if (connectionPool != null) { |
| connectionPool.setTestOnReturn(testOnReturn); |
| } |
| } |
| |
| /** |
| * Sets the <code>testWhileIdle</code> property. This property determines whether or not the idle object evictor |
| * will validate connections. |
| * |
| * @param testWhileIdle |
| * new value for testWhileIdle property |
| */ |
| public synchronized void setTestWhileIdle(final boolean testWhileIdle) { |
| this.testWhileIdle = testWhileIdle; |
| if (connectionPool != null) { |
| connectionPool.setTestWhileIdle(testWhileIdle); |
| } |
| } |
| |
| /** |
| * Sets the {@link #timeBetweenEvictionRunsMillis} property. |
| * |
| * @param timeBetweenEvictionRunsMillis |
| * the new time between evictor runs |
| * @see #timeBetweenEvictionRunsMillis |
| */ |
| public synchronized void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) { |
| this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; |
| if (connectionPool != null) { |
| connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); |
| } |
| } |
| |
| /** |
| * <p> |
| * Sets the {@link #url}. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param url |
| * the new value for the JDBC connection url |
| */ |
| public synchronized void setUrl(final String url) { |
| this.url = url; |
| } |
| |
| /** |
| * <p> |
| * Sets the {@link #userName}. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param userName |
| * the new value for the JDBC connection user name |
| */ |
| public void setUsername(final String userName) { |
| this.userName = userName; |
| } |
| |
| /** |
| * <p> |
| * Sets the {@link #validationQuery}. |
| * </p> |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param validationQuery |
| * the new value for the validation query |
| */ |
| public void setValidationQuery(final String validationQuery) { |
| if (validationQuery != null && validationQuery.trim().length() > 0) { |
| this.validationQuery = validationQuery; |
| } else { |
| this.validationQuery = null; |
| } |
| } |
| |
| /** |
| * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a |
| * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout. |
| * <p> |
| * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first |
| * time one of the following methods is invoked: <code>getConnection, setLogwriter, |
| * setLoginTimeout, getLoginTimeout, getLogWriter.</code> |
| * </p> |
| * |
| * @param validationQueryTimeoutSeconds |
| * new validation query timeout value in seconds |
| */ |
| public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) { |
| this.validationQueryTimeoutSeconds = validationQueryTimeoutSeconds; |
| } |
| |
| /** |
| * Starts the connection pool maintenance task, if configured. |
| */ |
| protected void startPoolMaintenance() { |
| if (connectionPool != null && timeBetweenEvictionRunsMillis > 0) { |
| connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); |
| } |
| } |
| |
| @Override |
| public <T> T unwrap(final Class<T> iface) throws SQLException { |
| throw new SQLException("BasicDataSource is not a wrapper."); |
| } |
| |
| private void updateJmxName(final GenericObjectPoolConfig<?> config) { |
| if (registeredJmxObjectName == null) { |
| return; |
| } |
| final StringBuilder base = new StringBuilder(registeredJmxObjectName.toString()); |
| base.append(Constants.JMX_CONNECTION_POOL_BASE_EXT); |
| config.setJmxNameBase(base.toString()); |
| config.setJmxNamePrefix(Constants.JMX_CONNECTION_POOL_PREFIX); |
| } |
| } |