You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by jm...@apache.org on 2002/03/04 08:52:38 UTC
cvs commit: jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool CPDSConnectionFactory.java TorqueClassicDataSource.java Jdbc2PoolDataSource.java
jmcnally 02/03/03 23:52:38
Modified: jdbc2pool build.xml default.properties
jdbc2pool/src/java/org/apache/commons/jdbc2pool
Jdbc2PoolDataSource.java
Added: jdbc2pool/src/java/org/apache/commons/jdbc2pool
CPDSConnectionFactory.java
TorqueClassicDataSource.java
Log:
switched Jdbc2PoolDataSource to use a pool from the commons pool package.
Moved the version based on torque's connection pool to a new class.
Revision Changes Path
1.3 +4 -0 jakarta-commons-sandbox/jdbc2pool/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/jdbc2pool/build.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- build.xml 26 Jan 2002 22:24:47 -0000 1.2
+++ build.xml 4 Mar 2002 07:52:37 -0000 1.3
@@ -14,6 +14,8 @@
<pathelement location="${jdbc.jar}"/>
<pathelement location="${log4j.jar}"/>
<pathelement location="${commons-util.jar}"/>
+ <pathelement location="${commons-pool.jar}"/>
+ <pathelement location="${commons-dbcp.jar}"/>
<pathelement location="${junit.jar}"/>
</path>
@@ -29,6 +31,8 @@
<echo message="jdbc.jar = ${jdbc.jar}"/>
<echo message="junit.jar = ${junit.jar}"/>
<echo message="commons-util.jar = ${commons-util.jar}"/>
+ <echo message="commons-pool.jar = ${commons-pool.jar}"/>
+ <echo message="commons-dbcp.jar = ${commons-dbcp.jar}"/>
</target>
<!-- ================================================================== -->
1.3 +2 -0 jakarta-commons-sandbox/jdbc2pool/default.properties
Index: default.properties
===================================================================
RCS file: /home/cvs/jakarta-commons-sandbox/jdbc2pool/default.properties,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- default.properties 26 Jan 2002 22:24:47 -0000 1.2
+++ default.properties 4 Mar 2002 07:52:37 -0000 1.3
@@ -31,6 +31,8 @@
log4j.jar = ${lib.repo}/log4j-1.1.3.jar
commons-util.jar = ${lib.repo}/commons-util-0.1-dev.jar
+commons-pool.jar = ${lib.repo}/commons-pool.jar
+commons-dbcp.jar = ${lib.repo}/commons-dbcp.jar
jdbc.jar = ${lib.repo}/jdbc2_0-stdext.jar
junit.jar = ${lib.repo}/junit-3.7.jar
1.3 +453 -108 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.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Jdbc2PoolDataSource.java 17 Jan 2002 05:44:26 -0000 1.2
+++ Jdbc2PoolDataSource.java 4 Mar 2002 07:52:37 -0000 1.3
@@ -69,6 +69,7 @@
import java.sql.SQLException;
import javax.sql.DataSource;
import javax.sql.ConnectionPoolDataSource;
+import javax.sql.PooledConnection;
import javax.naming.Name;
import javax.naming.Context;
import javax.naming.InitialContext;
@@ -81,16 +82,23 @@
import javax.naming.spi.ObjectFactory;
import org.apache.commons.util.ObjectUtils;
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.impl.GenericObjectPool;
/**
- * Torque's default connection pool DataSource
+ * DataSource that pools PooledConnection's from a
+ * ConnectionPoolDataSource.
*
* @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
- * @version $Id: Jdbc2PoolDataSource.java,v 1.2 2002/01/17 05:44:26 jmcnally Exp $
+ * @version $Id: Jdbc2PoolDataSource.java,v 1.3 2002/03/04 07:52:37 jmcnally Exp $
*/
public class Jdbc2PoolDataSource
implements DataSource, Referenceable, Serializable, ObjectFactory
{
+ private static final String GET_CONNECTION_CALLED =
+ "A Connection was already requested from this source, " +
+ "further initialization is not allowed.";
+
/** Pools keyed by username. */
private static Map pools = new HashMap();
@@ -110,122 +118,162 @@
/** Environment that may be used to set up a jndi initial context. */
private Properties jndiEnvironment;
- private int defaultMaxConnections;
- private Properties perUserMaxConnections;
- private int maxExpiryTime;
- private int connectionWaitTimeout;
+
private int logInterval;
private boolean defaultAutoCommit;
private boolean defaultReadOnly;
+ private boolean getConnectionCalled = false;
+
/**
* Default no-arg constructor for Serialization
*/
public Jdbc2PoolDataSource()
{
- defaultAutoCommit = true;
}
+ /**
+ * Throws an IllegalStateException, if a PooledConnection has already
+ * been requested.
+ */
+ private void assertInitializationAllowed()
+ throws IllegalStateException
+ {
+ if (getConnectionCalled)
+ {
+ throw new IllegalStateException(GET_CONNECTION_CALLED);
+ }
+ }
+
+ // -------------------------------------------------------------------
// Properties
/**
- * Get the number of database connections to cache per user.
+ * 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 1.
- *
- * @return value of maxConnections.
+ * in perUserMaxConnections. The default is 0.
*/
- public int getDefaultMaxConnections()
- {
- return defaultMaxConnections;
+ private int defaultMaxActive = 0;
+
+ public int getDefaultMaxActive() {
+ return (this.defaultMaxActive);
}
-
+
+ public void setDefaultMaxActive(int maxActive) {
+ assertInitializationAllowed();
+ this.defaultMaxActive = maxActive;
+ }
+
/**
- * Set the number of database connections to cache per user.
+ * 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 perUserMaxConnections. The default is 1.
- *
- * @param v Value to assign to maxConnections.
+ * in perUserMaxIdle. The default is 0.
*/
- public void setDefaultMaxConnections(int v)
- {
- this.defaultMaxConnections = v;
+ private int defaultMaxIdle = 0;
+
+ public int getDefaultMaxIdle() {
+ return (this.defaultMaxIdle);
}
-
-
+
+ public void setDefaultMaxIdle(int defaultMaxIdle) {
+ assertInitializationAllowed();
+ this.defaultMaxIdle = defaultMaxIdle;
+ }
+
/**
- * Get the number of database connections to cache per user. The keys
- * are usernames and the value is the maximum connections. Any username
- * specified here will override the value of defaultMaxConnections.
- *
- * @return value of perUserMaxConnections.
+ * 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.
+ */
+ private int defaultMaxWait = -1;
+
+ public int getDefaultMaxWait() {
+ return (this.defaultMaxWait);
+ }
+
+ 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.
*/
- public Properties getPerUserMaxConnections()
+ public Properties getPerUserMaxActive()
{
- return perUserMaxConnections;
+ return perUserMaxActive;
}
/**
- * Set the number of database connections to cache per user. The keys
- * are usernames and the value is the maximum connections. Any username
- * specified here will override the value of defaultMaxConnections.
- *
- * @param v Value to assign to perUserMaxConnections.
+ * 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 setPerUserMaxConnections(Properties v)
+ public void setPerUserMaxActive(Properties v)
{
- this.perUserMaxConnections = v;
+ assertInitializationAllowed();
+ this.perUserMaxActive = v;
}
-
-
+
+ private Properties perUserMaxIdle;
/**
- * Get the amount of time (in seconds) that database connections
- * will be cached. The default is 3600 (1 hour).
- *
- * @return value of expiryTime.
+ * 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 int getMaxExpiryTime()
+ public Properties getPerUserMaxIdle()
{
- return maxExpiryTime;
+ return perUserMaxIdle;
}
/**
- * Set the amount of time (in seconds) that database connections
- * will be cached. The default is 3600 (1 hour).
- *
- * @param v Value to assign to expiryTime.
+ * 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 setMaxExpiryTime(int v)
+ public void setPerUserMaxIdle(Properties v)
{
- this.maxExpiryTime = v;
+ assertInitializationAllowed();
+ this.perUserMaxIdle = v;
}
-
+ private Properties perUserMaxWait;
/**
- * Get the amount of time (in seconds) a connection request will
- * have to wait before a time out occurs and an error is thrown.
- * The default is 10 seconds.
- *
- * @return value of connectionWaitTimeout.
+ * 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 int getConnectionWaitTimeout()
+ public Properties getPerUserMaxWait()
{
- return connectionWaitTimeout;
+ return perUserMaxWait;
}
/**
- * Eet the amount of time (in seconds) a connection request will
- * have to wait before a time out occurs and an error is thrown.
- * The default is 10 seconds.
- *
- * @param v Value to assign to connectionWaitTimeout.
+ * 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 setConnectionWaitTimeout(int v)
+ public void setPerUserMaxWait(Properties v)
{
- this.connectionWaitTimeout = v;
+ assertInitializationAllowed();
+ this.perUserMaxWait = v;
}
-
-
+
/**
* Get the interval (in seconds) between which the ConnectionPool logs
* the status of it's Connections. Default is 0 which indicates no
@@ -273,9 +321,32 @@
*/
public void setDefaultAutoCommit(boolean v)
{
+ assertInitializationAllowed();
this.defaultAutoCommit = 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()
+ {
+ return perUserDefaultAutoCommit;
+ }
+
+ /**
+ * The keys are usernames and the value is the --. Any
+ * username specified here will override the value of defaultAutoCommit.
+ */
+ public void setPerUserDefaultAutoCommit(Properties v)
+ {
+ assertInitializationAllowed();
+ this.perUserDefaultAutoCommit = v;
+ }
+
+ private Properties perUserDefaultReadOnly;
/**
* Get the value of defaultReadOnly, which defines the state of
* connections handed out from this pool. The value can be changed
@@ -299,10 +370,217 @@
*/
public void setDefaultReadOnly(boolean v)
{
+ assertInitializationAllowed();
this.defaultReadOnly = v;
}
/**
+ * The keys are usernames and the value is the --. Any
+ * username specified here will override the value of defaultReadOnly.
+ */
+ public Properties getPerUserDefaultReadOnly()
+ {
+ return perUserDefaultReadOnly;
+ }
+
+ /**
+ * The keys are usernames and the value is the --. Any
+ * username specified here will override the value of defaultReadOnly.
+ */
+ public void setPerUserDefaultReadOnly(Properties v)
+ {
+ assertInitializationAllowed();
+ this.perUserDefaultReadOnly = v;
+ }
+
+ boolean _testOnBorrow;
+ /**
+ * When <tt>true</tt>, objects will be
+ * {*link PoolableObjectFactory#validateObject validated}
+ * before being returned by the {*link #borrowObject}
+ * method. If the object fails to validate,
+ * it will be dropped from the pool, and we will attempt
+ * to borrow another.
+ *
+ * *see #setTestOnBorrow
+ */
+ public boolean getTestOnBorrow() {
+ return _testOnBorrow;
+ }
+
+ /**
+ * When <tt>true</tt>, objects will be
+ * {*link PoolableObjectFactory#validateObject validated}
+ * before being returned by the {*link #borrowObject}
+ * method. If the object fails to validate,
+ * it will be dropped from the pool, and we will attempt
+ * to borrow another.
+ *
+ * *see #getTestOnBorrow
+ */
+ public void setTestOnBorrow(boolean testOnBorrow) {
+ assertInitializationAllowed();
+ _testOnBorrow = testOnBorrow;
+ }
+
+ boolean _testOnReturn;
+ /**
+ * When <tt>true</tt>, objects will be
+ * {*link PoolableObjectFactory#validateObject validated}
+ * before being returned to the pool within the
+ * {*link #returnObject}.
+ *
+ * *see #setTestOnReturn
+ */
+ public boolean getTestOnReturn() {
+ return _testOnReturn;
+ }
+
+ /**
+ * When <tt>true</tt>, objects will be
+ * {*link PoolableObjectFactory#validateObject validated}
+ * before being returned to the pool within the
+ * {*link #returnObject}.
+ *
+ * *see #getTestOnReturn
+ */
+ public void setTestOnReturn(boolean testOnReturn) {
+ assertInitializationAllowed();
+ _testOnReturn = testOnReturn;
+ }
+
+ long _timeBetweenEvictionRunsMillis;
+ /**
+ * Returns 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.
+ *
+ * *see #setTimeBetweenEvictionRunsMillis
+ */
+ public synchronized long getTimeBetweenEvictionRunsMillis() {
+ return _timeBetweenEvictionRunsMillis;
+ }
+
+ /**
+ * Sets 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.
+ *
+ * *see #getTimeBetweenEvictionRunsMillis
+ */
+ public synchronized void
+ setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
+ assertInitializationAllowed();
+ _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ }
+
+ int _numTestsPerEvictionRun;
+ /**
+ * Returns the number of objects to examine during each run of the
+ * idle object evictor thread (if any).
+ *
+ * *see #setNumTestsPerEvictionRun
+ * *see #setTimeBetweenEvictionRunsMillis
+ */
+ public int getNumTestsPerEvictionRun() {
+ return _numTestsPerEvictionRun;
+ }
+
+ /**
+ * Sets the number of objects to examine during each run of the
+ * idle object evictor thread (if any).
+ * <p>
+ * When a negative value is supplied, <tt>ceil({*link #numIdle})/abs({*link #getNumTestsPerEvictionRun})</tt>
+ * tests will be run. I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
+ * idle objects will be tested per run.
+ *
+ * *see #getNumTestsPerEvictionRun
+ * *see #setTimeBetweenEvictionRunsMillis
+ */
+ public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
+ assertInitializationAllowed();
+ _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.
@@ -414,14 +692,15 @@
String password)
throws SQLException
{
+ getConnectionCalled = true;
String key = getKey(username);
- ConnectionPool pool = (ConnectionPool)pools.get(key);
+ ObjectPool pool = (ObjectPool)pools.get(key);
if ( pool == null )
{
try
{
registerPool(username, password);
- pool = (ConnectionPool)pools.get(key);
+ pool = (ObjectPool)pools.get(key);
}
catch (Exception e)
{
@@ -430,7 +709,32 @@
}
Connection con =
- pool.getConnection(username, password).getConnection();
+ ((PooledConnection)pool.borrowObject()).getConnection();
+
+ // FIXME! this could be more efficient
+ boolean defaultAutoCommit = isDefaultAutoCommit();
+ if ( username != null )
+ {
+ String userMax =
+ (String)getPerUserDefaultAutoCommit().get(username);
+ if ( userMax != null )
+ {
+ defaultAutoCommit = Boolean.getBoolean(userMax);
+ }
+ }
+
+ // FIXME! this could be more efficient
+ boolean defaultReadOnly = isDefaultReadOnly();
+ if ( username != null )
+ {
+ String userMax =
+ (String)getPerUserDefaultReadOnly().get(username);
+ if ( userMax != null )
+ {
+ defaultReadOnly = Boolean.getBoolean(userMax);
+ }
+ }
+
con.setAutoCommit(defaultAutoCommit);
con.setReadOnly(defaultReadOnly);
return con;
@@ -452,6 +756,46 @@
String key = getKey(username);
if ( !pools.containsKey(key) )
{
+ int maxActive = getDefaultMaxActive();
+ if ( username != null )
+ {
+ String userMax =
+ (String)getPerUserMaxActive().get(username);
+ if ( userMax != null )
+ {
+ maxActive = Integer.parseInt(userMax);
+ }
+ }
+
+ int maxIdle = getDefaultMaxIdle();
+ if ( username != null )
+ {
+ String userMax =
+ (String)getPerUserMaxIdle().get(username);
+ if ( userMax != null )
+ {
+ maxIdle = Integer.parseInt(userMax);
+ }
+ }
+
+ int maxWait = getDefaultMaxWait();
+ if ( username != null )
+ {
+ String userMax =
+ (String)getPerUserMaxIdle().get(username);
+ if ( userMax != null )
+ {
+ maxWait = Integer.parseInt(userMax);
+ }
+ }
+
+ // Create an object pool to contain our active connections
+ GenericObjectPool pool = new GenericObjectPool(null);
+ pool.setMaxActive(maxActive);
+ pool.setMaxIdle(maxIdle);
+ pool.setMaxWait(maxWait);
+ // FIXME! set the rest of the properties
+
ConnectionPoolDataSource cpds = this.cpds;
if ( cpds == null )
{
@@ -467,21 +811,11 @@
cpds = (ConnectionPoolDataSource)ctx.lookup(dataSourceName);
}
- int maxConnections = getDefaultMaxConnections();
- if ( username != null )
- {
- String userMaxCon =
- (String)getPerUserMaxConnections().get(username);
- if ( userMaxCon != null )
- {
- maxConnections = Integer.parseInt(userMaxCon);
- }
- }
-
- ConnectionPool pool = new ConnectionPool(cpds, username, password,
- maxConnections, maxExpiryTime, connectionWaitTimeout,
- logInterval, logWriter);
-
+ // Set up the factory we will use
+ CPDSConnectionFactory connectionFactory =
+ new CPDSConnectionFactory(cpds, pool, validationQuery,
+ username, password);
+
// avoid ConcurrentModificationException
Map newPools = new HashMap(pools);
newPools.put(key, pool);
@@ -533,25 +867,26 @@
Reference ref = new Reference(getClass().getName(), factory, null);
- ref.add(new StringRefAddr("defaultMaxConnections",
- String.valueOf(getDefaultMaxConnections())));
- ref.add(new StringRefAddr("maxExpiryTime",
- String.valueOf(getMaxExpiryTime())));
- ref.add(new StringRefAddr("connectionWaitTimeout",
- String.valueOf(getConnectionWaitTimeout())));
+ 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("description", getDescription()));
- byte[] serJndiEnv = null;
+ byte[] ser = null;
// BinaryRefAddr does not allow null byte[].
if ( getJndiEnvironment() != null )
{
try
{
- serJndiEnv = serialize(getJndiEnvironment());
- ref.add(new BinaryRefAddr("jndiEnvironment", serJndiEnv));
+ ser = serialize(getJndiEnvironment());
+ ref.add(new BinaryRefAddr("jndiEnvironment", ser));
}
catch (IOException ioe)
{
@@ -560,14 +895,13 @@
}
}
- byte[] serPUMC = null;
// BinaryRefAddr does not allow null byte[].
- if ( getPerUserMaxConnections() != null )
+ if ( getPerUserMaxActive() != null )
{
try
{
- serPUMC = serialize(getPerUserMaxConnections());
- ref.add(new BinaryRefAddr("perUserMaxConnections", serPUMC));
+ ser = serialize(getPerUserMaxActive());
+ ref.add(new BinaryRefAddr("perUserMaxActive", ser));
}
catch (IOException ioe)
{
@@ -575,6 +909,21 @@
"serializing the perUserMaxConnections properties.");
}
}
+
+ // BinaryRefAddr does not allow null byte[].
+ if ( getPerUserMaxActive() != null )
+ {
+ try
+ {
+ ser = serialize(getPerUserMaxActive());
+ ref.add(new BinaryRefAddr("perUserMaxActive", ser));
+ }
+ catch (IOException ioe)
+ {
+ throw new NamingException("An IOException prevented " +
+ "serializing the perUserMaxActive properties.");
+ }
+ }
return ref;
}
@@ -591,12 +940,8 @@
if (ref.getClassName().equals(getClass().getName()))
{
- setDefaultMaxConnections(Integer.parseInt(
- (String)ref.get("defaultMaxConnections").getContent()));
- setMaxExpiryTime(Integer.parseInt(
- (String)ref.get("maxExpiryTime").getContent()));
- setConnectionWaitTimeout(Integer.parseInt(
- (String)ref.get("connectionWaitTimeout").getContent()));
+ setDefaultMaxActive(Integer.parseInt(
+ (String)ref.get("defaultMaxActive").getContent()));
setLogInterval(Integer.parseInt(
(String)ref.get("logInterval").getContent()));
setDataSourceName((String)ref.get("dataSourceName").getContent());
@@ -610,11 +955,11 @@
(Properties)ObjectUtils.deserialize(serialized) );
}
- refAddr = ref.get("perUserMaxConnections");
+ refAddr = ref.get("perUserMaxActive");
if ( refAddr != null )
{
byte[] serialized = (byte[])refAddr.getContent();
- setPerUserMaxConnections(
+ setPerUserMaxActive(
(Properties)ObjectUtils.deserialize(serialized) );
}
1.1 jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/CPDSConnectionFactory.java
Index: CPDSConnectionFactory.java
===================================================================
/*
* $Header: /home/cvs/jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/CPDSConnectionFactory.java,v 1.1 2002/03/04 07:52:37 jmcnally Exp $
* $Revision: 1.1 $
* $Date: 2002/03/04 07:52:37 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.commons.jdbc2pool;
import java.util.Map;
import java.util.HashMap;
import java.sql.*;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import javax.sql.ConnectionEvent;
import javax.sql.ConnectionEventListener;
import org.apache.commons.pool.*;
import org.apache.commons.dbcp.*;
/**
* A {*link PoolableObjectFactory} that creates
* {*link PoolableConnection}s.
*
* @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
* @version $Id: CPDSConnectionFactory.java,v 1.1 2002/03/04 07:52:37 jmcnally Exp $
*/
public class CPDSConnectionFactory
implements PoolableObjectFactory, ConnectionEventListener {
/**
* Create a new <tt>PoolableConnectionFactory</tt>.
* @param connFactory the {*link ConnectionFactory} from which to obtain base {*link Connection}s
* @param pool the {*link ObjectPool} in which to pool those {*link Connection}s
* @param stmtPoolFactory the {*link KeyedObjectPoolFactory} to use to create {*link KeyedObjectPool}s for pooling {*link PreparedStatement}s, or <tt>null</tt> to disable {*link PreparedStatement} pooling
* @param validationQuery a query to use to {*link #validateObject validate} {*link Connection}s. Should return at least one row. May be <tt>null</tt>
* @param defaultReadOnly the default "read only" setting for borrowed {*link Connection}s
* @param defaultAutoCommit the default "auto commit" setting for returned {*link Connection}s
*/
public CPDSConnectionFactory(ConnectionPoolDataSource cpds,
ObjectPool pool,
String validationQuery,
String username,
String password) {
_cpds = cpds;
_pool = pool;
_pool.setFactory(this);
_validationQuery = validationQuery;
_username = username;
_password = password;
}
/**
* Sets the {*link ConnectionFactory} from which to obtain base {*link Connection}s.
* @param connFactory the {*link ConnectionFactory} from which to obtain base {*link Connection}s
*/
synchronized public void setCPDS(ConnectionPoolDataSource cpds) {
_cpds = cpds;
}
/**
* Sets the query I use to {*link #validateObject validate} {*link Connection}s.
* Should return at least one row.
* May be <tt>null</tt>
* @param validationQuery a query to use to {*link #validateObject validate} {*link Connection}s.
*/
synchronized public void setValidationQuery(String validationQuery) {
_validationQuery = validationQuery;
}
/**
* Sets the {*link ObjectPool} in which to pool {*link Connection}s.
* @param pool the {*link ObjectPool} in which to pool those {*link Connection}s
*/
synchronized public void setPool(ObjectPool pool) {
if(null != _pool && pool != _pool) {
_pool.close();
}
_pool = pool;
}
public ObjectPool getPool() {
return _pool;
}
synchronized public Object makeObject() {
PooledConnection pc = null;
try
{
if ( _username == null )
{
pc = _cpds.getPooledConnection();
}
else
{
pc = _cpds.getPooledConnection(_username, _password);
}
// should we add this object as a listener or the pool.
// consider the validateObject method in decision
pc.addConnectionEventListener(this);
}
catch (SQLException e)
{
throw new RuntimeException(e.getMessage());
}
return pc;
}
public void destroyObject(Object obj) {
if(obj instanceof PooledConnection) {
try {
((PooledConnection)obj).close();
} catch(RuntimeException e) {
throw e;
} catch(SQLException e) {
; // ignored
}
}
}
// FIXME! Connection from the PooledConnection must be closed before
// another one can be requested and closing it will send an event
// to the pool
synchronized public boolean validateObject(Object obj) {
boolean valid = false;
if(obj instanceof PooledConnection) {
PooledConnection pconn = (PooledConnection)obj;
String query = _validationQuery;
if(null != query) {
Connection conn = null;
Statement stmt = null;
ResultSet rset = null;
validatingMap.put(pconn, null);
try {
conn = pconn.getConnection();
stmt = conn.createStatement();
rset = stmt.executeQuery(query);
if(rset.next()) {
valid = true;
} else {
valid = false;
}
} catch(Exception e) {
valid = false;
}
finally
{
try {
rset.close();
} catch(Throwable t) {
// ignore
}
try {
stmt.close();
} catch(Throwable t) {
// ignore
}
try {
conn.close();
} catch(Throwable t) {
// ignore
}
validatingMap.remove(pconn);
}
} else {
valid = true;
}
} else {
valid = false;
}
return valid;
}
public void passivateObject(Object obj) {
}
public void activateObject(Object obj) {
}
// ***********************************************************************
// java.sql.ConnectionEventListener implementation
// ***********************************************************************
/**
* This will be called if the Connection returned by the getConnection
* method came from a PooledConnection, and the user calls the close()
* method of this connection object. What we need to do here is to
* release this PooledConnection from our pool...
*/
public void connectionClosed(ConnectionEvent event)
{
PooledConnection pc = (PooledConnection)event.getSource();
// if this event occured becase we were validating, ignore it
// otherwise return the connection to the pool.
if (!validatingMap.containsKey(pc))
{
_pool.returnObject(pc);
}
}
/**
* If a fatal error occurs, close the underlying physical connection so as
* not to be returned in the future
*/
public void connectionErrorOccurred(ConnectionEvent event)
{
PooledConnection pc = (PooledConnection)event.getSource();
try
{
System.err
.println("CLOSING DOWN CONNECTION DUE TO INTERNAL ERROR");
//remove this from the listener list because we are no more
//interested in errors since we are about to close this connection
pc.removeConnectionEventListener(this);
}
catch (Exception ignore)
{
// ignore
}
destroyObject(pc);
}
protected ConnectionPoolDataSource _cpds = null;
protected String _validationQuery = null;
protected ObjectPool _pool = null;
protected String _username = null;
protected String _password = null;
private Map validatingMap = new HashMap();
}
1.1 jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/TorqueClassicDataSource.java
Index: TorqueClassicDataSource.java
===================================================================
package org.apache.commons.jdbc2pool;
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Turbine" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Turbine", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Hashtable;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import javax.sql.ConnectionPoolDataSource;
import javax.naming.Name;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Referenceable;
import javax.naming.Reference;
import javax.naming.RefAddr;
import javax.naming.BinaryRefAddr;
import javax.naming.StringRefAddr;
import javax.naming.NamingException;
import javax.naming.spi.ObjectFactory;
import org.apache.commons.util.ObjectUtils;
/**
* Torque's default connection pool DataSource
*
* @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
* @version $Id: TorqueClassicDataSource.java,v 1.1 2002/03/04 07:52:37 jmcnally Exp $
*/
public class TorqueClassicDataSource
implements DataSource, Referenceable, Serializable, ObjectFactory
{
/** Pools keyed by username. */
private static Map pools = new HashMap();
/** DataSource Name used to find the ConnectionPoolDataSource */
private String dataSourceName;
/** Description */
private String description;
/** Login TimeOut in seconds */
private int loginTimeout;
private ConnectionPoolDataSource cpds;
/** Log stream */
private PrintWriter logWriter;
/** Environment that may be used to set up a jndi initial context. */
private Properties jndiEnvironment;
private int defaultMaxConnections;
private Properties perUserMaxConnections;
private int maxExpiryTime;
private int connectionWaitTimeout;
private int logInterval;
private boolean defaultAutoCommit;
private boolean defaultReadOnly;
/**
* Default no-arg constructor for Serialization
*/
public TorqueClassicDataSource()
{
defaultAutoCommit = true;
}
// Properties
/**
* Get the number of database connections to cache per user.
* This value is used for any username which is not specified
* in perUserMaxConnections. The default is 1.
*
* @return value of maxConnections.
*/
public int getDefaultMaxConnections()
{
return defaultMaxConnections;
}
/**
* Set the number of database connections to cache per user.
* This value is used for any username which is not specified
* in perUserMaxConnections. The default is 1.
*
* @param v Value to assign to maxConnections.
*/
public void setDefaultMaxConnections(int v)
{
this.defaultMaxConnections = v;
}
/**
* Get the number of database connections to cache per user. The keys
* are usernames and the value is the maximum connections. Any username
* specified here will override the value of defaultMaxConnections.
*
* @return value of perUserMaxConnections.
*/
public Properties getPerUserMaxConnections()
{
return perUserMaxConnections;
}
/**
* Set the number of database connections to cache per user. The keys
* are usernames and the value is the maximum connections. Any username
* specified here will override the value of defaultMaxConnections.
*
* @param v Value to assign to perUserMaxConnections.
*/
public void setPerUserMaxConnections(Properties v)
{
this.perUserMaxConnections = v;
}
/**
* Get the amount of time (in seconds) that database connections
* will be cached. The default is 3600 (1 hour).
*
* @return value of expiryTime.
*/
public int getMaxExpiryTime()
{
return maxExpiryTime;
}
/**
* Set the amount of time (in seconds) that database connections
* will be cached. The default is 3600 (1 hour).
*
* @param v Value to assign to expiryTime.
*/
public void setMaxExpiryTime(int v)
{
this.maxExpiryTime = v;
}
/**
* Get the amount of time (in seconds) a connection request will
* have to wait before a time out occurs and an error is thrown.
* The default is 10 seconds.
*
* @return value of connectionWaitTimeout.
*/
public int getConnectionWaitTimeout()
{
return connectionWaitTimeout;
}
/**
* Eet the amount of time (in seconds) a connection request will
* have to wait before a time out occurs and an error is thrown.
* The default is 10 seconds.
*
* @param v Value to assign to connectionWaitTimeout.
*/
public void setConnectionWaitTimeout(int v)
{
this.connectionWaitTimeout = v;
}
/**
* 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.
*/
public int getLogInterval()
{
return logInterval;
}
/**
* 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.
*/
public void setLogInterval(int v)
{
this.logInterval = 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)
{
this.defaultAutoCommit = v;
}
/**
* 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 boolean isDefaultReadOnly()
{
return defaultReadOnly;
}
/**
* 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 setDefaultReadOnly(boolean v)
{
this.defaultReadOnly = 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 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 String getDescription()
{
return description;
}
/**
* 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 setDescription(String v)
{
this.description = v;
}
/**
* 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 getJndiEnvironment()
{
return jndiEnvironment;
}
/**
* 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 setJndiEnvironment(Properties v)
{
this.jndiEnvironment = v;
}
/**
* 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;
}
/**
* Attempt to establish a database connection.
*/
public Connection getConnection()
throws SQLException
{
return getConnection(null, null);
}
/**
* Attempt to establish a database connection.
*/
synchronized public Connection getConnection(String username,
String password)
throws SQLException
{
String key = getKey(username);
ConnectionPool pool = (ConnectionPool)pools.get(key);
if ( pool == null )
{
try
{
registerPool(username, password);
pool = (ConnectionPool)pools.get(key);
}
catch (Exception e)
{
throw new SQLException(e.getMessage());
}
}
Connection con =
pool.getConnection(username, password).getConnection();
con.setAutoCommit(defaultAutoCommit);
con.setReadOnly(defaultReadOnly);
return con;
}
private String getKey(String suffix)
{
String key = getDataSourceName();
if ( suffix != null )
{
key += suffix;
}
return key;
}
synchronized private void registerPool(String username, String password)
throws javax.naming.NamingException
{
String key = getKey(username);
if ( !pools.containsKey(key) )
{
ConnectionPoolDataSource cpds = this.cpds;
if ( cpds == null )
{
Context ctx = null;
if ( jndiEnvironment == null )
{
ctx = new InitialContext();
}
else
{
ctx = new InitialContext(jndiEnvironment);
}
cpds = (ConnectionPoolDataSource)ctx.lookup(dataSourceName);
}
int maxConnections = getDefaultMaxConnections();
if ( username != null )
{
String userMaxCon =
(String)getPerUserMaxConnections().get(username);
if ( userMaxCon != null )
{
maxConnections = Integer.parseInt(userMaxCon);
}
}
ConnectionPool pool = new ConnectionPool(cpds, username, password,
maxConnections, maxExpiryTime, connectionWaitTimeout,
logInterval, logWriter);
// avoid ConcurrentModificationException
Map newPools = new HashMap(pools);
newPools.put(key, pool);
pools = newPools;
}
}
/**
* 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;
}
/**
* <CODE>Referenceable</CODE> implementation.
*/
public Reference getReference()
throws NamingException
{
String factory = getClass().getName();
Reference ref = new Reference(getClass().getName(), factory, null);
ref.add(new StringRefAddr("defaultMaxConnections",
String.valueOf(getDefaultMaxConnections())));
ref.add(new StringRefAddr("maxExpiryTime",
String.valueOf(getMaxExpiryTime())));
ref.add(new StringRefAddr("connectionWaitTimeout",
String.valueOf(getConnectionWaitTimeout())));
ref.add(new StringRefAddr("logInterval",
String.valueOf(getLogInterval())));
ref.add(new StringRefAddr("dataSourceName", getDataSourceName()));
ref.add(new StringRefAddr("description", getDescription()));
byte[] serJndiEnv = null;
// BinaryRefAddr does not allow null byte[].
if ( getJndiEnvironment() != null )
{
try
{
serJndiEnv = serialize(getJndiEnvironment());
ref.add(new BinaryRefAddr("jndiEnvironment", serJndiEnv));
}
catch (IOException ioe)
{
throw new NamingException("An IOException prevented " +
"serializing the jndiEnvironment properties.");
}
}
byte[] serPUMC = null;
// BinaryRefAddr does not allow null byte[].
if ( getPerUserMaxConnections() != null )
{
try
{
serPUMC = serialize(getPerUserMaxConnections());
ref.add(new BinaryRefAddr("perUserMaxConnections", serPUMC));
}
catch (IOException ioe)
{
throw new NamingException("An IOException prevented " +
"serializing the perUserMaxConnections properties.");
}
}
return ref;
}
/**
* 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()))
{
setDefaultMaxConnections(Integer.parseInt(
(String)ref.get("defaultMaxConnections").getContent()));
setMaxExpiryTime(Integer.parseInt(
(String)ref.get("maxExpiryTime").getContent()));
setConnectionWaitTimeout(Integer.parseInt(
(String)ref.get("connectionWaitTimeout").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("perUserMaxConnections");
if ( refAddr != null )
{
byte[] serialized = (byte[])refAddr.getContent();
setPerUserMaxConnections(
(Properties)ObjectUtils.deserialize(serialized) );
}
return this;
}
else
{
// We can't create an instance of the reference
return null;
}
}
/**
* 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.
*/
private static byte[] serialize(Serializable obj)
throws IOException
{
byte[] byteArray = null;
ByteArrayOutputStream baos = null;
ObjectOutputStream out = null;
try
{
// These objects are closed in the finally.
baos = new ByteArrayOutputStream();
out = new ObjectOutputStream(baos);
out.writeObject(obj);
byteArray = baos.toByteArray();
}
finally
{
if (out != null)
{
out.close();
}
}
return byteArray;
}
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>