Initial revision
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/pool/trunk@139576 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..3995981
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,2 @@
+build
+build.properties
\ No newline at end of file
diff --git a/PROPOSAL.html b/PROPOSAL.html
new file mode 100644
index 0000000..0c98c03
--- /dev/null
+++ b/PROPOSAL.html
@@ -0,0 +1,85 @@
+<html>
+<head>
+<title>Proposal for Pool Package</title>
+</head>
+<body bgcolor="white">
+
+<div align="center">
+<h1>Proposal for <em>Pool</em> Package</h1>
+</div>
+
+<h3>(0) Rationale</h3>
+<p>
+ Often a Java application makes use of instances or resources that
+ are expensive to create or that need to be limited due to
+ external constraints. Database and other network connections are
+ leading, although certainly not the only examples of this
+ situation. A pool of instances can be helpful in these circumstances.
+</p>
+<p>
+ A Commons package for object pooling would give committers an
+ opportunity to coordinate their efforts and create and maintain an
+ efficient, feature-rich package under the ASF licence.
+</p>
+
+<h3>(1) Scope of the Package</h3>
+<p>
+ The package will create and maintain an object (instance) pooling
+ package to be distributed under the ASF license.
+</p>
+<p>
+ The package should support a variety of pool implementations, but
+ encourage support of an interface that makes these implementations
+ interchangeable.
+</p>
+
+<h3>(1.5) Interaction With Other Packages</h3>
+
+<p><em>Pool</em> relies upon on standard JDK 1.2 (or later) and
+the Commons-Collections APIs for production deployment. It utilizes the
+JUnit unit testing framework for developing and executing unit tests, but
+this is of interest only to developers of the component. Pool
+will also be a dependency for several future proposed components
+for the Jakarta Commons subproject.
+
+<p>No external configuration files are utilized.</p>
+
+<h3>(2) Initial Source of the Package</h3>
+
+<p>
+ The initial codebase was contributed by Rodney Waldhoff from
+ a working project and can be distributed under the Apache license.
+</p>
+
+<p>The proposed package name for the new component is
+<code>org.apache.commons.pool</code>.</p>
+
+
+<h3>(3) Required Jakarta-Commons Resources</h3>
+
+<ul>
+<li>CVS Repository - New directory <code>pool</code> in the
+ <code>jakarta-commons</code> CVS repository. All initial committers
+ are already committers on <code>jakarta-commons</code>, so no
+ additional user setups are required.</li>
+<li>Mailing List - Discussions will take place on the general
+ <em>jakarta-commons@jakarta.apache.org</em> mailing list. To help
+ list subscribers identify messages of interest, it is suggested that
+ the message subject of messages about this component be prefixed with
+ [Pool].</li>
+<li>Bugzilla - New component "Pool" under the "Commons" product
+ category, with appropriate version identifiers as needed.</li>
+<li>Jyve FAQ - New category "commons-pool" (when available).
+</ul>
+
+
+<h3>(4) Initial Committers</h3>
+<ul>
+ <li>Morgan Delagrange</li>
+ <li>Geir Magnusson Jr.</li>
+ <li>Craig R. McClanahan</li>
+ <li>Rodney Waldhoff</li>
+ <li>David Weinrich</li>
+</ul>
+</body>
+</html>
diff --git a/STATUS.html b/STATUS.html
new file mode 100644
index 0000000..8c3a881
--- /dev/null
+++ b/STATUS.html
@@ -0,0 +1,110 @@
+<html>
+<head>
+<title>Status File for Jakarta Commons "Pool" Package</title>
+<head>
+<body bgcolor="white">
+
+
+<div align="center">
+<h1>The Jakarta Commons <em>Pool</em> Package</h1>
+$Id: STATUS.html,v 1.1 2001/04/14 16:40:32 rwaldhoff Exp $<br>
+<a href="#Introduction">[Introduction]</a>
+<a href="#Dependencies">[Dependencies]</a>
+<a href="#Release Info">[Release Info]</a>
+<a href="#Committers">[Committers]</a>
+<a href="#Action Items">[Action Items]</a>
+<br><br>
+</div>
+
+
+<a name="Introduction"></a>
+<h3>1. INTRODUCTION</h3>
+
+<p>The <em>Pool</em> package defines a generalized object pooling interfaces,
+and provides several general-purpose implementations.
+The following major classes are provided:
+
+<ul>
+<li><strong>ObjectPool</strong> - the basic pooling interface, defining
+ borrowObject, returnObject and several optional methods.</li>
+<li><strong>KeyedObjectPool</strong> - a pooling interface that supports pooling
+ multiple <em>typed</em> objects.</li>
+<li><strong>PoolableObjectFactory</strong> - interface defining
+ lifecycle methods for object instances used within an ObjectPool.
+<li><strong>KeyedPoolableObjectFactory</strong> - interface defining
+ lifecycle methods for object instances used within a KeyedObjectPool.
+<li><strong>StackObjectPool/StackKeyedObjectPool</strong> - implementations
+ of ObjectPool and KeyedObjectPool backed by a simple Stack of
+ pooled instances</li>
+<li><strong>GenericObjectPool/GenericKeyedObjectPool</strong> - more
+ complex implementations of ObjectPool and KeyedObjectPool, supporting
+ asynchronous eviction of pooled instances, etc.</li>
+</ul>
+
+<a name="Dependencies"></a>
+<h3>2. DEPENDENCIES</h3>
+
+<p>The <em>Pool</em> package is dependent upon the following external
+components for development and use:</p>
+<ul>
+<li><a href="http://java.sun.com/j2se">Java Development Kit</a>
+ (Version 1.2 or later)</li>
+<li>Jakarta-Commons Collections package (Version 1.0 or later)</li>
+<li><a href="http://www.junit.org">JUnit Testing Framework</a>
+ (Version 3.2 or later) - for unit tests only, not required
+ for deployment</li>
+</ul>
+
+
+<a name="Release Info"></a>
+<h3>3. RELEASE INFO</h3>
+
+<p>Current Release: <strong>Unreleased, CVS Repository Only</strong></p>
+
+<p>Planned Next Release: TBD</p>
+
+<a name="Committers"></a>
+<h3>4. COMMITTERS</h3>
+
+<p>The following individuals are the primary developers and maintainers of this
+component. Developers who plan to use the <em>Pool</em> package in their own
+projects are encouraged to collaborate on the future development of this
+component to ensure that it continues to meet a variety of needs.</p>
+
+<ul>
+ <li><a href="mailto:morgand@apache.org">Morgan Delagrange</a></li>
+ <li><a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a></li>
+ <li><a href="mailto:craigmcc@apache.org">Craig McClanahan</a></li>
+ <li><a href="mailto:rwaldhoff@apache.org">Rodney Waldhoff</a></li>
+ <li><a href="mailto:dweinr1@apache.org">David Weinrich</a></li>
+</ul>
+
+<a name="Action Items"></a>
+<h3>5. ACTION ITEMS</h3>
+
+<p>The following action items need to be completed prior to a Version 1.0
+release of this component:</p>
+
+<table border="1">
+ <tr>
+ <th width="80%">Action Item</th>
+ <th width="20%">Volunteer</th>
+ </tr>
+
+ <tr>
+ <td><strong>Weak-Reference Based Pools</strong> - pool implementations
+ that keep weak references to the pooled instances, evicting objects
+ when the VM needs memory</td>
+ <td align="center"> </td>
+ </tr>
+
+ <tr>
+ <td><strong>Install / Use Documentation</strong>. Expanded examples and
+ installation documentation. </td>
+ <td align="center"> </td>
+ </tr>
+
+</table>
+
+</body>
+</html>
diff --git a/build.properties.sample b/build.properties.sample
new file mode 100644
index 0000000..581170e
--- /dev/null
+++ b/build.properties.sample
@@ -0,0 +1,4 @@
+# commons-collections.jar - Commons-Collections Classpath
+commons-collections.jar=${basedir}/../collections/build/commons-collections.jar
+# junit.jar - JUnit 3.2+ Classpath
+junit.jar=/java/junit/junit.jar
\ No newline at end of file
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..99beb0c
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,225 @@
+<!-- $Id: build.xml,v 1.1 2001/04/14 16:40:37 rwaldhoff Exp $ -->
+<project name="commons-pool" default="test" basedir=".">
+
+ <!-- patternset describing files to be copied from the doc directory -->
+ <patternset id="patternset-doc"/>
+
+ <!-- patternset describing test classes -->
+ <patternset id="patternset-test-classes">
+ <include name="**/Test*.class"/>
+ </patternset>
+
+ <!-- patternset describing non test classes -->
+ <patternset id="patternset-non-test-classes">
+ <include name="**/*.class"/>
+ <exclude name="**/Test*.class"/>
+ </patternset>
+
+ <!-- patternset describing non test source files (*.java, *html, etc.) -->
+ <patternset id="patternset-javadocable-sources">
+ <include name="**/*"/>
+ <exclude name="**/Test*.java"/>
+ </patternset>
+
+ <!-- ######################################################### -->
+
+ <target name="init">
+ <tstamp/>
+
+ <!-- read properties from the ${user.home}/propfile, if any -->
+ <property name="user-propfile" value="${user.home}/build.properties"/>
+ <property file="${user-propfile}"/>
+ <property name="user-classpath" value=""/>
+ <!-- read properties from the build.properties, if any -->
+ <property file="${basedir}/build.properties"/>
+
+ <!-- command line classpath, if any -->
+ <property name="cp" value=""/>
+
+ <!-- now combine the classpaths -->
+ <property name="classpath" value="${cp}:${user-classpath}:${commons-collections.jar}:${junit.jar}"/>
+
+ <property name="name" value="commons-pool"/>
+ <property name="Name" value="Commons-Pool"/>
+ <property name="Name-Long" value="Jakarta Commons Object Pooling Package"/>
+
+ <property name="test.entry" value="org.apache.commons.pool.TestAll"/>
+ <property name="test.failonerror" value="true" />
+ <property name="test.runner" value="junit.textui.TestRunner" />
+
+ <property name="workdir" value="${java.io.tmpdir}/buildtemp_${DSTAMP}${TSTAMP}"/>
+ <property name="source" value="${basedir}"/>
+ <property name="source.src" value="${basedir}/src"/>
+ <property name="source.src.java" value="${source.src}/java"/>
+ <property name="source.src.test" value="${source.src}/test"/>
+ <property name="source.doc" value="${basedir}/doc"/>
+ <property name="dest" value="${basedir}/build"/>
+ <property name="dest.classes" value="${dest}/classes"/>
+ <property name="dest.doc" value="${dest}/doc"/>
+ <property name="dest.doc.api" value="${dest.doc}/api"/>
+ <property name="dest.jardir" value="${dest}"/>
+ <property name="dest.jardir.jar" value="${dest.jardir}/${name}.jar"/>
+
+ <available property="available-doc" file="${source.doc}"/> <!-- does this module have docs? -->
+ <available property="available-src-java" file="${source.src.java}"/> <!-- does this module have java src? -->
+ <available property="available-src-test" file="${source.src.test}"/> <!-- does this module have test src? -->
+
+ </target>
+
+ <!-- ######################################################### -->
+
+ <target name="copy-javadoc-source" depends="init" if="available-src-java">
+ <mkdir dir="${javadoc-source-dir}"/>
+ <copy todir="${javadoc-source-dir}" filtering="no">
+ <fileset dir="${source.src.java}">
+ <patternset refid="patternset-javadocable-sources"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="copy-doc" depends="init" if="available-doc">
+ <mkdir dir="${doc-source-dir}/${name}"/>
+ <copy todir="${doc-source-dir}/${name}" filtering="no">
+ <fileset dir="${source.doc}">
+ <patternset refid="patternset-doc"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <!-- ######################################################### -->
+
+ <target name="clean" depends="init,clean-doc,clean-build,clean-dist" description="removes generated files">
+ <delete dir="${dest}"/>
+ </target>
+
+ <target name="clean-doc" depends="init,clean-javadoc">
+ <delete dir="${dest.doc}"/>
+ </target>
+
+ <target name="clean-javadoc" depends="init">
+ <delete dir="${dest.doc.api}"/>
+ </target>
+
+ <target name="clean-build" depends="init">
+ <delete dir="${dest.classes}"/>
+ </target>
+
+ <target name="clean-dist" depends="init">
+ <delete file="${dest.jardir.jar}"/>
+ </target>
+
+ <!-- ######################################################### -->
+
+ <target name="doc" depends="init,doc-copy,doc-javadoc" description="generates javadocs and other documentation">
+ </target>
+
+ <target name="doc-copy" depends="init" if="available-doc">
+ <mkdir dir="${dest.doc}"/>
+ <copy todir="${dest.doc}">
+ <fileset dir="${source.doc}">
+ <patternset refid="patternset-doc"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="doc-javadoc" depends="init" if="available-src-java">
+ <!-- copy all the non-test sources out to the work directory and javadoc that -->
+ <mkdir dir="${workdir}"/>
+ <copy todir="${workdir}">
+ <fileset dir="${source.src.java}">
+ <patternset refid="patternset-javadocable-sources"/>
+ </fileset>
+ </copy>
+ <mkdir dir="${dest.doc.api}"/>
+ <javadoc packagenames="org.*"
+ sourcepath="${workdir}"
+ classpath="${classpath}"
+ destdir="${dest.doc.api}"
+ windowtitle="${Name-Long}"
+ doctitle="${Name-Long}"
+ bottom="<small>Copyright &copy; 2001 Apache Software Foundation. Documenation generated ${TODAY}</small>."
+ public="true"
+ version="true"
+ author="false"
+ splitindex="false"
+ nodeprecated="true"
+ nodeprecatedlist="true"
+ notree="true"
+ noindex="false"
+ nohelp="true"
+ nonavbar="false"
+ serialwarn="false">
+ </javadoc>
+ <delete dir="${workdir}"/>
+ </target>
+
+ <!-- ######################################################### -->
+
+ <target name="build" depends="init,build-java" description="compiles source files"/>
+
+ <target name="build-java" depends="init" if="available-src-java">
+ <mkdir dir="${dest.classes}"/>
+ <javac destdir="${dest.classes}"
+ srcdir="${source.src.java}"
+ classpath="${classpath}"
+ debug="false"
+ deprecation="true"
+ optimize="true"/>
+ </target>
+
+ <target name="build-test" depends="init,build-java" if="available-src-test">
+ <mkdir dir="${dest.classes}"/>
+ <javac destdir="${dest.classes}"
+ srcdir="${source.src.test}"
+ classpath="${classpath}"
+ debug="false"
+ deprecation="true"
+ optimize="true"/>
+ </target>
+
+ <!-- ######################################################### -->
+
+ <target name="test" depends="build-test" if="test.entry" description="runs (junit) unit tests">
+ <!--
+ <junit printsummary="yes" fork="on" haltonfailure="yes">
+ <formatter type="plain" usefile="false"/>
+ <test name="${test.entry}"/>
+ <classpath>
+ <pathelement location="${dest.classes}" />
+ <pathelement path="${classpath}" />
+ <pathelement path="${java.class.path}" />
+ </classpath>
+ </junit>
+ -->
+
+ <java classname="${test.runner}" fork="yes" failonerror="${test.failonerror}">
+ <arg value="${test.entry}"/>
+ <classpath>
+ <pathelement location="${dest.classes}" />
+ <pathelement path="${classpath}" />
+ <pathelement path="${java.class.path}" />
+ </classpath>
+ </java>
+ </target>
+
+ <!-- ######################################################### -->
+
+ <target name="dist" depends="dist-jar" description="builds production jar"/>
+
+ <target name="dist-jar" depends="build">
+ <mkdir dir="${dest.jardir}"/>
+ <mkdir dir="${workdir}"/>
+ <copy todir="${workdir}">
+ <fileset dir="${dest.classes}">
+ <patternset refid="patternset-non-test-classes"/>
+ </fileset>
+ </copy>
+ <jar jarfile="${dest.jardir.jar}">
+ <fileset dir="${workdir}"/>
+ </jar>
+ <delete dir="${workdir}"/>
+ </target>
+
+ <!-- ######################################################### -->
+
+</project>
\ No newline at end of file
diff --git a/src/java/org/apache/commons/pool/BaseKeyedPoolableObjectFactory.java b/src/java/org/apache/commons/pool/BaseKeyedPoolableObjectFactory.java
new file mode 100644
index 0000000..04e1948
--- /dev/null
+++ b/src/java/org/apache/commons/pool/BaseKeyedPoolableObjectFactory.java
@@ -0,0 +1,97 @@
+/*
+ * 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 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", "Tomcat", 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.pool;
+
+/**
+ * A base implemenation of {@link KeyedPoolableObjectFactory <tt>KeyedPoolableObjectFactory</tt>}.
+ * <p>
+ * All operations defined here are essentially no-op's.
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: BaseKeyedPoolableObjectFactory.java,v 1.1 2001/04/14 16:40:38 rwaldhoff Exp $
+ *
+ * @see KeyedPoolableObjectFactory
+ * @see BasePoolableObjectFactory
+ */
+public abstract class BaseKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory {
+ public abstract Object makeObject(Object key);
+
+ /**
+ * No-op.
+ */
+ public void destroyObject(Object key, Object obj) {
+ }
+
+ /**
+ * This implementation always returns <tt>true</tt>.
+ * @return <tt>true</tt>
+ */
+ public boolean validateObject(Object key, Object obj) {
+ return true;
+ }
+
+ /**
+ * No-op.
+ */
+ public void activateObject(Object key, Object obj) {
+ }
+
+ /**
+ * No-op.
+ */
+ public void passivateObject(Object key, Object obj) {
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/apache/commons/pool/BasePoolableObjectFactory.java b/src/java/org/apache/commons/pool/BasePoolableObjectFactory.java
new file mode 100644
index 0000000..76e4cd4
--- /dev/null
+++ b/src/java/org/apache/commons/pool/BasePoolableObjectFactory.java
@@ -0,0 +1,103 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/BasePoolableObjectFactory.java,v 1.1 2001/04/14 16:40:40 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:40:40 $
+ *
+ * ====================================================================
+ *
+ * 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.pool;
+
+/**
+ * A base implemenation of {@link PoolableObjectFactory <tt>PoolableObjectFactory</tt>}.
+ * <p>
+ * All operations defined here are essentially no-op's.
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: BasePoolableObjectFactory.java,v 1.1 2001/04/14 16:40:40 rwaldhoff Exp $
+ *
+ * @see PoolableObjectFactory
+ * @see BaseKeyedPoolableObjectFactory
+ */
+public abstract class BasePoolableObjectFactory implements PoolableObjectFactory {
+ public abstract Object makeObject();
+
+ /**
+ * No-op.
+ */
+ public void destroyObject(Object obj) {
+ }
+
+ /**
+ * This implementation always returns <tt>true</tt>.
+ * @return <tt>true</tt>
+ */
+ public boolean validateObject(Object obj) {
+ return true;
+ }
+
+ /**
+ * No-op.
+ */
+ public void activateObject(Object obj) {
+ }
+
+ /**
+ * No-op.
+ */
+ public void passivateObject(Object obj) {
+ }
+}
\ No newline at end of file
diff --git a/src/java/org/apache/commons/pool/KeyedObjectPool.java b/src/java/org/apache/commons/pool/KeyedObjectPool.java
new file mode 100644
index 0000000..12ab22b
--- /dev/null
+++ b/src/java/org/apache/commons/pool/KeyedObjectPool.java
@@ -0,0 +1,201 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/KeyedObjectPool.java,v 1.1 2001/04/14 16:40:43 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:40:43 $
+ *
+ * ====================================================================
+ *
+ * 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.pool;
+
+/**
+ * A simple "keyed" {@link Object} pooling interface.
+ * <p>
+ * A keyed pool caches mutiple named instances of {@link Object}s.
+ * <p>
+ * Example of use:
+ * <table border="1" cellspacing="0" cellpadding="3" align="center" bgcolor="#FFFFFF"><tr><td><pre>
+ * Object obj = <font color="#0000CC">null</font>;
+ * Object key = <font color="#CC0000">"Key"</font>;
+ * <font color="#0000CC">try</font> {
+ * obj = keyedPool.borrowObject(key);
+ * <font color="#00CC00">//...use the object...</font>
+ * } <font color="#0000CC">catch</font>(Exception e) {
+ * <font color="#00CC00">//...handle any exceptions...</font>
+ * } <font color="#0000CC">finally</font> {
+ * <font color="#00CC00">// make sure the object is returned to the pool</font>
+ * <font color="#0000CC">if</font>(<font color="#0000CC">null</font> != obj) {
+ * keyedPool.returnObject(key,obj);
+ * }
+ * }</pre></td></tr></table>
+ *
+ * <p>
+ * {@link KeyedObjectPool} implementations <i>may</i> choose to store at most
+ * one instance per key value, or may choose to maintain a pool of instances
+ * for each key (essentially creating a Map of Pools).
+ * </p>
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: KeyedObjectPool.java,v 1.1 2001/04/14 16:40:43 rwaldhoff Exp $
+ *
+ * @see KeyedPoolableObjectFactory
+ * @see KeyedObjectPoolFactory
+ * @see ObjectPool
+ */
+public interface KeyedObjectPool {
+ /**
+ * Obtain an <tt>Object</tt> from my pool
+ * using the specified <i>key</i>.
+ * By contract, clients MUST return
+ * the borrowed object using
+ * {@link #returnObject(java.lang.Object,java.lang.Object) <tt>returnObject</tt>},
+ * or a related method as defined in an implementation
+ * or sub-interface,
+ * using a <i>key</i> that is equivalent to the one used to
+ * borrow the <tt>Object</tt> in the first place.
+ *
+ * @param key the key used to obtain the object
+ * @return an <tt>Object</tt> from my pool.
+ */
+ public abstract Object borrowObject(Object key);
+
+ /**
+ * Return an <tt>Object</tt> to my pool.
+ * By contract, <i>obj</i> MUST have been obtained
+ * using {@link #borrowObject(java.lang.Object) <tt>borrowObject</tt>}
+ * or a related method as defined in an implementation
+ * or sub-interface,
+ * using a <i>key</i> that is equivalent to the one used to
+ * borrow the <tt>Object</tt> in the first place.
+ *
+ * @param key the key used to obtain the object
+ * @param obj a {@link #borrowObject(java.lang.Object) borrowed} <tt>Object</tt> to be returned.
+ */
+ public abstract void returnObject(Object key, Object obj);
+
+ /**
+ * Return the number of <tt>Object</tt>s
+ * corresponding to the given <i>key</i>
+ * currently idle in my pool, or
+ * throws {@link UnsupportedOperationException}
+ * if this information is not available.
+ *
+ * @param key the key
+ * @return the number of <tt>Object</tt>s corresponding to the given <i>key</i> currently idle in my pool
+ * @throws UnsupportedOperationException
+ */
+ public abstract int numIdle(Object key) throws UnsupportedOperationException;
+
+ /**
+ * Return the number of <tt>Object</tt>s
+ * currently borrowed from my pool corresponding to the
+ * given <i>key</i>, or
+ * throws {@link UnsupportedOperationException}
+ * if this information is not available.
+ *
+ * @param key the key
+ * @return the number of <tt>Object</tt>s corresponding to the given <i>key</i> currently borrowed in my pool
+ * @throws UnsupportedOperationException
+ */
+ public abstract int numActive(Object key) throws UnsupportedOperationException;
+
+ /**
+ * Return the total number of <tt>Object</tt>s
+ * currently idle in my pool, or
+ * throws {@link UnsupportedOperationException}
+ * if this information is not available.
+ *
+ * @return the total number of <tt>Object</tt>s currently idle in my pool
+ * @throws UnsupportedOperationException
+ */
+ public abstract int numIdle() throws UnsupportedOperationException;
+
+ /**
+ * Return the total number of <tt>Object</tt>s
+ * current borrowed from my pool, or
+ * throws {@link UnsupportedOperationException}
+ * if this information is not available.
+ *
+ * @return the total number of <tt>Object</tt>s currently borrowed in my pool
+ * @throws UnsupportedOperationException
+ */
+ public abstract int numActive() throws UnsupportedOperationException;
+
+ /**
+ * Clears my pool, or throws {@link UnsupportedOperationException}
+ * if the pool cannot be cleared.
+ */
+ public abstract void clear() throws UnsupportedOperationException;
+
+ /**
+ * Clears the specified pool, or throws {@link UnsupportedOperationException}
+ * if the pool cannot be cleared.
+ * @param key the key to clear
+ */
+ public abstract void clear(Object key) throws UnsupportedOperationException;
+
+ /**
+ * Close this pool, and free any resources associated with it.
+ */
+ public abstract void close();
+
+ /**
+ * Sets the {@link KeyedPoolableObjectFactory factory} I use
+ * to create new instances.
+ * @param factory the {@link KeyedPoolableObjectFactory} I use to create new instances.
+ */
+ public abstract void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException;
+}
\ No newline at end of file
diff --git a/src/java/org/apache/commons/pool/KeyedObjectPoolFactory.java b/src/java/org/apache/commons/pool/KeyedObjectPoolFactory.java
new file mode 100644
index 0000000..b81de67
--- /dev/null
+++ b/src/java/org/apache/commons/pool/KeyedObjectPoolFactory.java
@@ -0,0 +1,78 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/KeyedObjectPoolFactory.java,v 1.1 2001/04/14 16:40:45 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:40:45 $
+ *
+ * ====================================================================
+ *
+ * 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.pool;
+
+/**
+ * A simple factory interface for creating {@link KeyedObjectPool}s.
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: KeyedObjectPoolFactory.java,v 1.1 2001/04/14 16:40:45 rwaldhoff Exp $
+ *
+ * @see KeyedObjectPool
+ */
+public interface KeyedObjectPoolFactory {
+ /**
+ * Create and return a new {@link KeyedObjectPool}.
+ * @return a new, empty {@link KeyedObjectPool}
+ */
+ public abstract KeyedObjectPool createPool();
+}
diff --git a/src/java/org/apache/commons/pool/KeyedPoolableObjectFactory.java b/src/java/org/apache/commons/pool/KeyedPoolableObjectFactory.java
new file mode 100644
index 0000000..0ef34e2
--- /dev/null
+++ b/src/java/org/apache/commons/pool/KeyedPoolableObjectFactory.java
@@ -0,0 +1,145 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/KeyedPoolableObjectFactory.java,v 1.1 2001/04/14 16:40:47 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:40:47 $
+ *
+ * ====================================================================
+ *
+ * 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.pool;
+
+/**
+ * A simple interface defining life-cycle methods for
+ * <tt>Object</tt>s to be used in a
+ * {@link KeyedObjectPool <tt>KeyedObjectPool</tt>}.
+ * <p>
+ * By contract, when an {@link KeyedObjectPool <tt>KeyedObjectPool</tt>}
+ * delegates to a <tt>KeyedPoolableObjectFactory</tt>,
+ * <ol>
+ * <li>
+ * {@link #makeObject(java.lang.Object) <tt>makeObject</tt>} is called whenever a new <tt>Object</tt>
+ * is needed.
+ * </li>
+ * <li>
+ * {@link #activateObject(java.lang.Object,java.lang.Object) <tt>activateObject</tt>} is invoked
+ * on every <tt>Object</tt> before it is returned from the
+ * {@link KeyedObjectPool <tt>KeyedObjectPool</tt>}.
+ * </li>
+ * <li>
+ * {@link #passivateObject(java.lang.Object,java.lang.Object) <tt>passivateObject</tt>} is invoked
+ * on every <tt>Object</tt> when it is returned to the
+ * {@link KeyedObjectPool <tt>KeyedObjectPool</tt>}.
+ * </li>
+ * <li>
+ * {@link #destroyObject(java.lang.Object,java.lang.Object) <tt>destroyObject</tt>} is invoked
+ * on every <tt>Object</tt> when it is being "dropped" from the
+ * {@link KeyedObjectPool <tt>KeyedObjectPool</tt>} (whether due to the response from
+ * {@link #validateObject(java.lang.Object,java.lang.Object) <tt>validateObject</tt>}, or
+ * for reasons specific to the {@link KeyedObjectPool <tt>KeyedObjectPool</tt>} implementation.)
+ * </li>
+ * <li>
+ * {@link #validateObject(java.lang.Object,java.lang.Object) <tt>validateObject</tt>} is invoked
+ * in an implementation-specific fashion to determine if an <tt>Object</tt>
+ * is still valid to be returned by the{@link KeyedObjectPool <tt>KeyedObjectPool</tt>}.
+ * It will only be invoked on an {@link #activateObject(java.lang.Object,java.lang.Object) "activated"}
+ * <tt>Object</tt>.
+ * </li>
+ * </ol>
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: KeyedPoolableObjectFactory.java,v 1.1 2001/04/14 16:40:47 rwaldhoff Exp $
+ *
+ * @see KeyedObjectPool
+ */
+public interface KeyedPoolableObjectFactory {
+ /**
+ * Create an Object that can be returned by the pool.
+ * @param key the key used when constructing the object
+ * @return an Object that can be returned by the pool.
+ */
+ public abstract Object makeObject(Object key);
+
+ /**
+ * Destroy an Object no longer needed by the pool.
+ * @param key the key used when selecting the object
+ * @param obj the Object to be destroyed
+ */
+ public abstract void destroyObject(Object key, Object obj);
+
+ /**
+ * Ensures that the Object is safe to be returned by the pool.
+ * Returns <tt>false</tt> if this object should be destroyed.
+ * @param key the key used when selecting the object
+ * @param obj the <tt>Object</tt> to be validated
+ * @return <tt>false</tt> if this <i>obj</i> is not valid and should
+ * be dropped from the pool, <tt>true</tt> otherwise.
+ */
+ public abstract boolean validateObject(Object key, Object obj);
+
+ /**
+ * Reinitialize an Object to be returned by the pool.
+ * @param key the key used when selecting the object
+ * @param obj the <tt>Object</tt> to be activated
+ */
+ public abstract void activateObject(Object key, Object obj);
+
+ /**
+ * Uninitialize an Object to be returned to the pool.
+ * @param key the key used when selecting the object
+ * @param obj the <tt>Object</tt> to be passivated
+ */
+ public abstract void passivateObject(Object key, Object obj);
+}
\ No newline at end of file
diff --git a/src/java/org/apache/commons/pool/ObjectPool.java b/src/java/org/apache/commons/pool/ObjectPool.java
new file mode 100644
index 0000000..4558aa7
--- /dev/null
+++ b/src/java/org/apache/commons/pool/ObjectPool.java
@@ -0,0 +1,158 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/ObjectPool.java,v 1.1 2001/04/14 16:40:49 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:40:49 $
+ *
+ * ====================================================================
+ *
+ * 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.pool;
+
+/**
+ * A simple {@link Object} pooling interface.
+ * <p>
+ * Example of use:
+ * <table border="1" cellspacing="0" cellpadding="3" align="center" bgcolor="#FFFFFF"><tr><td><pre>
+ * Object obj = <font color="#0000CC">null</font>;
+ * <font color="#0000CC">try</font> {
+ * obj = pool.borrowObject();
+ * <font color="#00CC00">//...use the object...</font>
+ * } <font color="#0000CC">catch</font>(Exception e) {
+ * <font color="#00CC00">//...handle any exceptions...</font>
+ * } <font color="#0000CC">finally</font> {
+ * <font color="#00CC00">// make sure the object is returned to the pool</font>
+ * <font color="#0000CC">if</font>(<font color="#0000CC">null</font> != obj) {
+ * pool.returnObject(obj);
+ * }
+ * }</pre></td></tr></table>
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: ObjectPool.java,v 1.1 2001/04/14 16:40:49 rwaldhoff Exp $
+ *
+ * @see KeyedObjectPool
+ * @see ObjectPoolFactory
+ * @see PoolableObjectFactory
+ */
+public interface ObjectPool {
+ /**
+ * Obtain an <tt>Object</tt> from my pool.
+ * By contract, clients MUST return
+ * the borrowed object using
+ * {@link #returnObject(java.lang.Object) <tt>returnObject</tt>}
+ * or a related method as defined in an implementation
+ * or sub-interface.
+ * <p>
+ * The behaviour of this method when the pool has been exhausted
+ * is not specified (although it may be specified by implementations).
+ *
+ * @return an <tt>Object</tt> from my pool.
+ */
+ public abstract Object borrowObject();
+
+ /**
+ * Return an <tt>Object</tt> to my pool.
+ * By contract, <i>obj</i> MUST have been obtained
+ * using {@link #borrowObject() <tt>borrowObject</tt>}
+ * or a related method as defined in an implementation
+ * or sub-interface.
+ *
+ * @param obj a {@link #borrowObject() borrowed} <tt>Object</tt> to be returned.
+ */
+ public abstract void returnObject(Object obj);
+
+ /**
+ * Return the number of <tt>Object</tt>s
+ * currently idle in my pool, or
+ * throws {@link UnsupportedOperationException}
+ * if this information is not available.
+ *
+ * @return the number of <tt>Object</tt>s currently idle in my pool
+ * @throws UnsupportedOperationException
+ */
+ public abstract int numIdle() throws UnsupportedOperationException;
+
+ /**
+ * Return the number of <tt>Object</tt>s
+ * currently borrowed from my pool, or
+ * throws {@link UnsupportedOperationException}
+ * if this information is not available.
+ *
+ * @return the number of <tt>Object</tt>s currently borrowed in my pool
+ * @throws UnsupportedOperationException
+ */
+ public abstract int numActive() throws UnsupportedOperationException;
+
+ /**
+ * Clears any objects sitting idle in the pool, releasing any
+ * associated resources, or throws {@link UnsupportedOperationException}
+ * if the pool cannot be cleared.
+ *
+ * @throws UnsupportedOperationException
+ */
+ public abstract void clear() throws UnsupportedOperationException;
+
+ /**
+ * Close this pool, and free any resources associated with it.
+ */
+ public abstract void close();
+
+ /**
+ * Sets the {@link PoolableObjectFactory factory} I use
+ * to create new instances.
+ * @param factory the {@link PoolableObjectFactory} I use to create new instances.
+ */
+ public abstract void setFactory(PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException;
+}
diff --git a/src/java/org/apache/commons/pool/ObjectPoolFactory.java b/src/java/org/apache/commons/pool/ObjectPoolFactory.java
new file mode 100644
index 0000000..2afaad6
--- /dev/null
+++ b/src/java/org/apache/commons/pool/ObjectPoolFactory.java
@@ -0,0 +1,78 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/ObjectPoolFactory.java,v 1.1 2001/04/14 16:40:50 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:40:50 $
+ *
+ * ====================================================================
+ *
+ * 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.pool;
+
+/**
+ * A simple factory interface for creating {@link ObjectPool}s.
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: ObjectPoolFactory.java,v 1.1 2001/04/14 16:40:50 rwaldhoff Exp $
+ *
+ * @see ObjectPool
+ */
+public interface ObjectPoolFactory {
+ /**
+ * Create and return a new {@link ObjectPool}.
+ * @return a new, empty {@link ObjectPool}
+ */
+ public abstract ObjectPool createPool();
+}
diff --git a/src/java/org/apache/commons/pool/PoolableObjectFactory.java b/src/java/org/apache/commons/pool/PoolableObjectFactory.java
new file mode 100644
index 0000000..9e7ca95
--- /dev/null
+++ b/src/java/org/apache/commons/pool/PoolableObjectFactory.java
@@ -0,0 +1,141 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/PoolableObjectFactory.java,v 1.1 2001/04/14 16:40:53 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:40:53 $
+ *
+ * ====================================================================
+ *
+ * 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.pool;
+
+/**
+ * A simple interface defining life-cycle methods for
+ * <tt>Object</tt>s to be used in an
+ * {@link ObjectPool <tt>ObjectPool</tt>}.
+ * <p>
+ * By contract, when an {@link ObjectPool <tt>ObjectPool</tt>}
+ * delegates to a <tt>PoolableObjectFactory</tt>,
+ * <ol>
+ * <li>
+ * {@link #makeObject <tt>makeObject</tt>} is called whenever a new <tt>Object</tt>
+ * is needed.
+ * </li>
+ * <li>
+ * {@link #activateObject(java.lang.Object) <tt>activateObject</tt>} is invoked
+ * on every <tt>Object</tt> before it is returned from the
+ * {@link ObjectPool}, and before it is {@link #validateObject validated}.
+ * </li>
+ * <li>
+ * {@link #passivateObject(java.lang.Object) <tt>passivateObject</tt>} is invoked
+ * on every <tt>Object</tt> when it is returned to the
+ * {@link ObjectPool <tt>ObjectPool</tt>}.
+ * </li>
+ * <li>
+ * {@link #destroyObject(java.lang.Object) <tt>destroyObject</tt>} is invoked
+ * on every <tt>Object</tt> when it is being "dropped" from the
+ * {@link ObjectPool <tt>ObjectPool</tt>} (whether due to the response from
+ * {@link #validateObject(java.lang.Object) <tt>validateObject</tt>}, or
+ * for reasons specific to the {@link ObjectPool <tt>ObjectPool</tt>} implementation.)
+ * </li>
+ * <li>
+ * {@link #validateObject(java.lang.Object) <tt>validateObject</tt>} is invoked
+ * in an implementation-specific fashion to determine if an <tt>Object</tt>
+ * is still valid to be returned by the {@link ObjectPool <tt>ObjectPool</tt>}.
+ * It will only be invoked on an {@link #activateObject(java.lang.Object) "activated"}
+ * <tt>Object</tt>.
+ * </li>
+ * </ol>
+ *
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: PoolableObjectFactory.java,v 1.1 2001/04/14 16:40:53 rwaldhoff Exp $
+ *
+ * @see ObjectPool
+ */
+public interface PoolableObjectFactory {
+ /**
+ * Creates an Object that can be returned by the pool.
+ * @return an Object that can be returned by the pool.
+ */
+ public abstract Object makeObject();
+
+ /**
+ * Destroys an Object no longer needed by the pool.
+ * @param obj the <tt>Object</tt> to be destroyed
+ */
+ public abstract void destroyObject(Object obj);
+
+ /**
+ * Ensures that the Object is safe to be returned by the pool.
+ * Returns <tt>false</tt> if this object should be destroyed.
+ * @param obj the <tt>Object</tt> to be validated
+ * @return <tt>false</tt> if this <i>obj</i> is not valid and should
+ * be dropped from the pool, <tt>true</tt> otherwise.
+ */
+ public abstract boolean validateObject(Object obj);
+
+ /**
+ * Reinitialize an Object to be returned by the pool.
+ * @param obj the <tt>Object</tt> to be activated
+ */
+ public abstract void activateObject(Object obj);
+
+ /**
+ * Uninitialize an Object to be returned to the pool.
+ * @param obj the <tt>Object</tt> to be passivated
+ */
+ public abstract void passivateObject(Object obj);
+}
\ No newline at end of file
diff --git a/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java b/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java
new file mode 100644
index 0000000..2e3cd60
--- /dev/null
+++ b/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java
@@ -0,0 +1,1282 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java,v 1.1 2001/04/14 16:41:21 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:41:21 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import org.apache.commons.pool.*;
+import org.apache.commons.collections.CursorableLinkedList;
+import org.apache.commons.collections.CursorableLinkedList.Cursor;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Enumeration;
+import java.util.EmptyStackException;
+import java.util.ListIterator;
+import java.util.HashMap;
+import java.util.Set;
+
+/**
+ * A configurable {@link KeyedObjectPool} implementation.
+ * <p>
+ * When coupled with the appropriate {@link KeyedPoolableObjectFactory},
+ * <tt>GenericKeyedObjectPool</tt> provides robust pooling functionality for
+ * arbitrary objects.
+ * <p>
+ * A <tt>GenericKeyedObjectPool</tt> provides a number of configurable parameters:
+ * <ul>
+ * <li>
+ * {@link #setMaxActive <i>maxActive</i>} controls the maximum number of objects (per key)
+ * that can be borrowed from the pool at one time. When non-positive, there
+ * is no limit to the number of objects that may be active at one time.
+ * When {@link #setMaxActive <i>maxActive</i>} is exceeded, the pool is said to be exhausted.
+ * </li>
+ * <li>
+ * {@link #setMaxIdle <i>maxIdle</i>} controls the maximum number of objects that can
+ * sit idle in the pool (per key) at any time. When non-positive, there
+ * is no limit to the number of objects that may be idle at one time.
+ * </li>
+ * <li>
+ * {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} specifies the
+ * behaviour of the {@link #borrowObject} method when the pool is exhausted:
+ * <ul>
+ * <li>
+ * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
+ * {@link #WHEN_EXHAUSTED_FAIL}, {@link #borrowObject} will throw
+ * a {@link NoSuchElementException}
+ * </li>
+ * <li>
+ * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
+ * {@link #WHEN_EXHAUSTED_GROW}, {@link #borrowObject} will create a new
+ * object and return it(essentially making {@link #setMaxActive <i>maxActive</i>}
+ * meaningless.)
+ * </li>
+ * <li>
+ * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>}
+ * is {@link #WHEN_EXHAUSTED_BLOCK}, {@link #borrowObject} will block
+ * (invoke {@link Object#wait} until a new or idle object is available.
+ * If a positive {@link #setMaxWait <i>maxWait</i>}
+ * value is supplied, the {@link #borrowObject} will block for at
+ * most that many milliseconds, after which a {@link NoSuchElementException}
+ * will be thrown. If {@link #setMaxWait <i>maxWait</i>} is non-positive,
+ * the {@link #borrowObject} method will block indefinitely.
+ * </li>
+ * </ul>
+ * </li>
+ * <li>
+ * When {@link #setTestOnBorrow <i>testOnBorrow</i>} is set, the pool will
+ * attempt to validate each object before it is returned from the
+ * {@link #borrowObject} method. (Using the provided factory's
+ * {@link PoolableObjectFactory#validateObject} method.) Objects that fail
+ * to validate will be dropped from the pool, and a different object will
+ * be borrowed.
+ * </li>
+ * <li>
+ * When {@link #setTestOnReturn <i>testOnReturn</i>} is set, the pool will
+ * attempt to validate each object before it is returned to the pool in the
+ * {@link #returnObject} method. (Using the provided factory's
+ * {@link PoolableObjectFactory#validateObject}
+ * method.) Objects that fail to validate will be dropped from the pool.
+ * </li>
+ * </ul>
+ * <p>
+ * Optionally, one may configure the pool to examine and possibly evict objects as they
+ * sit idle in the pool. This is performed by an "idle object eviction" thread, which
+ * runs asychronously. The idle object eviction thread may be configured using the
+ * following attributes:
+ * <ul>
+ * <li>
+ * {@link #setTimeBetweenEvictionRunsMillis <i>timeBetweenEvictionRunsMillis</i>}
+ * indicates how long the eviction thread should sleep before "runs" of examining
+ * idle objects. When non-positive, no eviction thread will be launched.
+ * </li>
+ * <li>
+ * {@link #setMinEvictableIdleTimeMillis <i>minEvictableIdleTimeMillis</i>}
+ * specifies the minimum amount of time that an object may sit idle in the pool
+ * before it is eligable for eviction due to idle time. When non-positive, no object
+ * will be dropped from the pool due to idle time alone.
+ * </li>
+ * <li>
+ * {@link #setTestWhileIdle <i>testWhileIdle</i>} indicates whether or not idle
+ * objects should be validated using the factory's
+ * {@link PoolableObjectFactory#validateObject} method. Objects
+ * that fail to validate will be dropped from the pool.
+ * </li>
+ * </ul>
+ * @see GenericObjectPool
+ * @author Rodney Waldhoff
+ * @version $Id: GenericKeyedObjectPool.java,v 1.1 2001/04/14 16:41:21 rwaldhoff Exp $
+ */
+public class GenericKeyedObjectPool implements KeyedObjectPool {
+
+ //--- public constants -------------------------------------------
+
+ /**
+ * A "when exhausted action" type indicating that when the pool is
+ * exhausted (i.e., the maximum number of active objects has
+ * been reached), the {@link #borrowObject}
+ * method should fail, throwing a {@link NoSuchElementException}.
+ * @see #WHEN_EXHAUSTED_BLOCK
+ * @see #WHEN_EXHAUSTED_GROW
+ * @see #setWhenExhaustedAction
+ */
+ public static final byte WHEN_EXHAUSTED_FAIL = 0;
+
+ /**
+ * A "when exhausted action" type indicating that when the pool
+ * is exhausted (i.e., the maximum number
+ * of active objects has been reached), the {@link #borrowObject}
+ * method should block until a new object is available, or the
+ * {@link #getMaxWait maximum wait time} has been reached.
+ * @see #WHEN_EXHAUSTED_FAIL
+ * @see #WHEN_EXHAUSTED_GROW
+ * @see #setMaxWait
+ * @see #getMaxWait
+ * @see #setWhenExhaustedAction
+ */
+ public static final byte WHEN_EXHAUSTED_BLOCK = 1;
+
+ /**
+ * A "when exhausted action" type indicating that when the pool is
+ * exhausted (i.e., the maximum number
+ * of active objects has been reached), the {@link #borrowObject}
+ * method should simply create a new object anyway.
+ * @see #WHEN_EXHAUSTED_FAIL
+ * @see #WHEN_EXHAUSTED_GROW
+ * @see #setWhenExhaustedAction
+ */
+ public static final byte WHEN_EXHAUSTED_GROW = 2;
+
+ /**
+ * The default cap on the number of idle instances in the pool
+ * (per key).
+ * @see #getMaxIdle
+ * @see #setMaxIdle
+ */
+ public static final int DEFAULT_MAX_IDLE = 8;
+
+ /**
+ * The default cap on the total number of active instances from the pool
+ * (per key).
+ * @see #getMaxActive
+ * @see #setMaxActive
+ */
+ public static final int DEFAULT_MAX_ACTIVE = 8;
+
+ /**
+ * The default "when exhausted action" for the pool.
+ * @see #WHEN_EXHAUSTED_BLOCK
+ * @see #WHEN_EXHAUSTED_FAIL
+ * @see #WHEN_EXHAUSTED_GROW
+ * @see #setWhenExhaustedAction
+ */
+ public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK;
+
+ /**
+ * The default maximum amount of time (in millis) the
+ * {@link #borrowObject} method should block before throwing
+ * an exception when the pool is exhausted and the
+ * {@link #getWhenExhaustedAction "when exhausted" action} is
+ * {@link #WHEN_EXHAUSTED_BLOCK}.
+ * @see #getMaxWait
+ * @see #setMaxWait
+ */
+ public static final long DEFAULT_MAX_WAIT = -1L;
+
+ /**
+ * The default "test on borrow" value.
+ * @see #getTestOnBorrow
+ * @see #setTestOnBorrow
+ */
+ public static final boolean DEFAULT_TEST_ON_BORROW = false;
+
+ /**
+ * The default "test on return" value.
+ * @see #getTestOnReturn
+ * @see #setTestOnReturn
+ */
+ public static final boolean DEFAULT_TEST_ON_RETURN = false;
+
+ /**
+ * The default "test while idle" value.
+ * @see #getTestWhileIdle
+ * @see #setTestWhileIdle
+ * @see #getTimeBetweenEvictionRunsMillis
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ public static final boolean DEFAULT_TEST_WHILE_IDLE = false;
+
+ /**
+ * The default "time between eviction runs" value.
+ * @see #getTimeBetweenEvictionRunsMillis
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;
+
+ /**
+ * The default number of objects to examine per run in the
+ * idle object evictor.
+ * @see #getNumTestsPerEvictionRun
+ * @see #setNumTestsPerEvictionRun
+ * @see #getTimeBetweenEvictionRunsMillis
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;
+
+ /**
+ * The default value for {@link #getMinEvictableIdleTimeMillis}.
+ * @see #getMinEvictableIdleTimeMillis
+ * @see #setMinEvictableIdleTimeMillis
+ */
+ public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;
+
+ //--- constructors -----------------------------------------------
+
+ /**
+ * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
+ */
+ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory) {
+ this(factory,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ /**
+ * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
+ * @param config a non-<tt>null</tt> {@link GenericKeyedObjectPool.Config} describing my configuration
+ */
+ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, GenericKeyedObjectPool.Config config) {
+ this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle);
+ }
+
+ /**
+ * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
+ * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
+ */
+ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive) {
+ this(factory,maxActive,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ /**
+ * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
+ * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
+ * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
+ * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
+ */
+ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ /**
+ * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
+ * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
+ * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
+ * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
+ * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
+ * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
+ */
+ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,testOnBorrow,testOnReturn,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ /**
+ * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
+ * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
+ * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
+ * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
+ * @param maxIdle the maximum number of idle objects in my pool (per key) (see {@link #setMaxIdle})
+ */
+ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ /**
+ * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
+ * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
+ * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
+ * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})
+ * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
+ * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
+ * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
+ */
+ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,testOnBorrow,testOnReturn,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ /**
+ * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
+ * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
+ * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
+ * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
+ * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
+ * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
+ * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
+ * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
+ * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
+ * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
+ * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
+ */
+ public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
+ _factory = factory;
+ _maxActive = maxActive;
+ switch(whenExhaustedAction) {
+ case WHEN_EXHAUSTED_BLOCK:
+ case WHEN_EXHAUSTED_FAIL:
+ case WHEN_EXHAUSTED_GROW:
+ _whenExhaustedAction = whenExhaustedAction;
+ break;
+ default:
+ throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
+ }
+ _maxWait = maxWait;
+ _maxIdle = maxIdle;
+ _testOnBorrow = testOnBorrow;
+ _testOnReturn = testOnReturn;
+ _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ _numTestsPerEvictionRun = numTestsPerEvictionRun;
+ _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+ _testWhileIdle = testWhileIdle;
+
+ _poolMap = new HashMap();
+ _activeMap = new HashMap();
+ _poolList = new CursorableLinkedList();
+
+ if(_timeBetweenEvictionRunsMillis > 0) {
+ _evictor = new Evictor();
+ Thread t = new Thread(_evictor);
+ t.setDaemon(true);
+ t.start();
+ }
+ }
+
+ //--- public methods ---------------------------------------------
+
+ //--- configuration methods --------------------------------------
+
+ /**
+ * Returns the cap on the total number of active instances from my pool.
+ * @return the cap on the total number of active instances from my pool.
+ * @see #setMaxActive
+ */
+ public int getMaxActive() {
+ return _maxActive;
+ }
+
+ /**
+ * Sets the cap on the total number of active instances from my pool.
+ * @param maxActive The cap on the total number of active instances from my pool.
+ * Use a negative value for an infinite number of instances.
+ * @see #getMaxActive
+ */
+ public void setMaxActive(int maxActive) {
+ _maxActive = maxActive;
+ synchronized(this) {
+ notifyAll();
+ }
+ }
+
+ /**
+ * Returns the action to take when the {@link #borrowObject} method
+ * is invoked when the pool is exhausted (the maximum number
+ * of "active" objects has been reached).
+ *
+ * @return one of {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL} or {@link #WHEN_EXHAUSTED_GROW}
+ * @see #setWhenExhaustedAction
+ */
+ public byte getWhenExhaustedAction() {
+ return _whenExhaustedAction;
+ }
+
+ /**
+ * Sets the action to take when the {@link #borrowObject} method
+ * is invoked when the pool is exhausted (the maximum number
+ * of "active" objects has been reached).
+ *
+ * @param whenExhaustedAction the action code, which must be one of
+ * {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL},
+ * or {@link #WHEN_EXHAUSTED_GROW}
+ * @see #getWhenExhaustedAction
+ */
+ public synchronized void setWhenExhaustedAction(byte whenExhaustedAction) {
+ switch(whenExhaustedAction) {
+ case WHEN_EXHAUSTED_BLOCK:
+ case WHEN_EXHAUSTED_FAIL:
+ case WHEN_EXHAUSTED_GROW:
+ _whenExhaustedAction = whenExhaustedAction;
+ notifyAll();
+ break;
+ default:
+ throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
+ }
+ }
+
+
+ /**
+ * Returns the maximum amount of time (in milliseconds) the
+ * {@link #borrowObject} method should block before throwing
+ * an exception when the pool is exhausted and the
+ * {@link #setWhenExhaustedAction "when exhausted" action} is
+ * {@link #WHEN_EXHAUSTED_BLOCK}.
+ *
+ * When less than 0, the {@link #borrowObject} method
+ * may block indefinitely.
+ *
+ * @see #setMaxWait
+ * @see #setWhenExhaustedAction
+ * @see #WHEN_EXHAUSTED_BLOCK
+ */
+ public synchronized long getMaxWait() {
+ return _maxWait;
+ }
+
+ /**
+ * Sets the maximum amount of time (in milliseconds) the
+ * {@link #borrowObject} method should block before throwing
+ * an exception when the pool is exhausted and the
+ * {@link #setWhenExhaustedAction "when exhausted" action} is
+ * {@link #WHEN_EXHAUSTED_BLOCK}.
+ *
+ * When less than 0, the {@link #borrowObject} method
+ * may block indefinitely.
+ *
+ * @see #getMaxWait
+ * @see #setWhenExhaustedAction
+ * @see #WHEN_EXHAUSTED_BLOCK
+ */
+ public synchronized void setMaxWait(long maxWait) {
+ _maxWait = maxWait;
+ }
+
+ /**
+ * Returns the cap on the number of "idle" instances in the pool.
+ * @return the cap on the number of "idle" instances in the pool.
+ * @see #setMaxIdle
+ */
+ public int getMaxIdle() {
+ return _maxIdle;
+ }
+
+ /**
+ * Sets the cap on the number of "idle" instances in the pool.
+ * @param maxIdle The cap on the number of "idle" instances in the pool.
+ * Use a negative value to indicate an unlimited number
+ * of idle instances.
+ * @see #getMaxIdle
+ */
+ public void setMaxIdle(int maxIdle) {
+ _maxIdle = maxIdle;
+ synchronized(this) {
+ notifyAll();
+ }
+ }
+
+ /**
+ * 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) {
+ _testOnBorrow = testOnBorrow;
+ }
+
+ /**
+ * 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) {
+ _testOnReturn = testOnReturn;
+ }
+
+ /**
+ * 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) {
+ if(_timeBetweenEvictionRunsMillis > 0 && timeBetweenEvictionRunsMillis <= 0) {
+ _evictor.cancel();
+ _evictor = null;
+ _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ } else if(_timeBetweenEvictionRunsMillis <= 0 && timeBetweenEvictionRunsMillis > 0) {
+ _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ _evictor = new Evictor();
+ Thread t = new Thread(_evictor);
+ t.setDaemon(true);
+ t.start();
+ } else {
+ _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ }
+ }
+
+ /**
+ * 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) {
+ _numTestsPerEvictionRun = numTestsPerEvictionRun;
+ }
+
+ /**
+ * 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 long 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(long minEvictableIdleTimeMillis) {
+ _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+ }
+
+ /**
+ * 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) {
+ _testWhileIdle = testWhileIdle;
+ }
+
+ /**
+ * Sets my configuration.
+ * @see GenericKeyedObjectPool.Config
+ */
+ public synchronized void setConfig(GenericKeyedObjectPool.Config conf) {
+ setMaxIdle(conf.maxIdle);
+ setMaxActive(conf.maxActive);
+ setMaxWait(conf.maxWait);
+ setWhenExhaustedAction(conf.whenExhaustedAction);
+ setTestOnBorrow(conf.testOnBorrow);
+ setTestOnReturn(conf.testOnReturn);
+ setTestWhileIdle(conf.testWhileIdle);
+ setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);
+ setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);
+ setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);
+ }
+
+ //-- ObjectPool methods ------------------------------------------
+
+ public synchronized Object borrowObject(Object key) {
+ long starttime = System.currentTimeMillis();
+ for(;;) {
+ CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key));
+ if(null == pool) {
+ pool = new CursorableLinkedList();
+ _poolMap.put(key,pool);
+ _poolList.add(key);
+ }
+ ObjectTimestampPair pair = null;
+ // if there are any sleeping, just grab one of those
+ try {
+ pair = (ObjectTimestampPair)(pool.removeFirst());
+ if(null != pair) {
+ _totalIdle--;
+ }
+ } catch(NoSuchElementException e) { /* ignored */
+ }
+ // otherwise
+ if(null == pair) {
+ // check if we can create one
+ // (note we know that the num sleeping is 0, else we wouldn't be here)
+ int active = 0;
+ Integer act = (Integer)(_activeMap.get(key));
+ if(null != act) {
+ active = act.intValue();
+ }
+ if(_maxActive > 0 && active < _maxActive) {
+ Object obj = _factory.makeObject(key);
+ pair = new ObjectTimestampPair(obj);
+ } else {
+ // the pool is exhausted
+ switch(_whenExhaustedAction) {
+ case WHEN_EXHAUSTED_GROW:
+ Object obj = _factory.makeObject(key);
+ pair = new ObjectTimestampPair(obj);
+ break;
+ case WHEN_EXHAUSTED_FAIL:
+ throw new NoSuchElementException();
+ case WHEN_EXHAUSTED_BLOCK:
+ try {
+ if(_maxWait <= 0) {
+ wait();
+ } else {
+ wait(_maxWait);
+ }
+ } catch(InterruptedException e) {
+ // ignored
+ }
+ if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
+ throw new NoSuchElementException("Timeout waiting for idle object");
+ } else {
+ continue; // keep looping
+ }
+ default:
+ throw new IllegalArgumentException("whenExhaustedAction " + _whenExhaustedAction + " not recognized.");
+ }
+ }
+ }
+ _factory.activateObject(key,pair.value);
+ if(_testOnBorrow && !_factory.validateObject(key,pair.value)) {
+ try {
+ _factory.passivateObject(key,pair.value);
+ } catch(Exception e) {
+ ; // ignored, we're throwing it out anyway
+ }
+ _factory.destroyObject(key,pair.value);
+ } else {
+ Integer active = (Integer)(_activeMap.get(key));
+ if(null == active) {
+ _activeMap.put(key,new Integer(1));
+ } else {
+ _activeMap.put(key,new Integer(active.intValue() + 1));
+ }
+ _totalActive++;
+ return pair.value;
+ }
+ }
+ }
+
+ public synchronized void clear() throws UnsupportedOperationException {
+ Iterator keyiter = _poolList.iterator();
+ while(keyiter.hasNext()) {
+ Object key = keyiter.next();
+ CursorableLinkedList list = (CursorableLinkedList)(_poolMap.get(key));
+ Iterator it = list.iterator();
+ while(it.hasNext()) {
+ _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
+ it.remove();
+ }
+ }
+ _poolMap.clear();
+ _poolList.clear();
+ _totalIdle = 0;
+ notifyAll();
+ }
+
+ public synchronized void clear(Object key) throws UnsupportedOperationException {
+ CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.remove(key));
+ if(null == pool) {
+ return;
+ } else {
+ _poolList.remove(key);
+ Iterator it = pool.iterator();
+ while(it.hasNext()) {
+ _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
+ it.remove();
+ _totalIdle--;
+ }
+ }
+ notifyAll();
+ }
+
+ public int numActive() {
+ return _totalActive;
+ }
+
+ public int numIdle() {
+ return _totalIdle;
+ }
+
+ public synchronized int numActive(Object key) {
+ try {
+ return((Integer)(_activeMap.get(key))).intValue();
+ } catch(Exception e) {
+ return 0;
+ }
+ }
+
+ public synchronized int numIdle(Object key) {
+ try {
+ return((CursorableLinkedList)(_poolMap.get(key))).size();
+ } catch(Exception e) {
+ return 0;
+ }
+ }
+
+ public synchronized void returnObject(Object key, Object obj) {
+ _totalActive--;
+
+ CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key));
+ if(null == pool) {
+ pool = new CursorableLinkedList();
+ _poolMap.put(key,pool);
+ _poolList.add(key);
+ }
+
+ Integer active = (Integer)(_activeMap.get(key));
+ if(null == active) {
+ // do nothing, either null or zero is OK
+ } else if(active.intValue() <= 1) {
+ _activeMap.remove(key);
+ } else {
+ _activeMap.put(key,new Integer(active.intValue() - 1));
+ }
+
+ if(_maxIdle > 0 && (pool.size() >= _maxIdle || (_testOnReturn && !_factory.validateObject(key,obj)))) {
+ try {
+ _factory.passivateObject(key,obj);
+ } catch(Exception e) {
+ ; // ignored, we're throwing it out anyway
+ }
+ _factory.destroyObject(key,obj);
+ } else {
+ try {
+ _factory.passivateObject(key,obj);
+ pool.addFirst(new ObjectTimestampPair(obj));
+ _totalIdle++;
+ } catch(Exception e) {
+ _factory.destroyObject(key,obj);
+ }
+ }
+ notifyAll();
+ }
+
+ synchronized public void close() {
+ clear();
+ _poolList = null;
+ _poolMap = null;
+ _activeMap = null;
+ if(null != _evictor) {
+ _evictor.cancel();
+ _evictor = null;
+ }
+ }
+
+ synchronized public void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
+ if(0 < numActive()) {
+ throw new IllegalStateException("Objects are already active");
+ } else {
+ clear();
+ _factory = factory;
+ }
+ }
+
+ //--- package methods --------------------------------------------
+
+ synchronized String debugInfo() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("Active: ").append(numActive()).append("\n");
+ buf.append("Idle: ").append(numIdle()).append("\n");
+ Iterator it = _poolList.iterator();
+ while(it.hasNext()) {
+ buf.append("\t").append(_poolMap.get(it.next())).append("\n");
+ }
+ return buf.toString();
+ }
+
+
+ //--- inner classes ----------------------------------------------
+
+ /**
+ * A simple "struct" encapsulating an object instance and a timestamp.
+ */
+ class ObjectTimestampPair {
+ Object value;
+ long tstamp;
+
+ ObjectTimestampPair(Object val) {
+ value = val;
+ tstamp = System.currentTimeMillis();
+ }
+
+ ObjectTimestampPair(Object val, long time) {
+ value = val;
+ tstamp = time;
+ }
+
+ public String toString() {
+ return value + ";" + tstamp;
+ }
+ }
+
+ /**
+ * The idle object evictor thread.
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ class Evictor implements Runnable {
+ protected boolean _cancelled = false;
+
+ void cancel() {
+ _cancelled = true;
+ }
+
+ public void run() {
+ CursorableLinkedList.Cursor objcursor = null;
+ CursorableLinkedList.Cursor keycursor = null;
+ Object key = null;
+
+ while(!_cancelled) {
+ long sleeptime = 0L;
+ synchronized(GenericKeyedObjectPool.this) {
+ sleeptime = _timeBetweenEvictionRunsMillis;
+ }
+ try {
+ Thread.currentThread().sleep(sleeptime);
+ } catch(Exception e) {
+ ; // ignored
+ }
+ try {
+ synchronized(GenericKeyedObjectPool.this) {
+ for(int i=0,m=getNumTests();i<m;i++) {
+ if(_poolMap.size() > 0) {
+ // if we don't have a key cursor, then create one, and close any object cursor
+ if(null == keycursor) {
+ keycursor = _poolList.cursor();
+ key = null;
+ if(null != objcursor) {
+ objcursor.close();
+ objcursor = null;
+ }
+ }
+ // if we don't have an object cursor
+ if(null == objcursor) {
+ // if the keycursor has a next value, then use it
+ if(keycursor.hasNext()) {
+ key = keycursor.next();
+ CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key));
+ objcursor = pool.cursor(pool.size());
+ } else {
+ // else close the key cursor and loop back around
+ if(null != keycursor) {
+ keycursor.close();
+ keycursor = _poolList.cursor();
+ if(null != objcursor) {
+ objcursor.close();
+ objcursor = null;
+ }
+ }
+ continue;
+ }
+ }
+ // if the objcursor has a previous object, then test it
+ if(objcursor.hasPrevious()) {
+ ObjectTimestampPair pair = (ObjectTimestampPair)(objcursor.previous());
+ if(System.currentTimeMillis() - pair.tstamp > _minEvictableIdleTimeMillis) {
+ try {
+ objcursor.remove();
+ _totalIdle--;
+ _factory.destroyObject(key,pair.value);
+
+ // if that was the last object for that key, drop that pool
+ if( ((CursorableLinkedList)(_poolMap.get(key))).isEmpty() ) {
+ _poolMap.remove(key);
+ _poolList.remove(key);
+ }
+
+
+ } catch(Exception e) {
+ ; // ignored
+ }
+ } else if(_testWhileIdle) {
+ boolean active = false;
+ try {
+ _factory.activateObject(key,pair.value);
+ active = true;
+ } catch(Exception e) {
+ objcursor.remove();
+ try {
+ _factory.passivateObject(key,pair.value);
+ } catch(Exception ex) {
+ ; // ignored
+ }
+ _factory.destroyObject(key,pair.value);
+ }
+ if(active) {
+ if(!_factory.validateObject(key,pair.value)) {
+ try {
+ objcursor.remove();
+ _totalIdle--;
+ try {
+ _factory.passivateObject(key,pair.value);
+ } catch(Exception e) {
+ ; // ignored
+ }
+ _factory.destroyObject(key,pair.value);
+ if( ((CursorableLinkedList)(_poolMap.get(key))).isEmpty() ) {
+ _poolMap.remove(key);
+ _poolList.remove(key);
+ }
+
+ } catch(Exception e) {
+ ; // ignored
+ }
+ } else {
+ try {
+ _factory.passivateObject(key,pair.value);
+ } catch(Exception e) {
+ objcursor.remove();
+ _totalIdle--;
+ _factory.destroyObject(key,pair.value);
+ if( ((CursorableLinkedList)(_poolMap.get(key))).isEmpty() ) {
+ _poolMap.remove(key);
+ _poolList.remove(key);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // else the objcursor is done, so close it and loop around
+ if(objcursor != null) {
+ objcursor.close();
+ objcursor = null;
+ }
+ }
+ }
+ }
+ }
+ } catch(Exception e) {
+ ; // ignored
+ }
+ }
+ if(null != keycursor) {
+ keycursor.close();
+ }
+ if(null != objcursor) {
+ objcursor.close();
+ }
+ }
+
+ private int getNumTests() {
+ if(_numTestsPerEvictionRun >= 0) {
+ return _numTestsPerEvictionRun;
+ } else {
+ return(int)(Math.ceil((double)_totalIdle/Math.abs((double)_numTestsPerEvictionRun)));
+ }
+ }
+ }
+
+ /**
+ * A simple "struct" encapsulating the
+ * configuration information for a {@link GenericKeyedObjectPool}.
+ * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory,GenericKeyedObjectPool.Config)
+ * @see GenericKeyedObjectPool#setConfig
+ */
+ public static class Config {
+ public int maxIdle = GenericKeyedObjectPool.DEFAULT_MAX_IDLE;
+ public int maxActive = GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE;
+ public long maxWait = GenericKeyedObjectPool.DEFAULT_MAX_WAIT;
+ public byte whenExhaustedAction = GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
+ public boolean testOnBorrow = GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW;
+ public boolean testOnReturn = GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN;
+ public boolean testWhileIdle = GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE;
+ public long timeBetweenEvictionRunsMillis = GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
+ public int numTestsPerEvictionRun = GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
+ public long minEvictableIdleTimeMillis = GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
+ }
+
+ //--- protected attributes ---------------------------------------
+
+ /**
+ * The cap on the number of idle instances in the pool (per key).
+ * @see #setMaxIdle
+ * @see #getMaxIdle
+ */
+ protected int _maxIdle = DEFAULT_MAX_IDLE;
+
+ /**
+ * The cap on the total number of active instances from the pool (per key).
+ * @see #setMaxActive
+ * @see #getMaxActive
+ */
+ protected int _maxActive = DEFAULT_MAX_ACTIVE;
+
+ /**
+ * The maximum amount of time (in millis) the
+ * {@link #borrowObject} method should block before throwing
+ * an exception when the pool is exhausted and the
+ * {@link #getWhenExhaustedAction "when exhausted" action} is
+ * {@link #WHEN_EXHAUSTED_BLOCK}.
+ *
+ * When less than 0, the {@link #borrowObject} method
+ * may block indefinitely.
+ *
+ * @see #setMaxWait
+ * @see #getMaxWait
+ * @see #WHEN_EXHAUSTED_BLOCK
+ * @see #setWhenExhaustedAction
+ * @see #getWhenExhaustedAction
+ */
+ protected long _maxWait = DEFAULT_MAX_WAIT;
+
+ /**
+ * The action to take when the {@link #borrowObject} method
+ * is invoked when the pool is exhausted (the maximum number
+ * of "active" objects has been reached).
+ *
+ * @see #WHEN_EXHAUSTED_BLOCK
+ * @see #WHEN_EXHAUSTED_FAIL
+ * @see #WHEN_EXHAUSTED_GROW
+ * @see #DEFAULT_WHEN_EXHAUSTED_ACTION
+ * @see #setWhenExhaustedAction
+ * @see #getWhenExhaustedAction
+ */
+ protected byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION;
+
+ /**
+ * 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
+ * @see #getTestOnBorrow
+ */
+ protected boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW;
+
+ /**
+ * When <tt>true</tt>, objects will be
+ * {@link PoolableObjectFactory#validateObject validated}
+ * before being returned to the pool within the
+ * {@link #returnObject}.
+ *
+ * @see #getTestOnReturn
+ * @see #setTestOnReturn
+ */
+ protected boolean _testOnReturn = DEFAULT_TEST_ON_RETURN;
+
+ /**
+ * 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 #getTestWhileIdle
+ * @see #getTimeBetweenEvictionRunsMillis
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ protected boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE;
+
+ /**
+ * 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
+ * @see #getTimeBetweenEvictionRunsMillis
+ */
+ protected long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
+
+ /**
+ * 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 #setNumTestsPerEvictionRun
+ * @see #getNumTestsPerEvictionRun
+ * @see #getTimeBetweenEvictionRunsMillis
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ protected int _numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
+
+ /**
+ * 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 #setMinEvictableIdleTimeMillis
+ * @see #getMinEvictableIdleTimeMillis
+ * @see #getTimeBetweenEvictionRunsMillis
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ protected long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
+
+
+ /** My hash of pools (CursorableLinkedLists). */
+ protected HashMap _poolMap = null;
+
+ /**
+ * A cursorable list of my pools.
+ * @see GenericKeyedObjectPool.Evictor#run
+ */
+ protected CursorableLinkedList _poolList = null;
+
+ /** Count of active objects, per key. */
+ protected HashMap _activeMap = null;
+
+ /** The total number of active instances. */
+ protected int _totalActive = 0;
+
+ /** The total number of idle instances. */
+ protected int _totalIdle = 0;
+
+
+ /** My {@link KeyedPoolableObjectFactory}. */
+ protected KeyedPoolableObjectFactory _factory = null;
+
+ /**
+ * My idle object eviction thread, if any.
+ */
+ protected Evictor _evictor = null;
+
+}
diff --git a/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPoolFactory.java b/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPoolFactory.java
new file mode 100644
index 0000000..8742bca
--- /dev/null
+++ b/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPoolFactory.java
@@ -0,0 +1,136 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPoolFactory.java,v 1.1 2001/04/14 16:41:24 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:41:24 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import org.apache.commons.pool.*;
+
+/**
+ * A factory for creating {@link GenericKeyedObjectPool} instances.
+ *
+ * @see GenericKeyedObjectPool
+ * @see KeyedObjectPoolFactory
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: GenericKeyedObjectPoolFactory.java,v 1.1 2001/04/14 16:41:24 rwaldhoff Exp $
+ */
+public class GenericKeyedObjectPoolFactory implements KeyedObjectPoolFactory {
+ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory) {
+ this(factory,GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE,GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,GenericKeyedObjectPool.DEFAULT_MAX_WAIT,GenericKeyedObjectPool.DEFAULT_MAX_IDLE,GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, GenericKeyedObjectPool.Config config) {
+ this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle);
+ }
+
+ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive) {
+ this(factory,maxActive,GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,GenericKeyedObjectPool.DEFAULT_MAX_WAIT,GenericKeyedObjectPool.DEFAULT_MAX_IDLE,GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,GenericKeyedObjectPool.DEFAULT_MAX_IDLE,GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,GenericKeyedObjectPool.DEFAULT_MAX_IDLE,testOnBorrow,testOnReturn,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW,GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,testOnBorrow,testOnReturn,GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
+ _maxIdle = maxIdle;
+ _maxActive = maxActive;
+ _maxWait = maxWait;
+ _whenExhaustedAction = whenExhaustedAction;
+ _testOnBorrow = testOnBorrow;
+ _testOnReturn = testOnReturn;
+ _testWhileIdle = testWhileIdle;
+ _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ _numTestsPerEvictionRun = numTestsPerEvictionRun;
+ _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+ _factory = factory;
+ }
+
+ public KeyedObjectPool createPool() {
+ return new GenericKeyedObjectPool(_factory,_maxActive,_whenExhaustedAction,_maxWait,_maxIdle,_testOnBorrow,_testOnReturn,_timeBetweenEvictionRunsMillis,_numTestsPerEvictionRun,_minEvictableIdleTimeMillis,_testWhileIdle);
+ }
+
+ //--- protected attributes ---------------------------------------
+
+ protected int _maxIdle = GenericKeyedObjectPool.DEFAULT_MAX_IDLE;
+ protected int _maxActive = GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE;
+ protected long _maxWait = GenericKeyedObjectPool.DEFAULT_MAX_WAIT;
+ protected byte _whenExhaustedAction = GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
+ protected boolean _testOnBorrow = GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW;
+ protected boolean _testOnReturn = GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN;
+ protected boolean _testWhileIdle = GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE;
+ protected long _timeBetweenEvictionRunsMillis = GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
+ protected int _numTestsPerEvictionRun = GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
+ protected long _minEvictableIdleTimeMillis = GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
+ protected KeyedPoolableObjectFactory _factory = null;
+
+}
diff --git a/src/java/org/apache/commons/pool/impl/GenericObjectPool.java b/src/java/org/apache/commons/pool/impl/GenericObjectPool.java
new file mode 100644
index 0000000..fa671bb
--- /dev/null
+++ b/src/java/org/apache/commons/pool/impl/GenericObjectPool.java
@@ -0,0 +1,1126 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/impl/GenericObjectPool.java,v 1.1 2001/04/14 16:41:43 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:41:43 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import org.apache.commons.pool.*;
+import org.apache.commons.collections.CursorableLinkedList;
+import org.apache.commons.collections.CursorableLinkedList.Cursor;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Enumeration;
+import java.util.EmptyStackException;
+import java.util.ListIterator;
+
+/**
+ * A configurable {@link ObjectPool} implementation.
+ * <p>
+ * When coupled with the appropriate {@link PoolableObjectFactory},
+ * <tt>GenericObjectPool</tt> provides robust pooling functionality for
+ * arbitrary objects.
+ * <p>
+ * A <tt>GenericObjectPool</tt> provides a number of configurable parameters:
+ * <ul>
+ * <li>
+ * {@link #setMaxActive <i>maxActive</i>} controls the maximum number of objects that can
+ * be borrowed from the pool at one time. When non-positive, there
+ * is no limit to the number of objects that may be active at one time.
+ * When {@link #setMaxActive <i>maxActive</i>} is exceeded, the pool is said to be exhausted.
+ * </li>
+ * <li>
+ * {@link #setMaxIdle <i>maxIdle</i>} controls the maximum number of objects that can
+ * sit idle in the pool at any time. When non-positive, there
+ * is no limit to the number of objects that may be idle at one time.
+ * </li>
+ * <li>
+ * {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} specifies the
+ * behaviour of the {@link #borrowObject} method when the pool is exhausted:
+ * <ul>
+ * <li>
+ * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
+ * {@link #WHEN_EXHAUSTED_FAIL}, {@link #borrowObject} will throw
+ * a {@link NoSuchElementException}
+ * </li>
+ * <li>
+ * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
+ * {@link #WHEN_EXHAUSTED_GROW}, {@link #borrowObject} will create a new
+ * object and return it(essentially making {@link #setMaxActive <i>maxActive</i>}
+ * meaningless.)
+ * </li>
+ * <li>
+ * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>}
+ * is {@link #WHEN_EXHAUSTED_BLOCK}, {@link #borrowObject} will block
+ * (invoke {@link Object#wait} until a new or idle object is available.
+ * If a positive {@link #setMaxWait <i>maxWait</i>}
+ * value is supplied, the {@link #borrowObject} will block for at
+ * most that many milliseconds, after which a {@link NoSuchElementException}
+ * will be thrown. If {@link #setMaxWait <i>maxWait</i>} is non-positive,
+ * the {@link #borrowObject} method will block indefinitely.
+ * </li>
+ * </ul>
+ * </li>
+ * <li>
+ * When {@link #setTestOnBorrow <i>testOnBorrow</i>} is set, the pool will
+ * attempt to validate each object before it is returned from the
+ * {@link #borrowObject} method. (Using the provided factory's
+ * {@link PoolableObjectFactory#validateObject} method.) Objects that fail
+ * to validate will be dropped from the pool, and a different object will
+ * be borrowed.
+ * </li>
+ * <li>
+ * When {@link #setTestOnReturn <i>testOnReturn</i>} is set, the pool will
+ * attempt to validate each object before it is returned to the pool in the
+ * {@link #returnObject} method. (Using the provided factory's
+ * {@link PoolableObjectFactory#validateObject}
+ * method.) Objects that fail to validate will be dropped from the pool.
+ * </li>
+ * </ul>
+ * <p>
+ * Optionally, one may configure the pool to examine and possibly evict objects as they
+ * sit idle in the pool. This is performed by an "idle object eviction" thread, which
+ * runs asychronously. The idle object eviction thread may be configured using the
+ * following attributes:
+ * <ul>
+ * <li>
+ * {@link #setTimeBetweenEvictionRunsMillis <i>timeBetweenEvictionRunsMillis</i>}
+ * indicates how long the eviction thread should sleep before "runs" of examining
+ * idle objects. When non-positive, no eviction thread will be launched.
+ * </li>
+ * <li>
+ * {@link #setMinEvictableIdleTimeMillis <i>minEvictableIdleTimeMillis</i>}
+ * specifies the minimum amount of time that an object may sit idle in the pool
+ * before it is eligable for eviction due to idle time. When non-positive, no object
+ * will be dropped from the pool due to idle time alone.
+ * </li>
+ * <li>
+ * {@link #setTestWhileIdle <i>testWhileIdle</i>} indicates whether or not idle
+ * objects should be validated using the factory's
+ * {@link PoolableObjectFactory#validateObject} method. Objects
+ * that fail to validate will be dropped from the pool.
+ * </li>
+ * </ul>
+ * @see GenericKeyedObjectPool
+ * @author Rodney Waldhoff
+ * @version $Id: GenericObjectPool.java,v 1.1 2001/04/14 16:41:43 rwaldhoff Exp $
+ */
+public class GenericObjectPool implements ObjectPool {
+
+ //--- public constants -------------------------------------------
+
+ /**
+ * A "when exhausted action" type indicating that when the pool is
+ * exhausted (i.e., the maximum number of active objects has
+ * been reached), the {@link #borrowObject}
+ * method should fail, throwing a {@link NoSuchElementException}.
+ * @see #WHEN_EXHAUSTED_BLOCK
+ * @see #WHEN_EXHAUSTED_GROW
+ * @see #setWhenExhaustedAction
+ */
+ public static final byte WHEN_EXHAUSTED_FAIL = 0;
+
+ /**
+ * A "when exhausted action" type indicating that when the pool
+ * is exhausted (i.e., the maximum number
+ * of active objects has been reached), the {@link #borrowObject}
+ * method should block until a new object is available, or the
+ * {@link #getMaxWait maximum wait time} has been reached.
+ * @see #WHEN_EXHAUSTED_FAIL
+ * @see #WHEN_EXHAUSTED_GROW
+ * @see #setMaxWait
+ * @see #getMaxWait
+ * @see #setWhenExhaustedAction
+ */
+ public static final byte WHEN_EXHAUSTED_BLOCK = 1;
+
+ /**
+ * A "when exhausted action" type indicating that when the pool is
+ * exhausted (i.e., the maximum number
+ * of active objects has been reached), the {@link #borrowObject}
+ * method should simply create a new object anyway.
+ * @see #WHEN_EXHAUSTED_FAIL
+ * @see #WHEN_EXHAUSTED_GROW
+ * @see #setWhenExhaustedAction
+ */
+ public static final byte WHEN_EXHAUSTED_GROW = 2;
+
+ /**
+ * The default cap on the number of "sleeping" instances in the pool.
+ * @see #getMaxIdle
+ * @see #setMaxIdle
+ */
+ public static final int DEFAULT_MAX_IDLE = 8;
+
+ /**
+ * The default cap on the total number of active instances from the pool.
+ * @see #getMaxActive
+ */
+ public static final int DEFAULT_MAX_ACTIVE = 8;
+
+ /**
+ * The default "when exhausted action" for the pool.
+ * @see #WHEN_EXHAUSTED_BLOCK
+ * @see #WHEN_EXHAUSTED_FAIL
+ * @see #WHEN_EXHAUSTED_GROW
+ * @see #setWhenExhaustedAction
+ */
+ public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK;
+
+ /**
+ * The default maximum amount of time (in millis) the
+ * {@link #borrowObject} method should block before throwing
+ * an exception when the pool is exhausted and the
+ * {@link #getWhenExhaustedAction "when exhausted" action} is
+ * {@link #WHEN_EXHAUSTED_BLOCK}.
+ * @see #getMaxWait
+ * @see #setMaxWait
+ */
+ public static final long DEFAULT_MAX_WAIT = -1L;
+
+ /**
+ * The default "test on borrow" value.
+ * @see #getTestOnBorrow
+ * @see #setTestOnBorrow
+ */
+ public static final boolean DEFAULT_TEST_ON_BORROW = false;
+
+ /**
+ * The default "test on return" value.
+ * @see #getTestOnReturn
+ * @see #setTestOnReturn
+ */
+ public static final boolean DEFAULT_TEST_ON_RETURN = false;
+
+ /**
+ * The default "test while idle" value.
+ * @see #getTestWhileIdle
+ * @see #setTestWhileIdle
+ * @see #getTimeBetweenEvictionRunsMillis
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ public static final boolean DEFAULT_TEST_WHILE_IDLE = false;
+
+ /**
+ * The default "time between eviction runs" value.
+ * @see #getTimeBetweenEvictionRunsMillis
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;
+
+ /**
+ * The default number of objects to examine per run in the
+ * idle object evictor.
+ * @see #getNumTestsPerEvictionRun
+ * @see #setNumTestsPerEvictionRun
+ * @see #getTimeBetweenEvictionRunsMillis
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;
+
+ /**
+ * The default value for {@link #getMinEvictableIdleTimeMillis}.
+ * @see #getMinEvictableIdleTimeMillis
+ * @see #setMinEvictableIdleTimeMillis
+ */
+ public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;
+
+ //--- constructors -----------------------------------------------
+
+ /**
+ * Create a new <tt>GenericObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
+ */
+ public GenericObjectPool(PoolableObjectFactory factory) {
+ this(factory,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ /**
+ * Create a new <tt>GenericObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
+ * @param config a non-<tt>null</tt> {@link GenericObjectPool.Config} describing my configuration
+ */
+ public GenericObjectPool(PoolableObjectFactory factory, GenericObjectPool.Config config) {
+ this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle);
+ }
+
+ /**
+ * Create a new <tt>GenericObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
+ * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
+ */
+ public GenericObjectPool(PoolableObjectFactory factory, int maxActive) {
+ this(factory,maxActive,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ /**
+ * Create a new <tt>GenericObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
+ * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
+ * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})
+ * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})
+ */
+ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ /**
+ * Create a new <tt>GenericObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
+ * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
+ * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})
+ * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})
+ * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #getTestOnBorrow})
+ * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #getTestOnReturn})
+ */
+ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,testOnBorrow,testOnReturn,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ /**
+ * Create a new <tt>GenericObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
+ * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
+ * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})
+ * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})
+ * @param maxIdle the maximum number of idle objects in my pool (see {@link #getMaxIdle})
+ */
+ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ /**
+ * Create a new <tt>GenericObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
+ * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
+ * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})
+ * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})
+ * @param maxIdle the maximum number of idle objects in my pool (see {@link #getMaxIdle})
+ * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #getTestOnBorrow})
+ * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #getTestOnReturn})
+ */
+ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,testOnBorrow,testOnReturn,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ /**
+ * Create a new <tt>GenericObjectPool</tt> using the specified values.
+ * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
+ * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
+ * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
+ * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
+ * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
+ * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
+ * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
+ * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
+ * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
+ * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
+ * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
+ */
+ public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
+ _factory = factory;
+ _maxActive = maxActive;
+ switch(whenExhaustedAction) {
+ case WHEN_EXHAUSTED_BLOCK:
+ case WHEN_EXHAUSTED_FAIL:
+ case WHEN_EXHAUSTED_GROW:
+ _whenExhaustedAction = whenExhaustedAction;
+ break;
+ default:
+ throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
+ }
+ _maxWait = maxWait;
+ _maxIdle = maxIdle;
+ _testOnBorrow = testOnBorrow;
+ _testOnReturn = testOnReturn;
+ _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ _numTestsPerEvictionRun = numTestsPerEvictionRun;
+ _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+ _testWhileIdle = testWhileIdle;
+
+ _pool = new CursorableLinkedList();
+ if(_timeBetweenEvictionRunsMillis > 0) {
+ _evictor = new Evictor();
+ Thread t = new Thread(_evictor);
+ t.setDaemon(true);
+ t.start();
+ }
+ }
+
+ //--- public methods ---------------------------------------------
+
+ //--- configuration methods --------------------------------------
+
+ /**
+ * Returns the cap on the total number of active instances from my pool.
+ * @return the cap on the total number of active instances from my pool.
+ * @see #setMaxActive
+ */
+ public int getMaxActive() {
+ return _maxActive;
+ }
+
+ /**
+ * Sets the cap on the total number of active instances from my pool.
+ * @param maxActive The cap on the total number of active instances from my pool.
+ * Use a negative value for an infinite number of instances.
+ * @see #getMaxActive
+ */
+ public void setMaxActive(int maxActive) {
+ _maxActive = maxActive;
+ synchronized(this) {
+ notifyAll();
+ }
+ }
+
+ /**
+ * Returns the action to take when the {@link #borrowObject} method
+ * is invoked when the pool is exhausted (the maximum number
+ * of "active" objects has been reached).
+ *
+ * @return one of {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL} or {@link #WHEN_EXHAUSTED_GROW}
+ * @see #setWhenExhaustedAction
+ */
+ public byte getWhenExhaustedAction() {
+ return _whenExhaustedAction;
+ }
+
+ /**
+ * Sets the action to take when the {@link #borrowObject} method
+ * is invoked when the pool is exhausted (the maximum number
+ * of "active" objects has been reached).
+ *
+ * @param whenExhaustedAction the action code, which must be one of
+ * {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL},
+ * or {@link #WHEN_EXHAUSTED_GROW}
+ * @see #getWhenExhaustedAction
+ */
+ public synchronized void setWhenExhaustedAction(byte whenExhaustedAction) {
+ switch(whenExhaustedAction) {
+ case WHEN_EXHAUSTED_BLOCK:
+ case WHEN_EXHAUSTED_FAIL:
+ case WHEN_EXHAUSTED_GROW:
+ _whenExhaustedAction = whenExhaustedAction;
+ notifyAll();
+ break;
+ default:
+ throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
+ }
+ }
+
+
+ /**
+ * Returns the maximum amount of time (in milliseconds) the
+ * {@link #borrowObject} method should block before throwing
+ * an exception when the pool is exhausted and the
+ * {@link #setWhenExhaustedAction "when exhausted" action} is
+ * {@link #WHEN_EXHAUSTED_BLOCK}.
+ *
+ * When less than 0, the {@link #borrowObject} method
+ * may block indefinitely.
+ *
+ * @see #setMaxWait
+ * @see #setWhenExhaustedAction
+ * @see #WHEN_EXHAUSTED_BLOCK
+ */
+ public synchronized long getMaxWait() {
+ return _maxWait;
+ }
+
+ /**
+ * Sets the maximum amount of time (in milliseconds) the
+ * {@link #borrowObject} method should block before throwing
+ * an exception when the pool is exhausted and the
+ * {@link #setWhenExhaustedAction "when exhausted" action} is
+ * {@link #WHEN_EXHAUSTED_BLOCK}.
+ *
+ * When less than 0, the {@link #borrowObject} method
+ * may block indefinitely.
+ *
+ * @see #getMaxWait
+ * @see #setWhenExhaustedAction
+ * @see #WHEN_EXHAUSTED_BLOCK
+ */
+ public synchronized void setMaxWait(long maxWait) {
+ _maxWait = maxWait;
+ }
+
+ /**
+ * Returns the cap on the number of "idle" instances in the pool.
+ * @return the cap on the number of "idle" instances in the pool.
+ * @see #setMaxIdle
+ */
+ public int getMaxIdle() {
+ return _maxIdle;
+ }
+
+ /**
+ * Sets the cap on the number of "idle" instances in the pool.
+ * @param maxIdle The cap on the number of "idle" instances in the pool.
+ * Use a negative value to indicate an unlimited number
+ * of idle instances.
+ * @see #getMaxIdle
+ */
+ public void setMaxIdle(int maxIdle) {
+ _maxIdle = maxIdle;
+ synchronized(this) {
+ notifyAll();
+ }
+ }
+
+ /**
+ * 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) {
+ _testOnBorrow = testOnBorrow;
+ }
+
+ /**
+ * 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) {
+ _testOnReturn = testOnReturn;
+ }
+
+ /**
+ * 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) {
+ if(_timeBetweenEvictionRunsMillis > 0 && timeBetweenEvictionRunsMillis <= 0) {
+ _evictor.cancel();
+ _evictor = null;
+ _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ } else if(_timeBetweenEvictionRunsMillis <= 0 && timeBetweenEvictionRunsMillis > 0) {
+ _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ _evictor = new Evictor();
+ Thread t = new Thread(_evictor);
+ t.setDaemon(true);
+ t.start();
+ } else {
+ _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ }
+ }
+
+ /**
+ * 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) {
+ _numTestsPerEvictionRun = numTestsPerEvictionRun;
+ }
+
+ /**
+ * 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 long 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(long minEvictableIdleTimeMillis) {
+ _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+ }
+
+ /**
+ * 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) {
+ _testWhileIdle = testWhileIdle;
+ }
+
+ /**
+ * Sets my configuration.
+ * @see GenericObjectPool.Config
+ */
+ public synchronized void setConfig(GenericObjectPool.Config conf) {
+ setMaxIdle(conf.maxIdle);
+ setMaxActive(conf.maxActive);
+ setMaxWait(conf.maxWait);
+ setWhenExhaustedAction(conf.whenExhaustedAction);
+ setTestOnBorrow(conf.testOnBorrow);
+ setTestOnReturn(conf.testOnReturn);
+ setTestWhileIdle(conf.testWhileIdle);
+ setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);
+ setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);
+ setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);
+ notifyAll();
+ }
+
+ //-- ObjectPool methods ------------------------------------------
+
+ public synchronized Object borrowObject() {
+ long starttime = System.currentTimeMillis();
+ for(;;) {
+ ObjectTimestampPair pair = null;
+ // if there are any sleeping, just grab one of those
+ try {
+ pair = (ObjectTimestampPair)(_pool.removeFirst());
+ } catch(NoSuchElementException e) { /* ignored */
+ }
+ // otherwise
+ if(null == pair) {
+ // check if we can create one
+ // (note we know that the num sleeping is 0, else we wouldn't be here)
+ if(_maxActive > 0 && _numActive < _maxActive) {
+ Object obj = _factory.makeObject();
+ pair = new ObjectTimestampPair(obj);
+ } else {
+ // the pool is exhausted
+ switch(_whenExhaustedAction) {
+ case WHEN_EXHAUSTED_GROW:
+ Object obj = _factory.makeObject();
+ pair = new ObjectTimestampPair(obj);
+ break;
+ case WHEN_EXHAUSTED_FAIL:
+ throw new NoSuchElementException();
+ case WHEN_EXHAUSTED_BLOCK:
+ try {
+ if(_maxWait <= 0) {
+ wait();
+ } else {
+ wait(_maxWait);
+ }
+ } catch(InterruptedException e) {
+ // ignored
+ }
+ if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
+ throw new NoSuchElementException("Timeout waiting for idle object");
+ } else {
+ continue; // keep looping
+ }
+ default:
+ throw new IllegalArgumentException("whenExhaustedAction " + _whenExhaustedAction + " not recognized.");
+ }
+ }
+ }
+ _factory.activateObject(pair.value);
+ if(_testOnBorrow && !_factory.validateObject(pair.value)) {
+ try {
+ _factory.passivateObject(pair.value);
+ } catch(Exception e) {
+ ; // ignored, we're throwing it out anyway
+ }
+ _factory.destroyObject(pair.value);
+ } else {
+ _numActive++;
+ return pair.value;
+ }
+ }
+ }
+
+ public synchronized void clear() throws UnsupportedOperationException {
+ Iterator it = _pool.iterator();
+ while(it.hasNext()) {
+ _factory.destroyObject(((ObjectTimestampPair)(it.next())).value);
+ it.remove();
+ }
+ _pool.clear();
+ notifyAll(); // num sleeping has changed
+ }
+
+ public int numActive() {
+ return _numActive;
+ }
+
+ public int numIdle() {
+ return _pool.size();
+ }
+
+ public synchronized void returnObject(Object obj) {
+ _numActive--;
+ if(_maxIdle > 0 && (_pool.size() >= _maxIdle || (_testOnReturn && !_factory.validateObject(obj)))) {
+ try {
+ _factory.passivateObject(obj);
+ } catch(Exception e) {
+ ; // ignored, we're throwing it out anway
+ }
+ _factory.destroyObject(obj);
+ } else {
+ try {
+ _factory.passivateObject(obj);
+ _pool.addFirst(new ObjectTimestampPair(obj));
+ } catch(Exception e) {
+ _factory.destroyObject(obj);
+ }
+ }
+ notifyAll(); // _numActive has changed
+ }
+
+ synchronized public void close() {
+ clear();
+ _pool = null;
+ _factory = null;
+ if(null != _evictor) {
+ _evictor.cancel();
+ _evictor = null;
+ }
+ }
+
+ synchronized public void setFactory(PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
+ if(0 < numActive()) {
+ throw new IllegalStateException("Objects are already active");
+ } else {
+ clear();
+ _factory = factory;
+ }
+ }
+
+ //--- package methods --------------------------------------------
+
+ synchronized String debugInfo() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("Active: ").append(numActive()).append("\n");
+ buf.append("Idle: ").append(numIdle()).append("\n");
+ buf.append("Idle Objects:\n");
+ Iterator it = _pool.iterator();
+ long time = System.currentTimeMillis();
+ while(it.hasNext()) {
+ ObjectTimestampPair pair = (ObjectTimestampPair)(it.next());
+ buf.append("\t").append(pair.value).append("\t").append(time - pair.tstamp).append("\n");
+ }
+ return buf.toString();
+ }
+
+ //--- inner classes ----------------------------------------------
+
+ /**
+ * A simple "struct" encapsulating an object instance and a timestamp.
+ */
+ class ObjectTimestampPair {
+ Object value;
+ long tstamp;
+
+ ObjectTimestampPair(Object val) {
+ value = val;
+ tstamp = System.currentTimeMillis();
+ }
+
+ ObjectTimestampPair(Object val, long time) {
+ value = val;
+ tstamp = time;
+ }
+ }
+
+ /**
+ * The idle object evictor thread.
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ class Evictor implements Runnable {
+ protected boolean _cancelled = false;
+
+ void cancel() {
+ _cancelled = true;
+ }
+
+ public void run() {
+ CursorableLinkedList.Cursor cursor = null;
+ while(!_cancelled) {
+ long sleeptime = 0L;
+ synchronized(GenericObjectPool.this) {
+ sleeptime = _timeBetweenEvictionRunsMillis;
+ }
+ try {
+ Thread.currentThread().sleep(_timeBetweenEvictionRunsMillis);
+ } catch(Exception e) {
+ ; // ignored
+ }
+ try {
+ synchronized(GenericObjectPool.this) {
+ if(!_pool.isEmpty()) {
+ if(null == cursor) {
+ cursor = (CursorableLinkedList.Cursor)(_pool.cursor(_pool.size()));
+ } else if(!cursor.hasPrevious()) {
+ cursor.close();
+ cursor = (CursorableLinkedList.Cursor)(_pool.cursor(_pool.size()));
+ }
+ for(int i=0,m=getNumTests();i<m;i++) {
+ if(!cursor.hasPrevious()) {
+ cursor.close();
+ cursor = (CursorableLinkedList.Cursor)(_pool.cursor(_pool.size()));
+ } else {
+ ObjectTimestampPair pair = (ObjectTimestampPair)(cursor.previous());
+ if(System.currentTimeMillis() - pair.tstamp > _minEvictableIdleTimeMillis) {
+ try {
+ cursor.remove();
+ _factory.destroyObject(pair.value);
+ } catch(Exception e) {
+ ; // ignored
+ }
+ } else if(_testWhileIdle) {
+ boolean active = false;
+ try {
+ _factory.activateObject(pair.value);
+ active = true;
+ } catch(Exception e) {
+ cursor.remove();
+ try {
+ _factory.passivateObject(pair.value);
+ } catch(Exception ex) {
+ ; // ignored
+ }
+ _factory.destroyObject(pair.value);
+ }
+ if(active) {
+ if(!_factory.validateObject(pair.value)) {
+ cursor.remove();
+ try {
+ _factory.passivateObject(pair.value);
+ } catch(Exception ex) {
+ ; // ignored
+ }
+ _factory.destroyObject(pair.value);
+ } else {
+ try {
+ _factory.passivateObject(pair.value);
+ } catch(Exception e) {
+ cursor.remove();
+ _factory.destroyObject(pair.value);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } catch(Exception e) {
+ // ignored
+ }
+ }
+ if(null != cursor) {
+ cursor.close();
+ }
+ }
+
+ private int getNumTests() {
+ if(_numTestsPerEvictionRun >= 0) {
+ return _numTestsPerEvictionRun;
+ } else {
+ return(int)(Math.ceil((double)_pool.size()/Math.abs((double)_numTestsPerEvictionRun)));
+ }
+ }
+ }
+
+ /**
+ * A simple "struct" encapsulating the
+ * configuration information for a {@link GenericObjectPool}.
+ * @see GenericObjectPool#GenericObjectPool(org.apache.commons.pool.PoolableObjectFactory,org.apache.commons.pool.impl.GenericObjectPool.Config)
+ * @see GenericObjectPool#setConfig
+ */
+ public static class Config {
+ public int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
+ public int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
+ public long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;
+ public byte whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
+ public boolean testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW;
+ public boolean testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN;
+ public boolean testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE;
+ public long timeBetweenEvictionRunsMillis = GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
+ public int numTestsPerEvictionRun = GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
+ public long minEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
+ }
+
+ //--- protected attributes ---------------------------------------
+
+ /**
+ * The cap on the number of idle instances in the pool.
+ * @see #setMaxIdle
+ * @see #getMaxIdle
+ */
+ protected int _maxIdle = DEFAULT_MAX_IDLE;
+
+ /**
+ * The cap on the total number of active instances from the pool.
+ * @see #setMaxActive
+ * @see #getMaxActive
+ */
+ protected int _maxActive = DEFAULT_MAX_ACTIVE;
+
+ /**
+ * The maximum amount of time (in millis) the
+ * {@link #borrowObject} method should block before throwing
+ * an exception when the pool is exhausted and the
+ * {@link #getWhenExhaustedAction "when exhausted" action} is
+ * {@link #WHEN_EXHAUSTED_BLOCK}.
+ *
+ * When less than 0, the {@link #borrowObject} method
+ * may block indefinitely.
+ *
+ * @see #setMaxWait
+ * @see #getMaxWait
+ * @see #WHEN_EXHAUSTED_BLOCK
+ * @see #setWhenExhaustedAction
+ * @see #getWhenExhaustedAction
+ */
+ protected long _maxWait = DEFAULT_MAX_WAIT;
+
+ /**
+ * The action to take when the {@link #borrowObject} method
+ * is invoked when the pool is exhausted (the maximum number
+ * of "active" objects has been reached).
+ *
+ * @see #WHEN_EXHAUSTED_BLOCK
+ * @see #WHEN_EXHAUSTED_FAIL
+ * @see #WHEN_EXHAUSTED_GROW
+ * @see #DEFAULT_WHEN_EXHAUSTED_ACTION
+ * @see #setWhenExhaustedAction
+ * @see #getWhenExhaustedAction
+ */
+ protected byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION;
+
+ /**
+ * 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
+ * @see #getTestOnBorrow
+ */
+ protected boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW;
+
+ /**
+ * When <tt>true</tt>, objects will be
+ * {@link PoolableObjectFactory#validateObject validated}
+ * before being returned to the pool within the
+ * {@link #returnObject}.
+ *
+ * @see #getTestOnReturn
+ * @see #setTestOnReturn
+ */
+ protected boolean _testOnReturn = DEFAULT_TEST_ON_RETURN;
+
+ /**
+ * 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 #getTestWhileIdle
+ * @see #getTimeBetweenEvictionRunsMillis
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ protected boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE;
+
+ /**
+ * 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
+ * @see #getTimeBetweenEvictionRunsMillis
+ */
+ protected long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
+
+ /**
+ * 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 #setNumTestsPerEvictionRun
+ * @see #getNumTestsPerEvictionRun
+ * @see #getTimeBetweenEvictionRunsMillis
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ protected int _numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
+
+ /**
+ * 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 #setMinEvictableIdleTimeMillis
+ * @see #getMinEvictableIdleTimeMillis
+ * @see #getTimeBetweenEvictionRunsMillis
+ * @see #setTimeBetweenEvictionRunsMillis
+ */
+ protected long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
+
+ /** My pool. */
+ protected CursorableLinkedList _pool = null;
+
+ /** My {@link PoolableObjectFactory}. */
+ protected PoolableObjectFactory _factory = null;
+
+ /**
+ * The number of objects {@link #borrowObject} borrowed
+ * from the pool, but not yet returned.
+ */
+ protected int _numActive = 0;
+
+ /**
+ * My idle object eviction thread, if any.
+ */
+ protected Evictor _evictor = null;
+}
diff --git a/src/java/org/apache/commons/pool/impl/GenericObjectPoolFactory.java b/src/java/org/apache/commons/pool/impl/GenericObjectPoolFactory.java
new file mode 100644
index 0000000..496b8e7
--- /dev/null
+++ b/src/java/org/apache/commons/pool/impl/GenericObjectPoolFactory.java
@@ -0,0 +1,135 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/impl/GenericObjectPoolFactory.java,v 1.1 2001/04/14 16:41:46 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:41:46 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import org.apache.commons.pool.*;
+
+/**
+ * A factory for creating {@link GenericObjectPool} instances.
+ *
+ * @see GenericObjectPool
+ * @see ObjectPoolFactory
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: GenericObjectPoolFactory.java,v 1.1 2001/04/14 16:41:46 rwaldhoff Exp $
+ */
+public class GenericObjectPoolFactory implements ObjectPoolFactory {
+ public GenericObjectPoolFactory(PoolableObjectFactory factory) {
+ this(factory,GenericObjectPool.DEFAULT_MAX_ACTIVE,GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,GenericObjectPool.DEFAULT_MAX_WAIT,GenericObjectPool.DEFAULT_MAX_IDLE,GenericObjectPool.DEFAULT_TEST_ON_BORROW,GenericObjectPool.DEFAULT_TEST_ON_RETURN,GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericObjectPool.DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ public GenericObjectPoolFactory(PoolableObjectFactory factory, GenericObjectPool.Config config) {
+ this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle);
+ }
+
+ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive) {
+ this(factory,maxActive,GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,GenericObjectPool.DEFAULT_MAX_WAIT,GenericObjectPool.DEFAULT_MAX_IDLE,GenericObjectPool.DEFAULT_TEST_ON_BORROW,GenericObjectPool.DEFAULT_TEST_ON_RETURN,GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericObjectPool.DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,GenericObjectPool.DEFAULT_MAX_IDLE,GenericObjectPool.DEFAULT_TEST_ON_BORROW,GenericObjectPool.DEFAULT_TEST_ON_RETURN,GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericObjectPool.DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,GenericObjectPool.DEFAULT_MAX_IDLE,testOnBorrow,testOnReturn,GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericObjectPool.DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,GenericObjectPool.DEFAULT_TEST_ON_BORROW,GenericObjectPool.DEFAULT_TEST_ON_RETURN,GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericObjectPool.DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
+ this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,testOnBorrow,testOnReturn,GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,GenericObjectPool.DEFAULT_TEST_WHILE_IDLE);
+ }
+
+ public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
+ _maxIdle = maxIdle;
+ _maxActive = maxActive;
+ _maxWait = maxWait;
+ _whenExhaustedAction = whenExhaustedAction;
+ _testOnBorrow = testOnBorrow;
+ _testOnReturn = testOnReturn;
+ _testWhileIdle = testWhileIdle;
+ _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ _numTestsPerEvictionRun = numTestsPerEvictionRun;
+ _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+ _factory = factory;
+ }
+
+ public ObjectPool createPool() {
+ return new GenericObjectPool(_factory,_maxActive,_whenExhaustedAction,_maxWait,_maxIdle,_testOnBorrow,_testOnReturn,_timeBetweenEvictionRunsMillis,_numTestsPerEvictionRun,_minEvictableIdleTimeMillis,_testWhileIdle);
+ }
+
+ protected int _maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
+ protected int _maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
+ protected long _maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;
+ protected byte _whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
+ protected boolean _testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW;
+ protected boolean _testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN;
+ protected boolean _testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE;
+ protected long _timeBetweenEvictionRunsMillis = GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
+ protected int _numTestsPerEvictionRun = GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
+ protected long _minEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
+ protected PoolableObjectFactory _factory = null;
+
+
+}
diff --git a/src/java/org/apache/commons/pool/impl/StackKeyedObjectPool.java b/src/java/org/apache/commons/pool/impl/StackKeyedObjectPool.java
new file mode 100644
index 0000000..57ac45e
--- /dev/null
+++ b/src/java/org/apache/commons/pool/impl/StackKeyedObjectPool.java
@@ -0,0 +1,331 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/impl/StackKeyedObjectPool.java,v 1.1 2001/04/14 16:41:50 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:41:50 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import org.apache.commons.pool.*;
+import java.util.HashMap;
+import java.util.Stack;
+import java.util.NoSuchElementException;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+/**
+ * A simple, {@link java.util.Stack Stack}-based {@link KeyedObjectPool} implementation.
+ * <p>
+ * Given a {@link KeyedPoolableObjectFactory}, this class will maintain
+ * a simple pool of instances. A finite number of "sleeping"
+ * or inactive instances is enforced, but when the pool is
+ * empty, new instances are created to support the new load.
+ * Hence this class places no limit on the number of "active"
+ * instances created by the pool, but is quite useful for
+ * re-using <tt>Object</tt>s without introducing
+ * artificial limits.
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: StackKeyedObjectPool.java,v 1.1 2001/04/14 16:41:50 rwaldhoff Exp $
+ */
+public class StackKeyedObjectPool implements KeyedObjectPool {
+ /**
+ * Create a new pool using
+ * no factory. Clients must first populate the pool
+ * using {@link #returnObject(java.lang.Object,java.lang.Object)}
+ * before they can be {@link #borrowObject(java.lang.Object) borrowed}.
+ */
+ public StackKeyedObjectPool() {
+ this((KeyedPoolableObjectFactory)null,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ /**
+ * Create a new pool using
+ * no factory. Clients must first populate the pool
+ * using {@link #returnObject(java.lang.Object,java.lang.Object)}
+ * before they can be {@link #borrowObject(java.lang.Object) borrowed}.
+ */
+ public StackKeyedObjectPool(int max) {
+ this((KeyedPoolableObjectFactory)null,max,DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ /**
+ * Create a new pool using
+ * no factory. Clients must first populate the pool
+ * using {@link #returnObject(java.lang.Object,java.lang.Object)}
+ * before they can be {@link #borrowObject(java.lang.Object) borrowed}.
+ */
+ public StackKeyedObjectPool(int max, int init) {
+ this((KeyedPoolableObjectFactory)null,max,init);
+ }
+
+ /**
+ * Create a new <tt>SimpleKeyedObjectPool</tt> using
+ * the specified <i>factory</i> to create new instances.
+ *
+ * @param factory the {@link KeyedPoolableObjectFactory} used to populate the pool
+ */
+ public StackKeyedObjectPool(KeyedPoolableObjectFactory factory) {
+ this(factory,DEFAULT_MAX_SLEEPING);
+ }
+
+ /**
+ * Create a new <tt>SimpleKeyedObjectPool</tt> using
+ * the specified <i>factory</i> to create new instances.
+ * capping the number of "sleeping" instances to <i>max</i>
+ *
+ * @param factory the {@link KeyedPoolableObjectFactory} used to populate the pool
+ * @param max cap on the number of "sleeping" instances in the pool
+ */
+ public StackKeyedObjectPool(KeyedPoolableObjectFactory factory, int max) {
+ this(factory,max,DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ /**
+ * Create a new <tt>SimpleKeyedObjectPool</tt> using
+ * the specified <i>factory</i> to create new instances.
+ * capping the number of "sleeping" instances to <i>max</i>,
+ * and initially allocating a container capable of containing
+ * at least <i>init</i> instances.
+ *
+ * @param factory the {@link KeyedPoolableObjectFactory} used to populate the pool
+ * @param max cap on the number of "sleeping" instances in the pool
+ * @param init initial size of the pool (this specifies the size of the container,
+ * it does not cause the pool to be pre-populated.)
+ */
+ public StackKeyedObjectPool(KeyedPoolableObjectFactory factory, int max, int init) {
+ _factory = factory;
+ _maxSleeping = (max < 0 ? DEFAULT_MAX_SLEEPING : max);
+ _initSleepingCapacity = (init < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : init);
+ _pools = new HashMap();
+ _activeCount = new HashMap();
+ }
+
+ public synchronized Object borrowObject(Object key) {
+ Object obj = null;
+ Stack stack = (Stack)(_pools.get(key));
+ if(null == stack) {
+ stack = new Stack();
+ stack.ensureCapacity( _initSleepingCapacity > _maxSleeping ? _maxSleeping : _initSleepingCapacity);
+ _pools.put(key,stack);
+ _activeCount.put(key,new Integer(0));
+ }
+ try {
+ obj = stack.pop();
+ _totIdle--;
+ } catch(Exception e) {
+ if(null == _factory) {
+ throw new NoSuchElementException();
+ } else {
+ obj = _factory.makeObject(key);
+ }
+ }
+ if(null != obj && null != _factory) {
+ _factory.activateObject(key,obj);
+ }
+ _totActive++;
+ Integer old = (Integer)(_activeCount.get(key));
+ _activeCount.put(key,new Integer(old.intValue() + 1));
+ return obj;
+ }
+
+ public synchronized void returnObject(Object key, Object obj) {
+ _totActive--;
+ if(null == _factory || _factory.validateObject(key,obj)) {
+ Stack stack = (Stack)(_pools.get(key));
+ if(null == stack) {
+ stack = new Stack();
+ stack.ensureCapacity( _initSleepingCapacity > _maxSleeping ? _maxSleeping : _initSleepingCapacity);
+ _pools.put(key,stack);
+ _activeCount.put(key,new Integer(1));
+ }
+ if(null != _factory) {
+ try {
+ _factory.passivateObject(key,obj);
+ } catch(Exception e) {
+ _factory.destroyObject(key,obj);
+ return;
+ }
+ }
+ if(stack.size() < _maxSleeping) {
+ stack.push(obj);
+ _totIdle++;
+ } else {
+ if(null != _factory) {
+ _factory.destroyObject(key,obj);
+ }
+ }
+ } else {
+ if(null != _factory) {
+ _factory.destroyObject(key,obj);
+ }
+ }
+ Integer old = (Integer)(_activeCount.get(key));
+ _activeCount.put(key,new Integer(old.intValue() - 1));
+ }
+
+ public int numIdle() {
+ return _totIdle;
+ }
+
+ public int numActive() {
+ return _totActive;
+ }
+
+ public int numActive(Object key) {
+ try {
+ return ((Integer)_activeCount.get(key)).intValue();
+ } catch(NoSuchElementException e) {
+ return 0;
+ } catch(NullPointerException e) {
+ return 0;
+ }
+ }
+
+ public synchronized int numIdle(Object key) {
+ try {
+ return((Stack)(_pools.get(key))).size();
+ } catch(Exception e) {
+ return 0;
+ }
+ }
+
+ public synchronized void clear() throws UnsupportedOperationException {
+ Iterator it = _pools.keySet().iterator();
+ while(it.hasNext()) {
+ clear(it.next());
+ }
+ _totIdle = 0;
+ _pools.clear();
+ _activeCount.clear();
+ }
+
+ public synchronized void clear(Object key) throws UnsupportedOperationException {
+ Stack stack = (Stack)(_pools.remove(key));
+ if(null == stack) {
+ return;
+ } else {
+ Enumeration enum = stack.elements();
+ while(enum.hasMoreElements()) {
+ _factory.destroyObject(key,enum.nextElement());
+ }
+ _totIdle -= stack.size();
+ _activeCount.put(key,new Integer(0));
+ stack.clear();
+ }
+ }
+
+ public synchronized String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(getClass().getName());
+ buf.append(" contains ").append(_pools.size()).append(" distinct pools: ");
+ Iterator it = _pools.keySet().iterator();
+ while(it.hasNext()) {
+ Object key = it.next();
+ buf.append(" |").append(key).append("|=");
+ Stack s = (Stack)(_pools.get(key));
+ buf.append(s.size());
+ }
+ return buf.toString();
+ }
+
+ synchronized public void close() {
+ clear();
+ _pools = null;
+ _factory = null;
+ _activeCount = null;
+ }
+
+ synchronized public void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
+ if(0 < numActive()) {
+ throw new IllegalStateException("Objects are already active");
+ } else {
+ clear();
+ _factory = factory;
+ }
+ }
+
+
+ /** The default cap on the number of "sleeping" instances in the pool. */
+ protected static final int DEFAULT_MAX_SLEEPING = 8;
+
+ /**
+ * The default initial size of the pool
+ * (this specifies the size of the container, it does not
+ * cause the pool to be pre-populated.)
+ */
+ protected static final int DEFAULT_INIT_SLEEPING_CAPACITY = 4;
+
+ /** My named-set of pools. */
+ protected HashMap _pools = null;
+
+ /** My {@link KeyedPoolableObjectFactory}. */
+ protected KeyedPoolableObjectFactory _factory = null;
+
+ /** The cap on the number of "sleeping" instances in <i>each</i> pool. */
+ protected int _maxSleeping = DEFAULT_MAX_SLEEPING;
+
+ /** The initial capacity of each pool. */
+ protected int _initSleepingCapacity = DEFAULT_INIT_SLEEPING_CAPACITY;
+
+ protected int _totActive = 0;
+ protected int _totIdle = 0;
+
+ protected HashMap _activeCount = null;
+
+}
\ No newline at end of file
diff --git a/src/java/org/apache/commons/pool/impl/StackKeyedObjectPoolFactory.java b/src/java/org/apache/commons/pool/impl/StackKeyedObjectPoolFactory.java
new file mode 100644
index 0000000..75682c5
--- /dev/null
+++ b/src/java/org/apache/commons/pool/impl/StackKeyedObjectPoolFactory.java
@@ -0,0 +1,113 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/impl/StackKeyedObjectPoolFactory.java,v 1.1 2001/04/14 16:41:52 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:41:52 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import org.apache.commons.pool.*;
+import java.util.Stack;
+import java.util.NoSuchElementException;
+import java.util.Enumeration;
+
+/**
+ * A factory for creating {@link StackKeyedObjectPool} instances.
+ *
+ * @see StackKeyedObjectPool
+ * @see KeyedObjectPoolFactory
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: StackKeyedObjectPoolFactory.java,v 1.1 2001/04/14 16:41:52 rwaldhoff Exp $
+ */
+public class StackKeyedObjectPoolFactory implements KeyedObjectPoolFactory {
+ public StackKeyedObjectPoolFactory() {
+ this((KeyedPoolableObjectFactory)null,StackKeyedObjectPool.DEFAULT_MAX_SLEEPING,StackKeyedObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ public StackKeyedObjectPoolFactory(int max) {
+ this((KeyedPoolableObjectFactory)null,max,StackKeyedObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ public StackKeyedObjectPoolFactory(int max, int init) {
+ this((KeyedPoolableObjectFactory)null,max,init);
+ }
+
+ public StackKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory) {
+ this(factory,StackKeyedObjectPool.DEFAULT_MAX_SLEEPING,StackKeyedObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ public StackKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int max) {
+ this(factory,max,StackKeyedObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ public StackKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int max, int init) {
+ _factory = factory;
+ _maxSleeping = max;
+ _initCapacity = init;
+ }
+
+ public KeyedObjectPool createPool() {
+ return new StackKeyedObjectPool(_factory,_maxSleeping,_initCapacity);
+ }
+
+ protected KeyedPoolableObjectFactory _factory = null;
+ protected int _maxSleeping = StackKeyedObjectPool.DEFAULT_MAX_SLEEPING;
+ protected int _initCapacity = StackKeyedObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY;
+
+}
diff --git a/src/java/org/apache/commons/pool/impl/StackObjectPool.java b/src/java/org/apache/commons/pool/impl/StackObjectPool.java
new file mode 100644
index 0000000..44faebe
--- /dev/null
+++ b/src/java/org/apache/commons/pool/impl/StackObjectPool.java
@@ -0,0 +1,253 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/impl/StackObjectPool.java,v 1.1 2001/04/14 16:41:56 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:41:56 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import org.apache.commons.pool.*;
+import java.util.Stack;
+import java.util.NoSuchElementException;
+import java.util.Enumeration;
+
+/**
+ * A simple, {@link java.util.Stack Stack}-based {@link ObjectPool} implementation.
+ * <p>
+ * Given a {@link PoolableObjectFactory}, this class will maintain
+ * a simple pool of instances. A finite number of "sleeping"
+ * or idle instances is enforced, but when the pool is
+ * empty, new instances are created to support the new load.
+ * Hence this class places no limit on the number of "active"
+ * instances created by the pool, but is quite useful for
+ * re-using <tt>Object</tt>s without introducing
+ * artificial limits.
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: StackObjectPool.java,v 1.1 2001/04/14 16:41:56 rwaldhoff Exp $
+ */
+public class StackObjectPool implements ObjectPool {
+ /**
+ * Create a new pool using
+ * no factory. Clients must first populate the pool
+ * using {@link #returnObject(java.lang.Object)}
+ * before they can be {@link #borrowObject borrowed}.
+ */
+ public StackObjectPool() {
+ this((PoolableObjectFactory)null,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ /**
+ * Create a new pool using
+ * no factory. Clients must first populate the pool
+ * using {@link #returnObject(java.lang.Object)}
+ * before they can be {@link #borrowObject borrowed}.
+ */
+ public StackObjectPool(int max) {
+ this((PoolableObjectFactory)null,max,DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ /**
+ * Create a new pool using
+ * no factory. Clients must first populate the pool
+ * using {@link #returnObject(java.lang.Object)}
+ * before they can be {@link #borrowObject borrowed}.
+ */
+ public StackObjectPool(int max, int init) {
+ this((PoolableObjectFactory)null,max,init);
+ }
+
+ /**
+ * Create a new <tt>StackObjectPool</tt> using
+ * the specified <i>factory</i> to create new instances.
+ *
+ * @param factory the {@link PoolableObjectFactory} used to populate the pool
+ */
+ public StackObjectPool(PoolableObjectFactory factory) {
+ this(factory,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ /**
+ * Create a new <tt>SimpleObjectPool</tt> using
+ * the specified <i>factory</i> to create new instances,
+ * capping the number of "sleeping" instances to <i>max</i>
+ *
+ * @param factory the {@link PoolableObjectFactory} used to populate the pool
+ * @param max cap on the number of "sleeping" instances in the pool
+ */
+ public StackObjectPool(PoolableObjectFactory factory, int max) {
+ this(factory,max,DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ /**
+ * Create a new <tt>SimpleObjectPool</tt> using
+ * the specified <i>factory</i> to create new instances,
+ * capping the number of "sleeping" instances to <i>max</i>,
+ * and initially allocating a container capable of containing
+ * at least <i>init</i> instances.
+ *
+ * @param factory the {@link PoolableObjectFactory} used to populate the pool
+ * @param max cap on the number of "sleeping" instances in the pool
+ * @param init initial size of the pool (this specifies the size of the container,
+ * it does not cause the pool to be pre-populated.)
+ */
+ public StackObjectPool(PoolableObjectFactory factory, int max, int init) {
+ _factory = factory;
+ _maxSleeping = (max < 0 ? DEFAULT_MAX_SLEEPING : max);
+ int initcapacity = (init < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : init);
+ _pool = new Stack();
+ _pool.ensureCapacity( initcapacity > _maxSleeping ? _maxSleeping : initcapacity);
+ }
+
+ public synchronized Object borrowObject() {
+ Object obj = null;
+ try {
+ obj = _pool.pop();
+ } catch(Exception e) {
+ if(null == _factory) {
+ throw new NoSuchElementException();
+ } else {
+ obj = _factory.makeObject();
+ }
+ }
+ if(null != _factory && null != obj) {
+ _factory.activateObject(obj);
+ }
+ _numActive++;
+ return obj;
+ }
+
+ public synchronized void returnObject(Object obj) {
+ _numActive--;
+ if(null == _factory || _factory.validateObject(obj)) {
+ if(null != _factory) {
+ try {
+ _factory.passivateObject(obj);
+ } catch(Exception e) {
+ _factory.destroyObject(obj);
+ return;
+ }
+ }
+ if(_pool.size() < _maxSleeping) {
+ _pool.push(obj);
+ } else {
+ if(null != _factory) {
+ _factory.destroyObject(obj);
+ }
+ }
+ } else {
+ if(null != _factory) {
+ _factory.destroyObject(obj);
+ }
+ }
+ }
+
+ public int numIdle() {
+ return _pool.size();
+ }
+
+ public int numActive() {
+ return _numActive;
+ }
+
+ public synchronized void clear() throws UnsupportedOperationException {
+ if(null != _factory) {
+ Enumeration enum = _pool.elements();
+ while(enum.hasMoreElements()) {
+ _factory.destroyObject(enum.nextElement());
+ }
+ }
+ _pool.clear();
+ }
+
+ synchronized public void close() {
+ clear();
+ _pool = null;
+ _factory = null;
+ }
+
+ synchronized public void setFactory(PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
+ if(0 < numActive()) {
+ throw new IllegalStateException("Objects are already active");
+ } else {
+ clear();
+ _factory = factory;
+ }
+ }
+
+ /** The default cap on the number of "sleeping" instances in the pool. */
+ protected static final int DEFAULT_MAX_SLEEPING = 8;
+
+ /**
+ * The default initial size of the pool
+ * (this specifies the size of the container, it does not
+ * cause the pool to be pre-populated.)
+ */
+ protected static final int DEFAULT_INIT_SLEEPING_CAPACITY = 4;
+
+ /** My pool. */
+ protected Stack _pool = null;
+
+ /** My {@link PoolableObjectFactory}. */
+ protected PoolableObjectFactory _factory = null;
+
+ /** The cap on the number of "sleeping" instances in the pool. */
+ protected int _maxSleeping = DEFAULT_MAX_SLEEPING;
+
+ protected int _numActive = 0;
+}
\ No newline at end of file
diff --git a/src/java/org/apache/commons/pool/impl/StackObjectPoolFactory.java b/src/java/org/apache/commons/pool/impl/StackObjectPoolFactory.java
new file mode 100644
index 0000000..c2aa276
--- /dev/null
+++ b/src/java/org/apache/commons/pool/impl/StackObjectPoolFactory.java
@@ -0,0 +1,113 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/java/org/apache/commons/pool/impl/StackObjectPoolFactory.java,v 1.1 2001/04/14 16:41:58 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:41:58 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import org.apache.commons.pool.*;
+import java.util.Stack;
+import java.util.NoSuchElementException;
+import java.util.Enumeration;
+
+/**
+ * A factory for creating {@link StackObjectPool} instances.
+ *
+ * @see StackObjectPool
+ * @see KeyedObjectPoolFactory
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: StackObjectPoolFactory.java,v 1.1 2001/04/14 16:41:58 rwaldhoff Exp $
+ */
+public class StackObjectPoolFactory implements ObjectPoolFactory {
+ public StackObjectPoolFactory() {
+ this((PoolableObjectFactory)null,StackObjectPool.DEFAULT_MAX_SLEEPING,StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ public StackObjectPoolFactory(int max) {
+ this((PoolableObjectFactory)null,max,StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ public StackObjectPoolFactory(int max, int init) {
+ this((PoolableObjectFactory)null,max,init);
+ }
+
+ public StackObjectPoolFactory(PoolableObjectFactory factory) {
+ this(factory,StackObjectPool.DEFAULT_MAX_SLEEPING,StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ public StackObjectPoolFactory(PoolableObjectFactory factory, int max) {
+ this(factory,max,StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY);
+ }
+
+ public StackObjectPoolFactory(PoolableObjectFactory factory, int max, int init) {
+ _factory = factory;
+ _maxSleeping = max;
+ _initCapacity = init;
+ }
+
+ public ObjectPool createPool() {
+ return new StackObjectPool(_factory,_maxSleeping,_initCapacity);
+ }
+
+ protected PoolableObjectFactory _factory = null;
+ protected int _maxSleeping = StackObjectPool.DEFAULT_MAX_SLEEPING;
+ protected int _initCapacity = StackObjectPool.DEFAULT_INIT_SLEEPING_CAPACITY;
+
+}
diff --git a/src/java/org/apache/commons/pool/impl/package.html b/src/java/org/apache/commons/pool/impl/package.html
new file mode 100644
index 0000000..2cb4408
--- /dev/null
+++ b/src/java/org/apache/commons/pool/impl/package.html
@@ -0,0 +1,40 @@
+<!-- $Id: package.html,v 1.1 2001/04/14 16:41:59 rwaldhoff Exp $ -->
+<html>
+ <head>
+ <title>Package Documentation for org.apache.commons.pool.impl</title>
+ </head>
+ <body>
+ <p>
+ Object pooling API implementations.
+ </p>
+ <p>
+ {@link org.apache.commons.pool.impl.StackObjectPool StackObjectPool}
+ ({@link org.apache.commons.pool.impl.StackKeyedObjectPool StackKeyedObjectPool})
+ provides a simple, {@link java.util.Stack Stack}-based
+ implementation of {@link org.apache.commons.pool.ObjectPool ObjectPool}
+ ({@link org.apache.commons.pool.KeyedObjectPool KeyedObjectPool}).
+ {@link org.apache.commons.pool.impl.StackObjectPoolFactory StackObjectPoolFactory}
+ ({@link org.apache.commons.pool.impl.StackKeyedObjectPoolFactory StackKeyedObjectPoolFactory})
+ provides an implementation of the
+ {@link org.apache.commons.pool.ObjectPoolFactory ObjectPoolFactory}
+ ({@link org.apache.commons.pool.KeyedObjectPoolFactory KeyedObjectPoolFactory})
+ factory interface for this class.
+ </p>
+ <p>
+ {@link org.apache.commons.pool.impl.GenericObjectPool GenericObjectPool}
+ ({@link org.apache.commons.pool.impl.GenericKeyedObjectPool GenericKeyedObjectPool})
+ provides a more robust (but also more complicated)
+ implementation of {@link org.apache.commons.pool.ObjectPool ObjectPool}
+ ({@link org.apache.commons.pool.KeyedObjectPool KeyedObjectPool}).
+ {@link org.apache.commons.pool.impl.GenericObjectPoolFactory GenericObjectPoolFactory}
+ ({@link org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory GenericKeyedObjectPoolFactory})
+ provides an implementation of the
+ {@link org.apache.commons.pool.ObjectPoolFactory ObjectPoolFactory}
+ ({@link org.apache.commons.pool.KeyedObjectPoolFactory KeyedObjectPoolFactory})
+ factory interface for this class.
+ </p>
+ <p>
+ See also the {@link org.apache.commons.pool} package.
+ </p>
+ </body>
+</html>
diff --git a/src/java/org/apache/commons/pool/package.html b/src/java/org/apache/commons/pool/package.html
new file mode 100644
index 0000000..78e31c5
--- /dev/null
+++ b/src/java/org/apache/commons/pool/package.html
@@ -0,0 +1,40 @@
+<!-- $Id: package.html,v 1.1 2001/04/14 16:40:54 rwaldhoff Exp $ -->
+<html>
+ <head>
+ <title>Package Documentation for org.apache.commons.pool</title>
+ </head>
+ <body>
+ <p>
+ Generic object pooling API.
+ </p>
+ <p>
+ The pool package seperates the way in which objects are pooled
+ from the way in which they are created. To use the pooling API, simply
+ associate a
+ {@link org.apache.commons.pool.PoolableObjectFactory PoolableObjectFactory}
+ ({@link org.apache.commons.pool.KeyedPoolableObjectFactory KeyedPoolableObjectFactory})
+ implementation with an
+ {@link org.apache.commons.pool.ObjectPool ObjectPool}
+ ({@link org.apache.commons.pool.KeyedObjectPool KeyedObjectPool})
+ implementation.
+ </p>
+ <p>
+ {@link org.apache.commons.pool.ObjectPool ObjectPool} defines a simple
+ object pooling interface.
+ {@link org.apache.commons.pool.KeyedObjectPool KeyedObjectPool} defines a
+ similiar interface for pooling "typed" or "keyed" objects.
+ </p>
+ <p>
+ The {@link org.apache.commons.pool.PoolableObjectFactory PoolableObjectFactory}
+ interface defines lifecycle methods for instances to be returned from an
+ {@link org.apache.commons.pool.ObjectPool ObjectPool}.
+ The {@link org.apache.commons.pool.KeyedPoolableObjectFactory KeyedPoolableObjectFactory}
+ interface defines similiar methods for instances to be returned from a
+ {@link org.apache.commons.pool.KeyedObjectPool KeyedObjectPool}.
+ </p>
+ <p>
+ The {@link org.apache.commons.pool.impl} package contains several simple
+ pool implementations.
+ </p>
+ </body>
+</html>
diff --git a/src/test/org/apache/commons/pool/TestAll.java b/src/test/org/apache/commons/pool/TestAll.java
new file mode 100644
index 0000000..171dfc5
--- /dev/null
+++ b/src/test/org/apache/commons/pool/TestAll.java
@@ -0,0 +1,85 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/test/org/apache/commons/pool/TestAll.java,v 1.1 2001/04/14 16:42:01 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:42:01 $
+ *
+ * ====================================================================
+ *
+ * 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.pool;
+
+import junit.framework.*;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Id: TestAll.java,v 1.1 2001/04/14 16:42:01 rwaldhoff Exp $
+ */
+public class TestAll extends TestCase {
+ public TestAll(String testName) {
+ super(testName);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(org.apache.commons.pool.impl.TestAll.suite());
+ return suite;
+ }
+
+ public static void main(String args[]) {
+ String[] testCaseName = { TestAll.class.getName() };
+ junit.textui.TestRunner.main(testCaseName);
+ }
+}
diff --git a/src/test/org/apache/commons/pool/impl/TestAll.java b/src/test/org/apache/commons/pool/impl/TestAll.java
new file mode 100644
index 0000000..0793456
--- /dev/null
+++ b/src/test/org/apache/commons/pool/impl/TestAll.java
@@ -0,0 +1,91 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/test/org/apache/commons/pool/impl/TestAll.java,v 1.1 2001/04/14 16:42:02 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:42:02 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import junit.framework.*;
+
+/**
+ * JUnit test suite for the {@link org.apache.commons.pool.impl}
+ * package.
+ *
+ * @author Rodney Waldhoff
+ * @version $Id: TestAll.java,v 1.1 2001/04/14 16:42:02 rwaldhoff Exp $
+ */
+public class TestAll extends TestCase {
+ public TestAll(String testName) {
+ super(testName);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(TestStackObjectPool.suite());
+ suite.addTest(TestStackKeyedObjectPool.suite());
+ suite.addTest(TestGenericObjectPool.suite());
+ suite.addTest(TestGenericKeyedObjectPool.suite());
+ return suite;
+ }
+
+ public static void main(String args[]) {
+ String[] testCaseName = { TestAll.class.getName() };
+ junit.textui.TestRunner.main(testCaseName);
+ }
+}
diff --git a/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java b/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java
new file mode 100644
index 0000000..c9ab6e6
--- /dev/null
+++ b/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java
@@ -0,0 +1,419 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java,v 1.1 2001/04/14 16:42:08 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:42:08 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import junit.framework.*;
+import org.apache.commons.pool.*;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Id: TestGenericKeyedObjectPool.java,v 1.1 2001/04/14 16:42:08 rwaldhoff Exp $
+ */
+public class TestGenericKeyedObjectPool extends TestCase {
+ public TestGenericKeyedObjectPool(String testName) {
+ super(testName);
+ }
+
+ public static Test suite() {
+ return new TestSuite(TestGenericKeyedObjectPool.class);
+ }
+
+ public static void main(String args[]) {
+ String[] testCaseName = { TestGenericKeyedObjectPool.class.getName() };
+ junit.textui.TestRunner.main(testCaseName);
+ }
+
+ private GenericKeyedObjectPool pool = null;
+
+ public void setUp() {
+ pool = new GenericKeyedObjectPool(
+ new KeyedPoolableObjectFactory() {
+ int counter = 0;
+ public Object makeObject(Object key) { return String.valueOf(key) + String.valueOf(counter++); }
+ public void destroyObject(Object key, Object obj) { }
+ public boolean validateObject(Object key, Object obj) { return true; }
+ public void activateObject(Object key, Object obj) { }
+ public void passivateObject(Object key, Object obj) { }
+ }
+ );
+ }
+
+ public void testBorrow() {
+ Object obj0 = pool.borrowObject("");
+ assertEquals("0",obj0);
+ Object obj1 = pool.borrowObject("");
+ assertEquals("1",obj1);
+ Object obj2 = pool.borrowObject("");
+ assertEquals("2",obj2);
+ }
+
+ public void testBorrowReturn() {
+ Object obj0 = pool.borrowObject("");
+ assertEquals("0",obj0);
+ Object obj1 = pool.borrowObject("");
+ assertEquals("1",obj1);
+ Object obj2 = pool.borrowObject("");
+ assertEquals("2",obj2);
+ pool.returnObject("",obj2);
+ obj2 = pool.borrowObject("");
+ assertEquals("2",obj2);
+ pool.returnObject("",obj1);
+ obj1 = pool.borrowObject("");
+ assertEquals("1",obj1);
+ pool.returnObject("",obj0);
+ pool.returnObject("",obj2);
+ obj2 = pool.borrowObject("");
+ assertEquals("2",obj2);
+ obj0 = pool.borrowObject("");
+ assertEquals("0",obj0);
+ }
+
+ public void testNumActiveNumIdle() {
+ assertEquals(0,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ Object obj0 = pool.borrowObject("");
+ assertEquals(1,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ Object obj1 = pool.borrowObject("");
+ assertEquals(2,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ pool.returnObject("",obj1);
+ assertEquals(1,pool.numActive(""));
+ assertEquals(1,pool.numIdle(""));
+ pool.returnObject("",obj0);
+ assertEquals(0,pool.numActive(""));
+ assertEquals(2,pool.numIdle(""));
+ }
+
+ public void testNumActiveNumIdle2() {
+ assertEquals(0,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ assertEquals(0,pool.numActive("A"));
+ assertEquals(0,pool.numIdle("A"));
+ assertEquals(0,pool.numActive("B"));
+ assertEquals(0,pool.numIdle("B"));
+
+ Object objA0 = pool.borrowObject("A");
+ Object objB0 = pool.borrowObject("B");
+
+ assertEquals(2,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ assertEquals(1,pool.numActive("A"));
+ assertEquals(0,pool.numIdle("A"));
+ assertEquals(1,pool.numActive("B"));
+ assertEquals(0,pool.numIdle("B"));
+
+ Object objA1 = pool.borrowObject("A");
+ Object objB1 = pool.borrowObject("B");
+
+ assertEquals(4,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ assertEquals(2,pool.numActive("A"));
+ assertEquals(0,pool.numIdle("A"));
+ assertEquals(2,pool.numActive("B"));
+ assertEquals(0,pool.numIdle("B"));
+
+ pool.returnObject("A",objA0);
+ pool.returnObject("B",objB0);
+
+ assertEquals(2,pool.numActive());
+ assertEquals(2,pool.numIdle());
+ assertEquals(1,pool.numActive("A"));
+ assertEquals(1,pool.numIdle("A"));
+ assertEquals(1,pool.numActive("B"));
+ assertEquals(1,pool.numIdle("B"));
+
+ pool.returnObject("A",objA1);
+ pool.returnObject("B",objB1);
+
+ assertEquals(0,pool.numActive());
+ assertEquals(4,pool.numIdle());
+ assertEquals(0,pool.numActive("A"));
+ assertEquals(2,pool.numIdle("A"));
+ assertEquals(0,pool.numActive("B"));
+ assertEquals(2,pool.numIdle("B"));
+ }
+
+ public void testClear() {
+ assertEquals(0,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ Object obj0 = pool.borrowObject("");
+ Object obj1 = pool.borrowObject("");
+ assertEquals(2,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ pool.returnObject("",obj1);
+ pool.returnObject("",obj0);
+ assertEquals(0,pool.numActive(""));
+ assertEquals(2,pool.numIdle(""));
+ pool.clear("");
+ assertEquals(0,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ Object obj2 = pool.borrowObject("");
+ assertEquals("2",obj2);
+ }
+
+ public void testMaxIdle() {
+ pool.setMaxActive(100);
+ pool.setMaxIdle(8);
+ Object[] active = new Object[100];
+ for(int i=0;i<100;i++) {
+ active[i] = pool.borrowObject("");
+ }
+ assertEquals(100,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ for(int i=0;i<100;i++) {
+ pool.returnObject("",active[i]);
+ assertEquals(99 - i,pool.numActive(""));
+ assertEquals((i < 8 ? i+1 : 8),pool.numIdle(""));
+ }
+ }
+
+ public void testMaxActive() {
+ pool.setMaxActive(3);
+ pool.setWhenExhaustedAction(pool.WHEN_EXHAUSTED_FAIL);
+
+ pool.borrowObject("");
+ pool.borrowObject("");
+ pool.borrowObject("");
+ try {
+ pool.borrowObject("");
+ fail("Shouldn't get here.");
+ } catch(java.util.NoSuchElementException e) {
+ // expected
+ }
+ }
+
+ public void testEviction() {
+ pool.setMaxIdle(500);
+ pool.setMaxActive(500);
+ pool.setNumTestsPerEvictionRun(100);
+ pool.setMinEvictableIdleTimeMillis(500L);
+ pool.setTimeBetweenEvictionRunsMillis(500L);
+
+ Object[] active = new Object[500];
+ for(int i=0;i<500;i++) {
+ active[i] = pool.borrowObject("");
+ }
+ for(int i=0;i<500;i++) {
+ pool.returnObject("",active[i]);
+ }
+
+ try { Thread.currentThread().sleep(2000L); } catch(Exception e) { }
+ assert("Should be less than 500 idle, found " + pool.numIdle(""),pool.numIdle("") < 500);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 400 idle, found " + pool.numIdle(""),pool.numIdle("") < 400);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 300 idle, found " + pool.numIdle(""),pool.numIdle("") < 300);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 200 idle, found " + pool.numIdle(""),pool.numIdle("") < 200);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 100 idle, found " + pool.numIdle(""),pool.numIdle("") < 100);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assertEquals("Should be zero idle, found " + pool.numIdle(""),0,pool.numIdle(""));
+
+ for(int i=0;i<500;i++) {
+ active[i] = pool.borrowObject("");
+ }
+ for(int i=0;i<500;i++) {
+ pool.returnObject("",active[i]);
+ }
+
+ try { Thread.currentThread().sleep(2000L); } catch(Exception e) { }
+ assert("Should be less than 500 idle, found " + pool.numIdle(""),pool.numIdle("") < 500);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 400 idle, found " + pool.numIdle(""),pool.numIdle("") < 400);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 300 idle, found " + pool.numIdle(""),pool.numIdle("") < 300);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 200 idle, found " + pool.numIdle(""),pool.numIdle("") < 200);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 100 idle, found " + pool.numIdle(""),pool.numIdle("") < 100);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assertEquals("Should be zero idle, found " + pool.numIdle(""),0,pool.numIdle(""));
+ }
+
+ public void testEviction2() {
+ pool.setMaxIdle(500);
+ pool.setMaxActive(500);
+ pool.setNumTestsPerEvictionRun(100);
+ pool.setMinEvictableIdleTimeMillis(500L);
+ pool.setTimeBetweenEvictionRunsMillis(500L);
+
+ Object[] active = new Object[500];
+ Object[] active2 = new Object[500];
+ for(int i=0;i<500;i++) {
+ active[i] = pool.borrowObject("");
+ active2[i] = pool.borrowObject("2");
+ }
+ for(int i=0;i<500;i++) {
+ pool.returnObject("",active[i]);
+ pool.returnObject("2",active2[i]);
+ }
+
+ try { Thread.currentThread().sleep(2000L); } catch(Exception e) { }
+ assert("Should be less than 1000 idle, found " + pool.numIdle(),pool.numIdle() < 1000);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 900 idle, found " + pool.numIdle(),pool.numIdle() < 900);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 800 idle, found " + pool.numIdle(),pool.numIdle() < 800);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 700 idle, found " + pool.numIdle(),pool.numIdle() < 700);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 600 idle, found " + pool.numIdle(),pool.numIdle() < 600);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 500 idle, found " + pool.numIdle(),pool.numIdle() < 500);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 400 idle, found " + pool.numIdle(),pool.numIdle() < 400);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 300 idle, found " + pool.numIdle(),pool.numIdle() < 300);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 200 idle, found " + pool.numIdle(),pool.numIdle() < 200);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 100 idle, found " + pool.numIdle(),pool.numIdle() < 100);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assertEquals("Should be zero idle, found " + pool.numIdle(),0,pool.numIdle());
+ }
+
+ public void testThreaded1() {
+ pool.setMaxActive(15);
+ pool.setMaxIdle(15);
+ pool.setMaxWait(1000L);
+ TestThread[] threads = new TestThread[20];
+ for(int i=0;i<20;i++) {
+ threads[i] = new TestThread(pool,100,50);
+ Thread t = new Thread(threads[i]);
+ t.start();
+ }
+ for(int i=0;i<20;i++) {
+ while(!(threads[i]).complete()) {
+ try {
+ Thread.currentThread().sleep(500L);
+ } catch(Exception e) {
+ // ignored
+ }
+ }
+ if(threads[i].failed()) {
+ fail();
+ }
+ }
+ }
+
+ class TestThread implements Runnable {
+ java.util.Random _random = new java.util.Random();
+ KeyedObjectPool _pool = null;
+ boolean _complete = false;
+ boolean _failed = false;
+ int _iter = 100;
+ int _delay = 50;
+
+ public TestThread(KeyedObjectPool pool) {
+ _pool = pool;
+ }
+
+ public TestThread(KeyedObjectPool pool, int iter) {
+ _pool = pool;
+ _iter = iter;
+ }
+
+ public TestThread(KeyedObjectPool pool, int iter, int delay) {
+ _pool = pool;
+ _iter = iter;
+ _delay = delay;
+ }
+
+ public boolean complete() {
+ return _complete;
+ }
+
+ public boolean failed() {
+ return _failed;
+ }
+
+ public void run() {
+ for(int i=0;i<_iter;i++) {
+ try {
+ Thread.currentThread().sleep((long)_random.nextInt(_delay));
+ } catch(Exception e) {
+ // ignored
+ }
+ Object obj = null;
+ try {
+ obj = _pool.borrowObject("");
+ } catch(java.util.NoSuchElementException e) {
+ _failed = true;
+ _complete = true;
+ break;
+ }
+
+ try {
+ Thread.currentThread().sleep((long)_random.nextInt(_delay));
+ } catch(Exception e) {
+ // ignored
+ }
+ _pool.returnObject("",obj);
+ }
+ _complete = true;
+ }
+ }
+}
+
+
diff --git a/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java b/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java
new file mode 100644
index 0000000..8489a06
--- /dev/null
+++ b/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java
@@ -0,0 +1,329 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java,v 1.1 2001/04/14 16:42:13 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:42:13 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import junit.framework.*;
+import org.apache.commons.pool.*;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Id: TestGenericObjectPool.java,v 1.1 2001/04/14 16:42:13 rwaldhoff Exp $
+ */
+public class TestGenericObjectPool extends TestCase {
+ public TestGenericObjectPool(String testName) {
+ super(testName);
+ }
+
+ public static Test suite() {
+ return new TestSuite(TestGenericObjectPool.class);
+ }
+
+ public static void main(String args[]) {
+ String[] testCaseName = { TestGenericObjectPool.class.getName() };
+ junit.textui.TestRunner.main(testCaseName);
+ }
+
+ private GenericObjectPool pool = null;
+
+ public void setUp() {
+ pool = new GenericObjectPool(
+ new PoolableObjectFactory() {
+ int counter = 0;
+ public Object makeObject() { return String.valueOf(counter++); }
+ public void destroyObject(Object obj) { }
+ public boolean validateObject(Object obj) { return true; }
+ public void activateObject(Object obj) { }
+ public void passivateObject(Object obj) { }
+ }
+ );
+ }
+
+ public void testBorrow() {
+ Object obj0 = pool.borrowObject();
+ assertEquals("0",obj0);
+ Object obj1 = pool.borrowObject();
+ assertEquals("1",obj1);
+ Object obj2 = pool.borrowObject();
+ assertEquals("2",obj2);
+ }
+
+ public void testBorrowReturn() {
+ Object obj0 = pool.borrowObject();
+ assertEquals("0",obj0);
+ Object obj1 = pool.borrowObject();
+ assertEquals("1",obj1);
+ Object obj2 = pool.borrowObject();
+ assertEquals("2",obj2);
+ pool.returnObject(obj2);
+ obj2 = pool.borrowObject();
+ assertEquals("2",obj2);
+ pool.returnObject(obj1);
+ obj1 = pool.borrowObject();
+ assertEquals("1",obj1);
+ pool.returnObject(obj0);
+ pool.returnObject(obj2);
+ obj2 = pool.borrowObject();
+ assertEquals("2",obj2);
+ obj0 = pool.borrowObject();
+ assertEquals("0",obj0);
+ }
+
+ public void testNumActiveNumIdle() {
+ assertEquals(0,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ Object obj0 = pool.borrowObject();
+ assertEquals(1,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ Object obj1 = pool.borrowObject();
+ assertEquals(2,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ pool.returnObject(obj1);
+ assertEquals(1,pool.numActive());
+ assertEquals(1,pool.numIdle());
+ pool.returnObject(obj0);
+ assertEquals(0,pool.numActive());
+ assertEquals(2,pool.numIdle());
+ }
+
+ public void testClear() {
+ assertEquals(0,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ Object obj0 = pool.borrowObject();
+ Object obj1 = pool.borrowObject();
+ assertEquals(2,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ pool.returnObject(obj1);
+ pool.returnObject(obj0);
+ assertEquals(0,pool.numActive());
+ assertEquals(2,pool.numIdle());
+ pool.clear();
+ assertEquals(0,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ Object obj2 = pool.borrowObject();
+ assertEquals("2",obj2);
+ }
+
+ public void testMaxIdle() {
+ pool.setMaxActive(100);
+ pool.setMaxIdle(8);
+ Object[] active = new Object[100];
+ for(int i=0;i<100;i++) {
+ active[i] = pool.borrowObject();
+ }
+ assertEquals(100,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ for(int i=0;i<100;i++) {
+ pool.returnObject(active[i]);
+ assertEquals(99 - i,pool.numActive());
+ assertEquals((i < 8 ? i+1 : 8),pool.numIdle());
+ }
+ }
+
+ public void testMaxActive() {
+ pool.setMaxActive(3);
+ pool.setWhenExhaustedAction(pool.WHEN_EXHAUSTED_FAIL);
+
+ pool.borrowObject();
+ pool.borrowObject();
+ pool.borrowObject();
+ try {
+ pool.borrowObject();
+ fail("Shouldn't get here.");
+ } catch(java.util.NoSuchElementException e) {
+ // expected
+ }
+ }
+
+ public void testEviction() {
+ pool.setMaxIdle(500);
+ pool.setMaxActive(500);
+ pool.setNumTestsPerEvictionRun(100);
+ pool.setMinEvictableIdleTimeMillis(500L);
+ pool.setTimeBetweenEvictionRunsMillis(500L);
+
+ Object[] active = new Object[500];
+ for(int i=0;i<500;i++) {
+ active[i] = pool.borrowObject();
+ }
+ for(int i=0;i<500;i++) {
+ pool.returnObject(active[i]);
+ }
+
+ try { Thread.currentThread().sleep(2000L); } catch(Exception e) { }
+ assert("Should be less than 500 idle, found " + pool.numIdle(),pool.numIdle() < 500);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 400 idle, found " + pool.numIdle(),pool.numIdle() < 400);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 300 idle, found " + pool.numIdle(),pool.numIdle() < 300);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 200 idle, found " + pool.numIdle(),pool.numIdle() < 200);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 100 idle, found " + pool.numIdle(),pool.numIdle() < 100);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assertEquals("Should be zero idle, found " + pool.numIdle(),0,pool.numIdle());
+
+ for(int i=0;i<500;i++) {
+ active[i] = pool.borrowObject();
+ }
+ for(int i=0;i<500;i++) {
+ pool.returnObject(active[i]);
+ }
+
+ try { Thread.currentThread().sleep(2000L); } catch(Exception e) { }
+ assert("Should be less than 500 idle, found " + pool.numIdle(),pool.numIdle() < 500);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 400 idle, found " + pool.numIdle(),pool.numIdle() < 400);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 300 idle, found " + pool.numIdle(),pool.numIdle() < 300);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 200 idle, found " + pool.numIdle(),pool.numIdle() < 200);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assert("Should be less than 100 idle, found " + pool.numIdle(),pool.numIdle() < 100);
+ try { Thread.currentThread().sleep(600L); } catch(Exception e) { }
+ assertEquals("Should be zero idle, found " + pool.numIdle(),0,pool.numIdle());
+ }
+
+
+ public void testThreaded1() {
+ pool.setMaxActive(15);
+ pool.setMaxIdle(15);
+ pool.setMaxWait(1000L);
+ TestThread[] threads = new TestThread[20];
+ for(int i=0;i<20;i++) {
+ threads[i] = new TestThread(pool,100,50);
+ Thread t = new Thread(threads[i]);
+ t.start();
+ }
+ for(int i=0;i<20;i++) {
+ while(!(threads[i]).complete()) {
+ try {
+ Thread.currentThread().sleep(500L);
+ } catch(Exception e) {
+ // ignored
+ }
+ }
+ if(threads[i].failed()) {
+ fail();
+ }
+ }
+ }
+
+ class TestThread implements Runnable {
+ java.util.Random _random = new java.util.Random();
+ ObjectPool _pool = null;
+ boolean _complete = false;
+ boolean _failed = false;
+ int _iter = 100;
+ int _delay = 50;
+
+ public TestThread(ObjectPool pool) {
+ _pool = pool;
+ }
+
+ public TestThread(ObjectPool pool, int iter) {
+ _pool = pool;
+ _iter = iter;
+ }
+
+ public TestThread(ObjectPool pool, int iter, int delay) {
+ _pool = pool;
+ _iter = iter;
+ _delay = delay;
+ }
+
+ public boolean complete() {
+ return _complete;
+ }
+
+ public boolean failed() {
+ return _failed;
+ }
+
+ public void run() {
+ for(int i=0;i<_iter;i++) {
+ try {
+ Thread.currentThread().sleep((long)_random.nextInt(_delay));
+ } catch(Exception e) {
+ // ignored
+ }
+ Object obj = null;
+ try {
+ obj = _pool.borrowObject();
+ } catch(java.util.NoSuchElementException e) {
+ _failed = true;
+ _complete = true;
+ break;
+ }
+
+ try {
+ Thread.currentThread().sleep((long)_random.nextInt(_delay));
+ } catch(Exception e) {
+ // ignored
+ }
+ _pool.returnObject(obj);
+ }
+ _complete = true;
+ }
+ }
+}
+
+
diff --git a/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java b/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java
new file mode 100644
index 0000000..d9f5425
--- /dev/null
+++ b/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java
@@ -0,0 +1,227 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java,v 1.1 2001/04/14 16:42:16 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:42:16 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import junit.framework.*;
+import org.apache.commons.pool.*;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Id: TestStackKeyedObjectPool.java,v 1.1 2001/04/14 16:42:16 rwaldhoff Exp $
+ */
+public class TestStackKeyedObjectPool extends TestCase {
+ public TestStackKeyedObjectPool(String testName) {
+ super(testName);
+ }
+
+ public static Test suite() {
+ return new TestSuite(TestStackKeyedObjectPool.class);
+ }
+
+ public static void main(String args[]) {
+ String[] testCaseName = { TestStackKeyedObjectPool.class.getName() };
+ junit.textui.TestRunner.main(testCaseName);
+ }
+
+ private StackKeyedObjectPool pool = null;
+
+ public void setUp() {
+ pool = new StackKeyedObjectPool(
+ new KeyedPoolableObjectFactory() {
+ int counter = 0;
+ public Object makeObject(Object key) { return String.valueOf(key) + String.valueOf(counter++); }
+ public void destroyObject(Object key, Object obj) { }
+ public boolean validateObject(Object key, Object obj) { return true; }
+ public void activateObject(Object key, Object obj) { }
+ public void passivateObject(Object key, Object obj) { }
+ }
+ );
+ }
+
+ public void testBorrow() {
+ Object obj0 = pool.borrowObject("");
+ assertEquals("0",obj0);
+ Object obj1 = pool.borrowObject("");
+ assertEquals("1",obj1);
+ Object obj2 = pool.borrowObject("");
+ assertEquals("2",obj2);
+ }
+
+ public void testBorrowReturn() {
+ Object obj0 = pool.borrowObject("");
+ assertEquals("0",obj0);
+ Object obj1 = pool.borrowObject("");
+ assertEquals("1",obj1);
+ Object obj2 = pool.borrowObject("");
+ assertEquals("2",obj2);
+ pool.returnObject("",obj2);
+ obj2 = pool.borrowObject("");
+ assertEquals("2",obj2);
+ pool.returnObject("",obj1);
+ obj1 = pool.borrowObject("");
+ assertEquals("1",obj1);
+ pool.returnObject("",obj0);
+ pool.returnObject("",obj2);
+ obj2 = pool.borrowObject("");
+ assertEquals("2",obj2);
+ obj0 = pool.borrowObject("");
+ assertEquals("0",obj0);
+ }
+
+ public void testNumActiveNumIdle() {
+ assertEquals(0,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ Object obj0 = pool.borrowObject("");
+ assertEquals(1,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ Object obj1 = pool.borrowObject("");
+ assertEquals(2,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ pool.returnObject("",obj1);
+ assertEquals(1,pool.numActive(""));
+ assertEquals(1,pool.numIdle(""));
+ pool.returnObject("",obj0);
+ assertEquals(0,pool.numActive(""));
+ assertEquals(2,pool.numIdle(""));
+ }
+
+ public void testNumActiveNumIdle2() {
+ assertEquals(0,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ assertEquals(0,pool.numActive("A"));
+ assertEquals(0,pool.numIdle("A"));
+ assertEquals(0,pool.numActive("B"));
+ assertEquals(0,pool.numIdle("B"));
+
+ Object objA0 = pool.borrowObject("A");
+ Object objB0 = pool.borrowObject("B");
+
+ assertEquals(2,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ assertEquals(1,pool.numActive("A"));
+ assertEquals(0,pool.numIdle("A"));
+ assertEquals(1,pool.numActive("B"));
+ assertEquals(0,pool.numIdle("B"));
+
+ Object objA1 = pool.borrowObject("A");
+ Object objB1 = pool.borrowObject("B");
+
+ assertEquals(4,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ assertEquals(2,pool.numActive("A"));
+ assertEquals(0,pool.numIdle("A"));
+ assertEquals(2,pool.numActive("B"));
+ assertEquals(0,pool.numIdle("B"));
+
+ pool.returnObject("A",objA0);
+ pool.returnObject("B",objB0);
+
+ assertEquals(2,pool.numActive());
+ assertEquals(2,pool.numIdle());
+ assertEquals(1,pool.numActive("A"));
+ assertEquals(1,pool.numIdle("A"));
+ assertEquals(1,pool.numActive("B"));
+ assertEquals(1,pool.numIdle("B"));
+
+ pool.returnObject("A",objA1);
+ pool.returnObject("B",objB1);
+
+ assertEquals(0,pool.numActive());
+ assertEquals(4,pool.numIdle());
+ assertEquals(0,pool.numActive("A"));
+ assertEquals(2,pool.numIdle("A"));
+ assertEquals(0,pool.numActive("B"));
+ assertEquals(2,pool.numIdle("B"));
+ }
+
+ public void testClear() {
+ assertEquals(0,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ Object obj0 = pool.borrowObject("");
+ Object obj1 = pool.borrowObject("");
+ assertEquals(2,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ pool.returnObject("",obj1);
+ pool.returnObject("",obj0);
+ assertEquals(0,pool.numActive(""));
+ assertEquals(2,pool.numIdle(""));
+ pool.clear("");
+ assertEquals(0,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ Object obj2 = pool.borrowObject("");
+ assertEquals("2",obj2);
+ }
+
+ public void testIdleCap() {
+ Object[] active = new Object[100];
+ for(int i=0;i<100;i++) {
+ active[i] = pool.borrowObject("");
+ }
+ assertEquals(100,pool.numActive(""));
+ assertEquals(0,pool.numIdle(""));
+ for(int i=0;i<100;i++) {
+ pool.returnObject("",active[i]);
+ assertEquals(99 - i,pool.numActive(""));
+ assertEquals((i < 8 ? i+1 : 8),pool.numIdle(""));
+ }
+ }
+}
diff --git a/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java b/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java
new file mode 100644
index 0000000..40f828c
--- /dev/null
+++ b/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java
@@ -0,0 +1,178 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//pool/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java,v 1.1 2001/04/14 16:42:18 rwaldhoff Exp $
+ * $Revision: 1.1 $
+ * $Date: 2001/04/14 16:42:18 $
+ *
+ * ====================================================================
+ *
+ * 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.pool.impl;
+
+import junit.framework.*;
+import org.apache.commons.pool.*;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Id: TestStackObjectPool.java,v 1.1 2001/04/14 16:42:18 rwaldhoff Exp $
+ */
+public class TestStackObjectPool extends TestCase {
+ public TestStackObjectPool(String testName) {
+ super(testName);
+ }
+
+ public static Test suite() {
+ return new TestSuite(TestStackObjectPool.class);
+ }
+
+ public static void main(String args[]) {
+ String[] testCaseName = { TestStackObjectPool.class.getName() };
+ junit.textui.TestRunner.main(testCaseName);
+ }
+
+ private StackObjectPool pool = null;
+
+ public void setUp() {
+ pool = new StackObjectPool(
+ new PoolableObjectFactory() {
+ int counter = 0;
+ public Object makeObject() { return String.valueOf(counter++); }
+ public void destroyObject(Object obj) { }
+ public boolean validateObject(Object obj) { return true; }
+ public void activateObject(Object obj) { }
+ public void passivateObject(Object obj) { }
+ }
+ );
+ }
+
+ public void testBorrow() {
+ Object obj0 = pool.borrowObject();
+ assertEquals("0",obj0);
+ Object obj1 = pool.borrowObject();
+ assertEquals("1",obj1);
+ Object obj2 = pool.borrowObject();
+ assertEquals("2",obj2);
+ }
+
+ public void testBorrowReturn() {
+ Object obj0 = pool.borrowObject();
+ assertEquals("0",obj0);
+ Object obj1 = pool.borrowObject();
+ assertEquals("1",obj1);
+ Object obj2 = pool.borrowObject();
+ assertEquals("2",obj2);
+ pool.returnObject(obj2);
+ obj2 = pool.borrowObject();
+ assertEquals("2",obj2);
+ pool.returnObject(obj1);
+ obj1 = pool.borrowObject();
+ assertEquals("1",obj1);
+ pool.returnObject(obj0);
+ pool.returnObject(obj2);
+ obj2 = pool.borrowObject();
+ assertEquals("2",obj2);
+ obj0 = pool.borrowObject();
+ assertEquals("0",obj0);
+ }
+
+ public void testNumActiveNumIdle() {
+ assertEquals(0,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ Object obj0 = pool.borrowObject();
+ assertEquals(1,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ Object obj1 = pool.borrowObject();
+ assertEquals(2,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ pool.returnObject(obj1);
+ assertEquals(1,pool.numActive());
+ assertEquals(1,pool.numIdle());
+ pool.returnObject(obj0);
+ assertEquals(0,pool.numActive());
+ assertEquals(2,pool.numIdle());
+ }
+
+ public void testClear() {
+ assertEquals(0,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ Object obj0 = pool.borrowObject();
+ Object obj1 = pool.borrowObject();
+ assertEquals(2,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ pool.returnObject(obj1);
+ pool.returnObject(obj0);
+ assertEquals(0,pool.numActive());
+ assertEquals(2,pool.numIdle());
+ pool.clear();
+ assertEquals(0,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ Object obj2 = pool.borrowObject();
+ assertEquals("2",obj2);
+ }
+
+ public void testIdleCap() {
+ Object[] active = new Object[100];
+ for(int i=0;i<100;i++) {
+ active[i] = pool.borrowObject();
+ }
+ assertEquals(100,pool.numActive());
+ assertEquals(0,pool.numIdle());
+ for(int i=0;i<100;i++) {
+ pool.returnObject(active[i]);
+ assertEquals(99 - i,pool.numActive());
+ assertEquals((i < 8 ? i+1 : 8),pool.numIdle());
+ }
+ }
+}