jmcnally 02/03/17 22:49:32
Modified: jdbc2pool/src/java/org/apache/commons/jdbc2pool
Jdbc2PoolDataSource.java
Log:
modified the mapped properties to follow the format given by commons-beanutils.
added all the properties to the Referenceable and ObjectFactory implementations.
multiple instances with independent pools are now possible and if an instance
is looked up several times in jndi, it will maintain its pool.
reorganization of the properties and javadoc
Revision Changes Path
1.4 +706 -404
jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/Jdbc2PoolDataSource.java
Index: Jdbc2PoolDataSource.java
===================================================================
RCS file:
/home/cvs/jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/Jdbc2PoolDataSource.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Jdbc2PoolDataSource.java 4 Mar 2002 07:52:37 -0000 1.3
+++ Jdbc2PoolDataSource.java 18 Mar 2002 06:49:32 -0000 1.4
@@ -81,7 +81,8 @@
import javax.naming.NamingException;
import javax.naming.spi.ObjectFactory;
-import org.apache.commons.util.ObjectUtils;
+import org.apache.commons.collections.FastHashMap;
+import org.apache.commons.lang.Objects;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
@@ -90,7 +91,7 @@
* ConnectionPoolDataSource.
*
* @author <a href="mailto:[EMAIL PROTECTED]">John D. McNally</a>
- * @version $Id: Jdbc2PoolDataSource.java,v 1.3 2002/03/04 07:52:37 jmcnally Exp $
+ * @version $Id: Jdbc2PoolDataSource.java,v 1.4 2002/03/18 06:49:32 jmcnally Exp $
*/
public class Jdbc2PoolDataSource
implements DataSource, Referenceable, Serializable, ObjectFactory
@@ -99,37 +100,48 @@
"A Connection was already requested from this source, " +
"further initialization is not allowed.";
- /** Pools keyed by username. */
- private static Map pools = new HashMap();
+ public static Map dsInstanceMap = new HashMap();
+ private boolean getConnectionCalled = false;
+
+ private ConnectionPoolDataSource cpds;
/** DataSource Name used to find the ConnectionPoolDataSource */
private String dataSourceName;
+ private boolean defaultAutoCommit;
+ private int defaultMaxActive = 0;
+ private int defaultMaxIdle = 0;
+ private int defaultMaxWait = -1;
+ private boolean defaultReadOnly;
/** Description */
private String description;
-
+ /** Environment that may be used to set up a jndi initial context. */
+ private Properties jndiEnvironment;
/** Login TimeOut in seconds */
private int loginTimeout;
-
- private ConnectionPoolDataSource cpds;
-
/** Log stream */
private PrintWriter logWriter;
+ private Map perUserDefaultAutoCommit;
+ private Map perUserMaxActive;
+ private Map perUserMaxIdle;
+ private Map perUserMaxWait;
+ private Map perUserDefaultReadOnly;
+ private boolean _testOnBorrow;
+ private boolean _testOnReturn;
+ private int _timeBetweenEvictionRunsMillis;
+ private int _numTestsPerEvictionRun;
+ private int _minEvictableIdleTimeMillis;
+ private boolean _testWhileIdle;
+ private String validationQuery = null;
- /** Environment that may be used to set up a jndi initial context. */
- private Properties jndiEnvironment;
-
-
- private int logInterval;
- private boolean defaultAutoCommit;
- private boolean defaultReadOnly;
-
- private boolean getConnectionCalled = false;
+ private boolean isNew;
+ private Integer instanceKey;
/**
* Default no-arg constructor for Serialization
*/
public Jdbc2PoolDataSource()
{
+ isNew = true;
}
/**
@@ -147,41 +159,126 @@
// -------------------------------------------------------------------
// Properties
-
+
+ /**
+ * Get the value of connectionPoolDataSource. This method will return
+ * null, if the backing datasource is being accessed via jndi.
+ *
+ * @return value of connectionPoolDataSource.
+ */
+ public ConnectionPoolDataSource getConnectionPoolDataSource()
+ {
+ return cpds;
+ }
+
+ /**
+ * Set the backend ConnectionPoolDataSource. This property should not be
+ * set if using jndi to access the datasource.
+ *
+ * @param v Value to assign to connectionPoolDataSource.
+ */
+ public void setConnectionPoolDataSource(ConnectionPoolDataSource v)
+ {
+ this.cpds = v;
+ }
+
+ /**
+ * Get the name of the ConnectionPoolDataSource which backs this pool.
+ * This name is used to look up the datasource from a jndi service
+ * provider.
+ *
+ * @return value of dataSourceName.
+ */
+ public String getDataSourceName()
+ {
+ return dataSourceName;
+ }
+
+ /**
+ * Set the name of the ConnectionPoolDataSource which backs this pool.
+ * This name is used to look up the datasource from a jndi service
+ * provider.
+ *
+ * @param v Value to assign to dataSourceName.
+ */
+ public void setDataSourceName(String v)
+ {
+ this.dataSourceName = v;
+ }
+
+
+ /**
+ * Get the value of defaultAutoCommit, which defines the state of
+ * connections handed out from this pool. The value can be changed
+ * on the Connection using Connection.setAutoCommit(boolean).
+ * The default is true.
+ *
+ * @return value of defaultAutoCommit.
+ */
+ public boolean isDefaultAutoCommit()
+ {
+ return defaultAutoCommit;
+ }
+
+ /**
+ * Set the value of defaultAutoCommit, which defines the state of
+ * connections handed out from this pool. The value can be changed
+ * on the Connection using Connection.setAutoCommit(boolean).
+ * The default is true.
+ *
+ * @param v Value to assign to defaultAutoCommit.
+ */
+ public void setDefaultAutoCommit(boolean v)
+ {
+ assertInitializationAllowed();
+ this.defaultAutoCommit = v;
+ }
+
+
/**
* The maximum number of active connections that can be allocated from
* this pool at the same time, or zero for no limit.
* This value is used for any username which is not specified
* in perUserMaxConnections. The default is 0.
*/
- private int defaultMaxActive = 0;
-
public int getDefaultMaxActive() {
return (this.defaultMaxActive);
}
+ /**
+ * The maximum number of active connections that can be allocated from
+ * this pool at the same time, or zero for no limit.
+ * This value is used for any username which is not specified
+ * in perUserMaxConnections. The default is 0.
+ */
public void setDefaultMaxActive(int maxActive) {
assertInitializationAllowed();
this.defaultMaxActive = maxActive;
}
+
/**
* The maximum number of active connections that can remain idle in the
* pool, without extra ones being released, or zero for no limit.
* This value is used for any username which is not specified
* in perUserMaxIdle. The default is 0.
*/
- private int defaultMaxIdle = 0;
-
public int getDefaultMaxIdle() {
return (this.defaultMaxIdle);
}
+ /**
+ * The maximum number of active connections that can remain idle in the
+ * pool, without extra ones being released, or zero for no limit.
+ * This value is used for any username which is not specified
+ * in perUserMaxIdle. The default is 0.
+ */
public void setDefaultMaxIdle(int defaultMaxIdle) {
assertInitializationAllowed();
this.defaultMaxIdle = defaultMaxIdle;
}
+
/**
* The maximum number of milliseconds that the pool will wait (when there
* are no available connections) for a connection to be returned before
@@ -189,211 +286,306 @@
* This value is used for any username which is not specified
* in perUserMaxWait. The default is -1.
*/
- private int defaultMaxWait = -1;
-
public int getDefaultMaxWait() {
return (this.defaultMaxWait);
}
+ /**
+ * 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 -1 to wait indefinitely.
+ * This value is used for any username which is not specified
+ * in perUserMaxWait. The default is -1.
+ */
public void setDefaultMaxWait(int defaultMaxWait) {
assertInitializationAllowed();
this.defaultMaxWait = defaultMaxWait;
}
- private Properties perUserMaxActive;
+
/**
- * The maximum number of active connections that can be allocated from
- * this pool at the same time, or zero for no limit.
- * The keys are usernames and the value is the maximum connections. Any
- * username specified here will override the value of defaultMaxActive.
+ * Get the value of defaultReadOnly, which defines the state of
+ * connections handed out from this pool. The value can be changed
+ * on the Connection using Connection.setReadOnly(boolean).
+ * The default is false.
+ *
+ * @return value of defaultReadOnly.
*/
- public Properties getPerUserMaxActive()
+ public boolean isDefaultReadOnly()
{
- return perUserMaxActive;
+ return defaultReadOnly;
}
/**
- * The maximum number of active connections that can be allocated from
- * this pool at the same time, or zero for no limit.
- * The keys are usernames and the value is the maximum connections. Any
- * username specified here will override the value of defaultMaxActive.
+ * Set the value of defaultReadOnly, which defines the state of
+ * connections handed out from this pool. The value can be changed
+ * on the Connection using Connection.setReadOnly(boolean).
+ * The default is false.
+ *
+ * @param v Value to assign to defaultReadOnly.
*/
- public void setPerUserMaxActive(Properties v)
+ public void setDefaultReadOnly(boolean v)
{
assertInitializationAllowed();
- this.perUserMaxActive = v;
+ this.defaultReadOnly = v;
}
- private Properties perUserMaxIdle;
+
/**
- * The maximum number of active connections that can remain idle in the
- * pool, without extra ones being released, or zero for no limit.
- * The keys are usernames and the value is the maximum connections. Any
- * username specified here will override the value of defaultMaxIdle.
+ * Get the description. This property is defined by jdbc as for use with
+ * GUI (or other) tools that might deploy the datasource. It serves no
+ * internal purpose.
+ *
+ * @return value of description.
*/
- public Properties getPerUserMaxIdle()
+ public String getDescription()
{
- return perUserMaxIdle;
+ return description;
}
/**
- * The maximum number of active connections that can remain idle in the
- * pool, without extra ones being released, or zero for no limit.
- * The keys are usernames and the value is the maximum connections. Any
- * username specified here will override the value of defaultMaxIdle.
+ * Set the description. This property is defined by jdbc as for use with
+ * GUI (or other) tools that might deploy the datasource. It serves no
+ * internal purpose.
+ *
+ * @param v Value to assign to description.
*/
- public void setPerUserMaxIdle(Properties v)
+ public void setDescription(String v)
{
- assertInitializationAllowed();
- this.perUserMaxIdle = v;
+ this.description = v;
}
-
- private Properties perUserMaxWait;
+
+
/**
- * 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 -1 to wait indefinitely.
- * The keys are usernames and the value is the maximum connections. Any
- * username specified here will override the value of defaultMaxWait.
+ * Get the value of jndiEnvironment which is used when instantiating
+ * a jndi InitialContext. This InitialContext is used to locate the
+ * backend ConnectionPoolDataSource.
+ *
+ * @return value of jndiEnvironment.
*/
- public Properties getPerUserMaxWait()
+ public String getJndiEnvironment(String key)
{
- return perUserMaxWait;
+ String value = null;
+ if (jndiEnvironment != null)
+ {
+ value = jndiEnvironment.getProperty(key);
+ }
+ return value;
}
/**
- * 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 -1 to wait indefinitely.
- * The keys are usernames and the value is the maximum connections. Any
- * username specified here will override the value of defaultMaxWait.
+ * Set the value of jndiEnvironment which is used when instantiating
+ * a jndi InitialContext. This InitialContext is used to locate the
+ * backend ConnectionPoolDataSource.
+ *
+ * @param v Value to assign to jndiEnvironment.
*/
- public void setPerUserMaxWait(Properties v)
+ public void setJndiEnvironment(String key, String value)
{
- assertInitializationAllowed();
- this.perUserMaxWait = v;
+ if (jndiEnvironment == null)
+ {
+ jndiEnvironment = new Properties();
+ }
+ jndiEnvironment.setProperty(key, value);
}
+
/**
- * Get the interval (in seconds) between which the ConnectionPool logs
- * the status of it's Connections. Default is 0 which indicates no
- * logging.
- *
- * @return value of logInterval.
+ * Get the value of loginTimeout.
+ * @return value of loginTimeout.
*/
- public int getLogInterval()
+ public int getLoginTimeout()
{
- return logInterval;
+ return loginTimeout;
}
/**
- * Set the interval (in seconds) between which the ConnectionPool logs
- * the status of it's Connections. Default is 0 which indicates no
- * logging.
- *
- * @param v Value to assign to logInterval.
+ * Set the value of loginTimeout.
+ * @param v Value to assign to loginTimeout.
*/
- public void setLogInterval(int v)
+ public void setLoginTimeout(int v)
{
- this.logInterval = v;
+ this.loginTimeout = v;
}
- /**
- * Get the value of defaultAutoCommit, which defines the state of
- * connections handed out from this pool. The value can be changed
- * on the Connection using Connection.setAutoCommit(boolean).
- * The default is true.
- *
- * @return value of defaultAutoCommit.
+
+ /**
+ * Get the value of logWriter.
+ * @return value of logWriter.
*/
- public boolean isDefaultAutoCommit()
+ public PrintWriter getLogWriter()
{
- return defaultAutoCommit;
+ return logWriter;
}
/**
- * Set the value of defaultAutoCommit, which defines the state of
- * connections handed out from this pool. The value can be changed
- * on the Connection using Connection.setAutoCommit(boolean).
- * The default is true.
- *
- * @param v Value to assign to defaultAutoCommit.
+ * Set the value of logWriter.
+ * @param v Value to assign to logWriter.
*/
- public void setDefaultAutoCommit(boolean v)
+ public void setLogWriter(PrintWriter v)
{
- assertInitializationAllowed();
- this.defaultAutoCommit = v;
+ this.logWriter = v;
}
+
- private Properties perUserDefaultAutoCommit;
/**
* The keys are usernames and the value is the --. Any
* username specified here will override the value of defaultAutoCommit.
*/
- public Properties getPerUserDefaultAutoCommit()
+ public Boolean getPerUserDefaultAutoCommit(String key)
{
- return perUserDefaultAutoCommit;
+ Boolean value = null;
+ if (perUserDefaultAutoCommit != null)
+ {
+ value = (Boolean)perUserDefaultAutoCommit.get(key);
+ }
+ return value;
}
/**
* The keys are usernames and the value is the --. Any
* username specified here will override the value of defaultAutoCommit.
*/
- public void setPerUserDefaultAutoCommit(Properties v)
+ public void setPerUserDefaultAutoCommit(String username, Boolean value)
{
assertInitializationAllowed();
- this.perUserDefaultAutoCommit = v;
+ if (perUserDefaultAutoCommit == null)
+ {
+ perUserDefaultAutoCommit = new HashMap();
+ }
+ perUserDefaultAutoCommit.put(username, value);
}
-
- private Properties perUserDefaultReadOnly;
+
/**
- * Get the value of defaultReadOnly, which defines the state of
- * connections handed out from this pool. The value can be changed
- * on the Connection using Connection.setReadOnly(boolean).
- * The default is false.
- *
- * @return value of defaultReadOnly.
+ * The maximum number of active connections that can be allocated from
+ * this pool at the same time, or zero for no limit.
+ * The keys are usernames and the value is the maximum connections. Any
+ * username specified here will override the value of defaultMaxActive.
*/
- public boolean isDefaultReadOnly()
+ public Integer getPerUserMaxActive(String username)
{
- return defaultReadOnly;
+ Integer value = null;
+ if (perUserMaxActive != null)
+ {
+ value = (Integer)perUserMaxActive.get(username);
+ }
+ return value;
}
/**
- * Set the value of defaultReadOnly, which defines the state of
- * connections handed out from this pool. The value can be changed
- * on the Connection using Connection.setReadOnly(boolean).
- * The default is false.
- *
- * @param v Value to assign to defaultReadOnly.
+ * The maximum number of active connections that can be allocated from
+ * this pool at the same time, or zero for no limit.
+ * The keys are usernames and the value is the maximum connections. Any
+ * username specified here will override the value of defaultMaxActive.
*/
- public void setDefaultReadOnly(boolean v)
+ public void setPerUserMaxActive(String username, Integer value)
{
assertInitializationAllowed();
- this.defaultReadOnly = v;
+ if (perUserMaxActive == null)
+ {
+ perUserMaxActive = new HashMap();
+ }
+ perUserMaxActive.put(username, value);
+ }
+
+
+ /**
+ * The maximum number of active connections that can remain idle in the
+ * pool, without extra ones being released, or zero for no limit.
+ * The keys are usernames and the value is the maximum connections. Any
+ * username specified here will override the value of defaultMaxIdle.
+ */
+ public Integer getPerUserMaxIdle(String username)
+ {
+ Integer value = null;
+ if (perUserMaxIdle != null)
+ {
+ value = (Integer)perUserMaxIdle.get(username);
+ }
+ return value;
}
/**
+ * The maximum number of active connections that can remain idle in the
+ * pool, without extra ones being released, or zero for no limit.
+ * The keys are usernames and the value is the maximum connections. Any
+ * username specified here will override the value of defaultMaxIdle.
+ */
+ public void setPerUserMaxIdle(String username, Integer value)
+ {
+ assertInitializationAllowed();
+ if (perUserMaxIdle == null)
+ {
+ perUserMaxIdle = new HashMap();
+ }
+ perUserMaxIdle.put(username, value);
+ }
+
+ /**
+ * 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 -1 to wait indefinitely.
+ * The keys are usernames and the value is the maximum connections. Any
+ * username specified here will override the value of defaultMaxWait.
+ */
+ public Integer getPerUserMaxWait(String username)
+ {
+ Integer value = null;
+ if (perUserMaxWait != null)
+ {
+ value = (Integer)perUserMaxWait.get(username);
+ }
+ return value;
+ }
+
+ /**
+ * 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 -1 to wait indefinitely.
+ * The keys are usernames and the value is the maximum connections. Any
+ * username specified here will override the value of defaultMaxWait.
+ */
+ public void setPerUserMaxWait(String username, Integer value)
+ {
+ assertInitializationAllowed();
+ if (perUserMaxWait == null)
+ {
+ perUserMaxWait = new HashMap();
+ }
+ perUserMaxWait.put(username, value);
+ }
+
+
+ /**
* The keys are usernames and the value is the --. Any
* username specified here will override the value of defaultReadOnly.
*/
- public Properties getPerUserDefaultReadOnly()
+ public Boolean getPerUserDefaultReadOnly(String username)
{
- return perUserDefaultReadOnly;
+ Boolean value = null;
+ if (perUserDefaultReadOnly != null)
+ {
+ value = (Boolean)perUserDefaultReadOnly.get(username);
+ }
+ return value;
}
/**
* The keys are usernames and the value is the --. Any
* username specified here will override the value of defaultReadOnly.
*/
- public void setPerUserDefaultReadOnly(Properties v)
+ public void setPerUserDefaultReadOnly(String username, Boolean value)
{
assertInitializationAllowed();
- this.perUserDefaultReadOnly = v;
+ if (perUserDefaultReadOnly == null)
+ {
+ perUserDefaultReadOnly = new HashMap();
+ }
+ perUserDefaultReadOnly.put(username, value);
}
- boolean _testOnBorrow;
+
/**
* When <tt>true</tt>, objects will be
* {*link PoolableObjectFactory#validateObject validated}
@@ -423,7 +615,6 @@
_testOnBorrow = testOnBorrow;
}
- boolean _testOnReturn;
/**
* When <tt>true</tt>, objects will be
* {*link PoolableObjectFactory#validateObject validated}
@@ -449,7 +640,6 @@
_testOnReturn = testOnReturn;
}
- long _timeBetweenEvictionRunsMillis;
/**
* Returns the number of milliseconds to sleep between runs of the
* idle object evictor thread.
@@ -458,7 +648,7 @@
*
* *see #setTimeBetweenEvictionRunsMillis
*/
- public synchronized long getTimeBetweenEvictionRunsMillis() {
+ public int getTimeBetweenEvictionRunsMillis() {
return _timeBetweenEvictionRunsMillis;
}
@@ -470,13 +660,12 @@
*
* *see #getTimeBetweenEvictionRunsMillis
*/
- public synchronized void
- setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
+ public void
+ setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
assertInitializationAllowed();
_timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
}
- int _numTestsPerEvictionRun;
/**
* Returns the number of objects to examine during each run of the
* idle object evictor thread (if any).
@@ -504,177 +693,85 @@
_numTestsPerEvictionRun = numTestsPerEvictionRun;
}
- int _minEvictableIdleTimeMillis;
- /**
- * Returns the minimum amount of time an object may sit idle in the pool
- * before it is eligable for eviction by the idle object evictor
- * (if any).
- *
- * *see #setMinEvictableIdleTimeMillis
- * *see #setTimeBetweenEvictionRunsMillis
- */
- public synchronized int getMinEvictableIdleTimeMillis() {
- return _minEvictableIdleTimeMillis;
- }
-
- /**
- * Sets the minimum amount of time an object may sit idle in the pool
- * before it is eligable for eviction by the idle object evictor
- * (if any).
- * When non-positive, no objects will be evicted from the pool
- * due to idle time alone.
- *
- * *see #getMinEvictableIdleTimeMillis
- * *see #setTimeBetweenEvictionRunsMillis
- */
- public synchronized void
- setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
- assertInitializationAllowed();
- _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
- }
-
- boolean _testWhileIdle;
- /**
- * When <tt>true</tt>, objects will be
- * {*link PoolableObjectFactory#validateObject validated}
- * by the idle object evictor (if any). If an object
- * fails to validate, it will be dropped from the pool.
- *
- * *see #setTestWhileIdle
- * *see #setTimeBetweenEvictionRunsMillis
- */
- public boolean getTestWhileIdle() {
- return _testWhileIdle;
- }
-
- /**
- * When <tt>true</tt>, objects will be
- * {*link PoolableObjectFactory#validateObject validated}
- * by the idle object evictor (if any). If an object
- * fails to validate, it will be dropped from the pool.
- *
- * *see #getTestWhileIdle
- * *see #setTimeBetweenEvictionRunsMillis
- */
- public void setTestWhileIdle(boolean testWhileIdle) {
- assertInitializationAllowed();
- _testWhileIdle = testWhileIdle;
- }
-
-
- /**
- * 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.
- */
- private String validationQuery = null;
-
- public String getValidationQuery() {
- return (this.validationQuery);
- }
-
- public void setValidationQuery(String validationQuery) {
- assertInitializationAllowed();
- this.validationQuery = validationQuery;
- }
-
-
- /**
- * Get the name of the ConnectionPoolDataSource which backs this pool.
- * This name is used to look up the datasource from a jndi service
- * provider.
- *
- * @return value of dataSourceName.
- */
- public String getDataSourceName()
- {
- return dataSourceName;
- }
-
- /**
- * Set the name of the ConnectionPoolDataSource which backs this pool.
- * This name is used to look up the datasource from a jndi service
- * provider.
- *
- * @param v Value to assign to dataSourceName.
- */
- public void setDataSourceName(String v)
- {
- this.dataSourceName = v;
- }
-
-
- /**
- * Get the description. This property is defined by jdbc as for use with
- * GUI (or other) tools that might deploy the datasource. It serves no
- * internal purpose.
+ /**
+ * Returns the minimum amount of time an object may sit idle in the pool
+ * before it is eligable for eviction by the idle object evictor
+ * (if any).
*
- * @return value of description.
+ * *see #setMinEvictableIdleTimeMillis
+ * *see #setTimeBetweenEvictionRunsMillis
*/
- public String getDescription()
- {
- return description;
+ public int getMinEvictableIdleTimeMillis() {
+ return _minEvictableIdleTimeMillis;
}
-
+
/**
- * Set the description. This property is defined by jdbc as for use with
- * GUI (or other) tools that might deploy the datasource. It serves no
- * internal purpose.
- *
- * @param v Value to assign to description.
+ * Sets the minimum amount of time an object may sit idle in the pool
+ * before it is eligable for eviction by the idle object evictor
+ * (if any).
+ * When non-positive, no objects will be evicted from the pool
+ * due to idle time alone.
+ *
+ * *see #getMinEvictableIdleTimeMillis
+ * *see #setTimeBetweenEvictionRunsMillis
*/
- public void setDescription(String v)
- {
- this.description = v;
+ public void
+ setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
+ assertInitializationAllowed();
+ _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
}
-
+
/**
- * Get the value of jndiEnvironment which is used when instantiating
- * a jndi InitialContext. This InitialContext is used to locate the
- * backend ConnectionPoolDataSource.
+ * When <tt>true</tt>, objects will be
+ * {*link PoolableObjectFactory#validateObject validated}
+ * by the idle object evictor (if any). If an object
+ * fails to validate, it will be dropped from the pool.
*
- * @return value of jndiEnvironment.
+ * *see #setTestWhileIdle
+ * *see #setTimeBetweenEvictionRunsMillis
*/
- public Properties getJndiEnvironment()
- {
- return jndiEnvironment;
+ public boolean getTestWhileIdle() {
+ return _testWhileIdle;
}
-
+
/**
- * Set the value of jndiEnvironment which is used when instantiating
- * a jndi InitialContext. This InitialContext is used to locate the
- * backend ConnectionPoolDataSource.
+ * When <tt>true</tt>, objects will be
+ * {*link PoolableObjectFactory#validateObject validated}
+ * by the idle object evictor (if any). If an object
+ * fails to validate, it will be dropped from the pool.
*
- * @param v Value to assign to jndiEnvironment.
+ * *see #getTestWhileIdle
+ * *see #setTimeBetweenEvictionRunsMillis
*/
- public void setJndiEnvironment(Properties v)
- {
- this.jndiEnvironment = v;
+ public void setTestWhileIdle(boolean testWhileIdle) {
+ assertInitializationAllowed();
+ _testWhileIdle = testWhileIdle;
}
-
+
+
/**
- * Get the value of connectionPoolDataSource. This method will return
- * null, if the backing datasource is being accessed via jndi.
- *
- * @return value of connectionPoolDataSource.
+ * 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.
*/
- public ConnectionPoolDataSource getConnectionPoolDataSource()
- {
- return cpds;
+ public String getValidationQuery() {
+ return (this.validationQuery);
}
-
+
/**
- * Set the backend ConnectionPoolDataSource. This property should not be
- * set if using jndi to access the datasource.
- *
- * @param v Value to assign to connectionPoolDataSource.
+ * 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.
*/
- public void setConnectionPoolDataSource(ConnectionPoolDataSource v)
- {
- this.cpds = v;
+ public void setValidationQuery(String validationQuery) {
+ assertInitializationAllowed();
+ this.validationQuery = validationQuery;
}
-
+
+ // ----------------------------------------------------------------------
+ // DataSource implementation
/**
* Attempt to establish a database connection.
@@ -684,15 +781,20 @@
{
return getConnection(null, null);
}
-
+
+ private int connectioncalls=0;
/**
* Attempt to establish a database connection.
*/
- synchronized public Connection getConnection(String username,
- String password)
+ public Connection getConnection(String username, String password)
throws SQLException
{
getConnectionCalled = true;
+ if (isNew)
+ {
+ registerInstance();
+ }
+ Map pools = (Map)dsInstanceMap.get(instanceKey);
String key = getKey(username);
ObjectPool pool = (ObjectPool)pools.get(key);
if ( pool == null )
@@ -711,27 +813,25 @@
Connection con =
((PooledConnection)pool.borrowObject()).getConnection();
- // FIXME! this could be more efficient
boolean defaultAutoCommit = isDefaultAutoCommit();
if ( username != null )
{
- String userMax =
- (String)getPerUserDefaultAutoCommit().get(username);
+ Boolean userMax =
+ getPerUserDefaultAutoCommit(username);
if ( userMax != null )
{
- defaultAutoCommit = Boolean.getBoolean(userMax);
+ defaultAutoCommit = userMax.booleanValue();
}
}
- // FIXME! this could be more efficient
boolean defaultReadOnly = isDefaultReadOnly();
if ( username != null )
{
- String userMax =
- (String)getPerUserDefaultReadOnly().get(username);
+ Boolean userMax =
+ getPerUserDefaultReadOnly(username);
if ( userMax != null )
{
- defaultReadOnly = Boolean.getBoolean(userMax);
+ defaultReadOnly = userMax.booleanValue();
}
}
@@ -750,42 +850,59 @@
return key;
}
+ synchronized private void registerInstance()
+ {
+ if (isNew)
+ {
+ int max = 0;
+ Iterator i = dsInstanceMap.keySet().iterator();
+ while (i.hasNext())
+ {
+ int key = ((Integer)i.next()).intValue();
+ max = Math.max(max, key);
+ }
+ instanceKey = new Integer(max+1);
+ FastHashMap fhm = new FastHashMap();
+ fhm.setFast(true);
+ dsInstanceMap.put(instanceKey, fhm);
+ isNew = false;
+ }
+ }
+
synchronized private void registerPool(String username, String password)
throws javax.naming.NamingException
{
+ Map pools = (Map)dsInstanceMap.get(instanceKey);
String key = getKey(username);
if ( !pools.containsKey(key) )
{
int maxActive = getDefaultMaxActive();
if ( username != null )
{
- String userMax =
- (String)getPerUserMaxActive().get(username);
+ Integer userMax = getPerUserMaxActive(username);
if ( userMax != null )
{
- maxActive = Integer.parseInt(userMax);
+ maxActive = userMax.intValue();
}
}
int maxIdle = getDefaultMaxIdle();
if ( username != null )
{
- String userMax =
- (String)getPerUserMaxIdle().get(username);
+ Integer userMax = getPerUserMaxIdle(username);
if ( userMax != null )
{
- maxIdle = Integer.parseInt(userMax);
+ maxIdle = userMax.intValue();
}
}
int maxWait = getDefaultMaxWait();
if ( username != null )
{
- String userMax =
- (String)getPerUserMaxIdle().get(username);
+ Integer userMax = getPerUserMaxIdle(username);
if ( userMax != null )
{
- maxWait = Integer.parseInt(userMax);
+ maxWait = userMax.intValue();
}
}
@@ -794,7 +911,13 @@
pool.setMaxActive(maxActive);
pool.setMaxIdle(maxIdle);
pool.setMaxWait(maxWait);
- // FIXME! set the rest of the properties
+ pool.setTestOnBorrow(getTestOnBorrow());
+ pool.setTestOnReturn(getTestOnReturn());
+ pool.setTimeBetweenEvictionRunsMillis(
+ getTimeBetweenEvictionRunsMillis());
+ pool.setNumTestsPerEvictionRun(getNumTestsPerEvictionRun());
+ pool.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());
+ pool.setTestWhileIdle(getTestWhileIdle());
ConnectionPoolDataSource cpds = this.cpds;
if ( cpds == null )
@@ -811,81 +934,56 @@
cpds = (ConnectionPoolDataSource)ctx.lookup(dataSourceName);
}
- // Set up the factory we will use
- CPDSConnectionFactory connectionFactory =
- new CPDSConnectionFactory(cpds, pool, validationQuery,
- username, password);
+ // Set up the factory we will use (passing the pool associates
+ // the factory with the pool, so we do not have to do so
+ // explicitly)
+ new CPDSConnectionFactory(cpds, pool, validationQuery,
+ username, password);
- // avoid ConcurrentModificationException
- Map newPools = new HashMap(pools);
- newPools.put(key, pool);
- pools = newPools;
+ // pools is a FastHashMap set to put the pool in a thread-safe way
+ pools.put(key, pool);
}
}
- /**
- * Gets the maximum time in seconds that this data source can wait
- * while attempting to connect to a database.
- */
- public int getLoginTimeout()
- {
- return loginTimeout;
- }
-
- /**
- * Get the log writer for this data source.
- */
- public PrintWriter getLogWriter()
- {
- return logWriter;
- }
-
- /**
- * Sets the maximum time in seconds that this data source will wait
- * while attempting to connect to a database. NOT USED.
- */
- public void setLoginTimeout(int seconds)
- {
- loginTimeout = seconds;
- }
-
- /**
- * Set the log writer for this data source. NOT USED.
- */
- public void setLogWriter(java.io.PrintWriter out)
- {
- logWriter = out;
- }
+
+ // ----------------------------------------------------------------------
+ // Referenceable implementation
/**
- * <CODE>Referenceable</CODE> implementation.
+ * <CODE>Referenceable</CODE> implementation prepares object for
+ * binding in jndi.
*/
public Reference getReference()
throws NamingException
{
+ // this class implements its own factory
String factory = getClass().getName();
-
Reference ref = new Reference(getClass().getName(), factory, null);
+ ref.add(new StringRefAddr("isNew",
+ String.valueOf(isNew)));
+ ref.add(new StringRefAddr("instanceKey",
+ (instanceKey == null ? null : instanceKey.toString()) ));
+ ref.add(new StringRefAddr("dataSourceName", getDataSourceName()));
+ ref.add(new StringRefAddr("defaultAutoCommit",
+ String.valueOf(isDefaultAutoCommit())));
ref.add(new StringRefAddr("defaultMaxActive",
String.valueOf(getDefaultMaxActive())));
ref.add(new StringRefAddr("defaultMaxIdle",
String.valueOf(getDefaultMaxIdle())));
ref.add(new StringRefAddr("defaultMaxWait",
String.valueOf(getDefaultMaxWait())));
- // FIXME! more properties
- ref.add(new StringRefAddr("logInterval",
- String.valueOf(getLogInterval())));
- ref.add(new StringRefAddr("dataSourceName", getDataSourceName()));
+ ref.add(new StringRefAddr("defaultReadOnly",
+ String.valueOf(isDefaultReadOnly())));
ref.add(new StringRefAddr("description", getDescription()));
byte[] ser = null;
// BinaryRefAddr does not allow null byte[].
- if ( getJndiEnvironment() != null )
+ if ( jndiEnvironment != null )
{
try
{
- ser = serialize(getJndiEnvironment());
+ ser = serialize(jndiEnvironment);
ref.add(new BinaryRefAddr("jndiEnvironment", ser));
}
catch (IOException ioe)
@@ -895,27 +993,28 @@
}
}
- // BinaryRefAddr does not allow null byte[].
- if ( getPerUserMaxActive() != null )
+ ref.add(new StringRefAddr("loginTimeout",
+ String.valueOf(getLoginTimeout())));
+
+ if ( perUserDefaultAutoCommit != null )
{
try
{
- ser = serialize(getPerUserMaxActive());
- ref.add(new BinaryRefAddr("perUserMaxActive", ser));
+ ser = serialize((Serializable)perUserDefaultAutoCommit);
+ ref.add(new BinaryRefAddr("perUserDefaultAutoCommit", ser));
}
catch (IOException ioe)
{
throw new NamingException("An IOException prevented " +
- "serializing the perUserMaxConnections properties.");
+ "serializing the perUserDefaultAutoCommit properties.");
}
}
- // BinaryRefAddr does not allow null byte[].
- if ( getPerUserMaxActive() != null )
+ if ( perUserMaxActive != null )
{
try
{
- ser = serialize(getPerUserMaxActive());
+ ser = serialize((Serializable)perUserMaxActive);
ref.add(new BinaryRefAddr("perUserMaxActive", ser));
}
catch (IOException ioe)
@@ -924,61 +1023,72 @@
"serializing the perUserMaxActive properties.");
}
}
-
- return ref;
- }
+ if ( perUserMaxIdle != null )
+ {
+ try
+ {
+ ser = serialize((Serializable)perUserMaxIdle);
+ ref.add(new BinaryRefAddr("perUserMaxIdle", ser));
+ }
+ catch (IOException ioe)
+ {
+ throw new NamingException("An IOException prevented " +
+ "serializing the perUserMaxIdle properties.");
+ }
+ }
- /**
- * implements ObjectFactory to create an instance of this class
- */
- public Object getObjectInstance(Object refObj, Name name,
- Context context, Hashtable env)
- throws Exception
- {
- Reference ref = (Reference)refObj;
-
- if (ref.getClassName().equals(getClass().getName()))
- {
- setDefaultMaxActive(Integer.parseInt(
- (String)ref.get("defaultMaxActive").getContent()));
- setLogInterval(Integer.parseInt(
- (String)ref.get("logInterval").getContent()));
- setDataSourceName((String)ref.get("dataSourceName").getContent());
- setDescription((String)ref.get("description").getContent());
-
- RefAddr refAddr = ref.get("jndiEnvironment");
- if ( refAddr != null )
- {
- byte[] serialized = (byte[])refAddr.getContent();
- setJndiEnvironment(
- (Properties)ObjectUtils.deserialize(serialized) );
- }
-
- refAddr = ref.get("perUserMaxActive");
- if ( refAddr != null )
- {
- byte[] serialized = (byte[])refAddr.getContent();
- setPerUserMaxActive(
- (Properties)ObjectUtils.deserialize(serialized) );
+ if ( perUserMaxWait != null )
+ {
+ try
+ {
+ ser = serialize((Serializable)perUserMaxWait);
+ ref.add(new BinaryRefAddr("perUserMaxWait", ser));
+ }
+ catch (IOException ioe)
+ {
+ throw new NamingException("An IOException prevented " +
+ "serializing the perUserMaxWait properties.");
}
-
- return this;
}
- else
- {
- // We can't create an instance of the reference
- return null;
+
+ if ( perUserDefaultReadOnly != null )
+ {
+ try
+ {
+ ser = serialize((Serializable)perUserDefaultReadOnly);
+ ref.add(new BinaryRefAddr("perUserDefaultReadOnly", ser));
+ }
+ catch (IOException ioe)
+ {
+ throw new NamingException("An IOException prevented " +
+ "serializing the perUserDefaultReadOnly properties.");
+ }
}
+
+ ref.add(new StringRefAddr("testOnBorrow",
+ String.valueOf(getTestOnBorrow())));
+ ref.add(new StringRefAddr("testOnReturn",
+ String.valueOf(getTestOnReturn())));
+ ref.add(new StringRefAddr("timeBetweenEvictionRunsMillis",
+ String.valueOf(getTimeBetweenEvictionRunsMillis())));
+ ref.add(new StringRefAddr("numTestsPerEvictionRun",
+ String.valueOf(getNumTestsPerEvictionRun())));
+ ref.add(new StringRefAddr("minEvictableIdleTimeMillis",
+ String.valueOf(getMinEvictableIdleTimeMillis())));
+ ref.add(new StringRefAddr("testWhileIdle",
+ String.valueOf(getTestWhileIdle())));
+ ref.add(new StringRefAddr("validationQuery", getValidationQuery()));
+
+ return ref;
}
/**
* Converts a object to a byte array for storage/serialization.
- * FIXME! this method should be moved to commons.util.ObjectUtils
*
- * @param hash The Hashtable to convert.
- * @return A byte[] with the converted Hashtable.
- * @exception Exception, a generic exception.
+ * @param obj The Serializable to convert.
+ * @return A byte[] with the converted Serializable.
+ * @exception IOException, if conversion to a byte[] fails.
*/
private static byte[] serialize(Serializable obj)
throws IOException
@@ -1004,5 +1114,197 @@
}
return byteArray;
}
+
+
+ // ----------------------------------------------------------------------
+ // ObjectFactory implementation
+
+ /**
+ * implements ObjectFactory to create an instance of this class
+ */
+ public Object getObjectInstance(Object refObj, Name name,
+ Context context, Hashtable env)
+ throws Exception
+ {
+ // The spec says to return null if we can't create an instance
+ // of the reference
+ Jdbc2PoolDataSource ds = null;
+ if (refObj instanceof Reference)
+ {
+ Reference ref = (Reference)refObj;
+
+ if (ref.getClassName().equals(getClass().getName()))
+ {
+ RefAddr ra = ref.get("isNew");
+ if (ra != null && ra.getContent() != null)
+ {
+ isNew = Boolean.getBoolean(ra.getContent().toString());
+ }
+
+ ra = ref.get("instanceKey");
+ if (ra != null && ra.getContent() != null)
+ {
+ instanceKey = new Integer(ra.getContent().toString());
+ }
+
+ ra = ref.get("dataSourceName");
+ if (ra != null && ra.getContent() != null)
+ {
+ setDataSourceName(ra.getContent().toString());
+ }
+
+ ra = ref.get("defaultAutoCommit");
+ if (ra != null && ra.getContent() != null)
+ {
+ setDefaultAutoCommit
+ (Boolean.getBoolean(ra.getContent().toString()));
+ }
+
+ ra = ref.get("defaultMaxActive");
+ if (ra != null && ra.getContent() != null)
+ {
+ setDefaultMaxActive(
+ Integer.parseInt(ra.getContent().toString()));
+ }
+
+ ra = ref.get("defaultMaxIdle");
+ if (ra != null && ra.getContent() != null)
+ {
+ setDefaultMaxIdle(
+ Integer.parseInt(ra.getContent().toString()));
+ }
+
+ ra = ref.get("defaultMaxWait");
+ if (ra != null && ra.getContent() != null)
+ {
+ setDefaultMaxWait(
+ Integer.parseInt(ra.getContent().toString()));
+ }
+
+ ra = ref.get("defaultReadOnly");
+ if (ra != null && ra.getContent() != null)
+ {
+ setDefaultReadOnly
+ (Boolean.getBoolean(ra.getContent().toString()));
+ }
+
+ ra = ref.get("description");
+ if (ra != null && ra.getContent() != null)
+ {
+ setDescription(ra.getContent().toString());
+ }
+
+ ra = ref.get("jndiEnvironment");
+ if (ra != null && ra.getContent() != null)
+ {
+ byte[] serialized = (byte[])ra.getContent();
+ jndiEnvironment =
+ (Properties)Objects.deserialize(serialized);
+ }
+
+ ra = ref.get("loginTimeout");
+ if (ra != null && ra.getContent() != null)
+ {
+ setLoginTimeout(
+ Integer.parseInt(ra.getContent().toString()));
+ }
+
+ ra = ref.get("perUserDefaultAutoCommit");
+ if (ra != null && ra.getContent() != null)
+ {
+ byte[] serialized = (byte[])ra.getContent();
+ perUserDefaultAutoCommit =
+ (Map)Objects.deserialize(serialized);
+ }
+
+ ra = ref.get("perUserMaxActive");
+ if (ra != null && ra.getContent() != null)
+ {
+ byte[] serialized = (byte[])ra.getContent();
+ perUserMaxActive =
+ (Map)Objects.deserialize(serialized);
+ }
+
+ ra = ref.get("perUserMaxIdle");
+ if (ra != null && ra.getContent() != null)
+ {
+ byte[] serialized = (byte[])ra.getContent();
+ perUserMaxIdle =
+ (Map)Objects.deserialize(serialized);
+ }
+
+ ra = ref.get("perUserMaxWait");
+ if (ra != null && ra.getContent() != null)
+ {
+ byte[] serialized = (byte[])ra.getContent();
+ perUserMaxWait =
+ (Map)Objects.deserialize(serialized);
+ }
+
+ ra = ref.get("perUserDefaultReadOnly");
+ if (ra != null && ra.getContent() != null)
+ {
+ byte[] serialized = (byte[])ra.getContent();
+ perUserDefaultReadOnly =
+ (Map)Objects.deserialize(serialized);
+ }
+
+ ra = ref.get("testOnBorrow");
+ if (ra != null && ra.getContent() != null)
+ {
+ setTestOnBorrow
+ (Boolean.getBoolean(ra.getContent().toString()));
+ }
+
+ ra = ref.get("testOnReturn");
+ if (ra != null && ra.getContent() != null)
+ {
+ setTestOnReturn
+ (Boolean.getBoolean(ra.getContent().toString()));
+ }
+
+ ra = ref.get("timeBetweenEvictionRunsMillis");
+ if (ra != null && ra.getContent() != null)
+ {
+ setTimeBetweenEvictionRunsMillis(
+ Integer.parseInt(ra.getContent().toString()));
+ }
+
+ ra = ref.get("numTestsPerEvictionRun");
+ if (ra != null && ra.getContent() != null)
+ {
+ setNumTestsPerEvictionRun(
+ Integer.parseInt(ra.getContent().toString()));
+ }
+
+ ra = ref.get("minEvictableIdleTimeMillis");
+ if (ra != null && ra.getContent() != null)
+ {
+ setMinEvictableIdleTimeMillis(
+ Integer.parseInt(ra.getContent().toString()));
+ }
+
+ ra = ref.get("testWhileIdle");
+ if (ra != null && ra.getContent() != null)
+ {
+ setTestWhileIdle
+ (Boolean.getBoolean(ra.getContent().toString()));
+ }
+
+ ra = ref.get("validationQuery");
+ if (ra != null && ra.getContent() != null)
+ {
+ setValidationQuery(ra.getContent().toString());
+ }
+
+ ds = this;
+ }
+
+ }
+
+ return ds;
+ }
+
+
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>