[pkg-java] r2656 - in branches/commons-pool: . upstream upstream/1.3 upstream/1.3/src upstream/1.3/src/java upstream/1.3/src/java/org upstream/1.3/src/java/org/apache upstream/1.3/src/java/org/apache/commons upstream/1.3/src/java/org/apache/commons/pool upstream/1.3/src/java/org/apache/commons/pool/impl upstream/1.3/src/test upstream/1.3/src/test/org upstream/1.3/src/test/org/apache upstream/1.3/src/test/org/apache/commons upstream/1.3/src/test/org/apache/commons/pool upstream/1.3/src/test/org/apache/commons/pool/impl upstream/1.3/src/test/org/apache/commons/pool/performance upstream/1.3/xdocs upstream/1.3/xdocs/guide upstream/1.3/xdocs/images upstream/1.3/xdocs/images/uml upstream/1.3/xdocs/style

Marcus Better marcusb-guest at costa.debian.org
Thu Oct 26 09:27:53 UTC 2006


Author: marcusb-guest
Date: 2006-10-26 09:27:52 +0000 (Thu, 26 Oct 2006)
New Revision: 2656

Added:
   branches/commons-pool/upstream/
   branches/commons-pool/upstream/1.3/
   branches/commons-pool/upstream/1.3/LICENSE.txt
   branches/commons-pool/upstream/1.3/NOTICE.txt
   branches/commons-pool/upstream/1.3/README.txt
   branches/commons-pool/upstream/1.3/RELEASE-NOTES.txt
   branches/commons-pool/upstream/1.3/build.properties.sample
   branches/commons-pool/upstream/1.3/build.xml
   branches/commons-pool/upstream/1.3/commons-pool-1.3.jar
   branches/commons-pool/upstream/1.3/maven.xml
   branches/commons-pool/upstream/1.3/project.properties
   branches/commons-pool/upstream/1.3/project.xml
   branches/commons-pool/upstream/1.3/src/
   branches/commons-pool/upstream/1.3/src/java/
   branches/commons-pool/upstream/1.3/src/java/org/
   branches/commons-pool/upstream/1.3/src/java/org/apache/
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BaseKeyedObjectPool.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BaseKeyedPoolableObjectFactory.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BaseObjectPool.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BasePoolableObjectFactory.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/KeyedObjectPool.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/KeyedObjectPoolFactory.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/KeyedPoolableObjectFactory.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/ObjectPool.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/ObjectPoolFactory.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/PoolUtils.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/PoolableObjectFactory.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPoolFactory.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericObjectPool.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericObjectPoolFactory.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/SoftReferenceObjectPool.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackKeyedObjectPool.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackKeyedObjectPoolFactory.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackObjectPool.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackObjectPoolFactory.java
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/package.html
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/overview.html
   branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/package.html
   branches/commons-pool/upstream/1.3/src/test/
   branches/commons-pool/upstream/1.3/src/test/org/
   branches/commons-pool/upstream/1.3/src/test/org/apache/
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestAll.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBaseKeyedObjectPool.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBaseKeyedPoolableObjectFactory.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBaseObjectPool.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBasePoolableObjectFactory.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestKeyedObjectPool.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestObjectPool.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestPoolUtils.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestAll.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestSoftRefOutOfMemory.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestSoftReferenceObjectPool.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/performance/
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/performance/PerformanceTest.java
   branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/performance/SleepingObjectFactory.java
   branches/commons-pool/upstream/1.3/xdocs/
   branches/commons-pool/upstream/1.3/xdocs/cvs-usage.xml
   branches/commons-pool/upstream/1.3/xdocs/downloads.xml
   branches/commons-pool/upstream/1.3/xdocs/examples.xml
   branches/commons-pool/upstream/1.3/xdocs/guide/
   branches/commons-pool/upstream/1.3/xdocs/guide/classdiagrams.xml
   branches/commons-pool/upstream/1.3/xdocs/guide/index.xml
   branches/commons-pool/upstream/1.3/xdocs/guide/sequencediagrams.xml
   branches/commons-pool/upstream/1.3/xdocs/images/
   branches/commons-pool/upstream/1.3/xdocs/images/pool-logo-blue.jpg
   branches/commons-pool/upstream/1.3/xdocs/images/pool-logo-white.png
   branches/commons-pool/upstream/1.3/xdocs/images/pool-logo-white.xcf
   branches/commons-pool/upstream/1.3/xdocs/images/uml/
   branches/commons-pool/upstream/1.3/xdocs/images/uml/GenericKeyedObjectPool.gif
   branches/commons-pool/upstream/1.3/xdocs/images/uml/GenericObjectPool.gif
   branches/commons-pool/upstream/1.3/xdocs/images/uml/KeyedObjectPool.gif
   branches/commons-pool/upstream/1.3/xdocs/images/uml/ObjectPool.gif
   branches/commons-pool/upstream/1.3/xdocs/images/uml/borrowObject.gif
   branches/commons-pool/upstream/1.3/xdocs/images/uml/invalidateObject.gif
   branches/commons-pool/upstream/1.3/xdocs/images/uml/returnObject.gif
   branches/commons-pool/upstream/1.3/xdocs/index.xml
   branches/commons-pool/upstream/1.3/xdocs/issue-tracking.xml
   branches/commons-pool/upstream/1.3/xdocs/navigation.xml
   branches/commons-pool/upstream/1.3/xdocs/release-notes-1.1.xml
   branches/commons-pool/upstream/1.3/xdocs/release-notes-1.2.xml
   branches/commons-pool/upstream/1.3/xdocs/release-notes-1.3.xml
   branches/commons-pool/upstream/1.3/xdocs/release-plan.xml
   branches/commons-pool/upstream/1.3/xdocs/style/
   branches/commons-pool/upstream/1.3/xdocs/style/project.css
Log:
Import upstream sources.


Added: branches/commons-pool/upstream/1.3/LICENSE.txt
===================================================================
--- branches/commons-pool/upstream/1.3/LICENSE.txt	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/LICENSE.txt	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

Added: branches/commons-pool/upstream/1.3/NOTICE.txt
===================================================================
--- branches/commons-pool/upstream/1.3/NOTICE.txt	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/NOTICE.txt	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,2 @@
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).

Added: branches/commons-pool/upstream/1.3/README.txt
===================================================================
--- branches/commons-pool/upstream/1.3/README.txt	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/README.txt	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,34 @@
+See http://jakarta.apache.org/commons/pool/ for additional and 
+up-to-date information on Commons Pool.
+
+Pool 1.3 is largely a bug fix only release. For a complete set of release
+notes see: http://jakarta.apache.org/commons/pool/release-notes-1.3.html
+
+Notable Bugfixes since 1.2:
+
+* GenericObjectPools are now a FIFOs. Previously they was documented as such
+  but actually implemented as a LIFOs.
+
+* Synchronizations improvements across all implementations.
+
+Notable Additions since 1.2:
+
+* GenericObjectPool introduced a SoftMinEvictableIdleTimeMillis property
+  which can be used to evict idle objects so long as their eviction
+  would maintain the requested minIdle count.
+
+* PoolUtils contains a number of utility methods to decorate pools.
+
+* The one dependency on Commons Collections has been removed (okay,
+  technically a deletion) and the only requirement is Java 1.3 or above.
+
+Miscellaneous issues:
+
+Some of the unit tests may fail spuriously because they are trying to test
+behavior that depends on the thread scheduler or the garbage collector. If
+you get a test failure that has "evictor" or "thread" in the test name,
+please run this test a few times before reporting a bug report for it. If
+you know how to make one of these unit tests better, please submit a patch.
+
+
+The Apache Jakarta Commons Team, March 2006
\ No newline at end of file

Added: branches/commons-pool/upstream/1.3/RELEASE-NOTES.txt
===================================================================
--- branches/commons-pool/upstream/1.3/RELEASE-NOTES.txt	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/RELEASE-NOTES.txt	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,39 @@
+$Id: RELEASE-NOTES.txt 389017 2006-03-27 04:21:03Z sandymac $
+
+			 Commons Pool Package
+			    Version 1.3
+			   Release Notes
+
+Full Release Notes can be found online at
+http://jakarta.apache.org/commons/pool/release-notes-1.3.html
+or in the binary distrobution in the docs/release-notes-1.3.html
+
+
+Compatibility with 1.2
+----------------------
+
+Binary compatible - Yes
+
+Source compatible - Yes
+
+Semantic compatible - Yes*
+
+
+* GenericObjectPool and GenericKeyedObjectPool have always
+  been documented to be a FIFO but it was actually
+  implemented as a LIFO. Code that depends on the previous
+  LIFO behavior may have issues.
+
+
+Feedback
+--------
+Open source works best when you give feedback:
+http://jakarta.apache.org/commons/pool/
+
+Please direct all bug reports to Bugzilla (prefix bug reports by [Pool])
+http://issues.apache.org/bugzilla/buglist.cgi?product=Commons&component=Pool
+
+Or subscribe to the commons-user mailing list (prefix emails by [Pool])
+http://jakarta.apache.org/site/mail.html
+
+The Commons-Pool Team
\ No newline at end of file

Added: branches/commons-pool/upstream/1.3/build.properties.sample
===================================================================
--- branches/commons-pool/upstream/1.3/build.properties.sample	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/build.properties.sample	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,16 @@
+#   Copyright 2003-2004,2006 The Apache Software Foundation
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+# junit.jar - JUnit 3.2+ Classpath
+junit.jar=/java/junit/junit.jar

Added: branches/commons-pool/upstream/1.3/build.xml
===================================================================
--- branches/commons-pool/upstream/1.3/build.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/build.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,169 @@
+<!--
+   Copyright 2003-2004,2006 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<!-- $Id: build.xml 390933 2006-04-03 00:46:35Z sandymac $ -->
+<project name="commons-pool" default="test" basedir=".">
+
+   <target name="init">
+      <tstamp/>
+
+      <!-- read properties from the build.properties, if any -->
+      <property name="component-propfile" value="${basedir}/build.properties"/>
+      <property file="${component-propfile}"/>
+
+      <!-- read properties from the commons build.properties, if any -->
+      <property name="commons-propfile" value="${basedir}/../build.properties"/>
+      <property file="${commons-propfile}"/>
+
+      <!-- read properties from the ${user.home}/propfile, if any -->
+      <property name="user-propfile" value="${user.home}/build.properties"/>
+      <property file="${user-propfile}"/>
+
+      <!-- command line classpath, if any -->
+      <property name="cp" value=""/>
+
+      <!-- now combine the classpaths -->
+      <property name="classpath" value="${cp}:${junit.jar}"/>
+
+      <property name="name" value="commons-pool"/>
+      <property name="title" value="Jakarta Commons Object Pooling Package"/>
+      <property name="version" value="1.3"/>
+      <property name="package" value="org.apache.commons.pool.*"/>
+
+      <property name="src.dir" value="${basedir}/src"/>
+      <property name="src.java.dir" value="${src.dir}/java"/>
+      <property name="src.test.dir" value="${src.dir}/test"/>
+      <property name="build.dir" value="${basedir}/build"/>
+      <property name="build.classes.dir" value="${build.dir}/classes"/>
+      <property name="build.test-classes.dir" value="${build.dir}/test-classes"/>
+      <property name="dist.dir" value="${basedir}/dist"/>
+      <property name="dist.jar" value="${dist.dir}/${name}-${version}.jar"/>
+
+      <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="javadoc.dir" value="${dist.dir}/docs/api"/>
+      <property name="javadoc.bottom" value="&lt;small&gt;Copyright &amp;copy; 2001-2003 Apache Software Foundation. Documenation generated ${TODAY}&lt;/small&gt;."/>
+      <property name="javadoc.overview" value="${src.java.dir}/org/apache/commons/pool/overview.html" />
+
+      <property name="javac.optimize" value="false"/>
+      <property name="javac.debug" value="true"/>
+      <property name="javac.deprecation" value="true"/>
+   </target>
+
+   <!-- ######################################################### -->
+
+   <target name="clean" depends="init" description="removes generated files">
+      <delete dir="${build.dir}"/>
+      <delete dir="${dist.dir}"/>
+   </target>
+
+   <target name="javadoc" depends="init" description="generates javadocs">
+      <mkdir dir="${javadoc.dir}"/>
+      <javadoc packagenames="org.*"
+               sourcepath="${src.java.dir}"
+               classpath="${classpath}"
+               destdir="${javadoc.dir}"
+               windowtitle="${title}"
+               doctitle="${title}"
+               bottom="${javadoc.bottom}"
+               overview="${javadoc.overview}"
+               public="true"
+               version="true"
+               author="true"
+               splitindex="false"
+               nodeprecated="true"
+               nodeprecatedlist="true"
+               notree="true"
+               noindex="false"
+               nohelp="true"
+               nonavbar="false"
+               serialwarn="false"
+               source="1.3">
+          <link href="http://java.sun.com/j2se/1.3/docs/api"/>
+      </javadoc>
+   </target>
+
+   <!-- ######################################################### -->
+
+   <target name="compile" depends="init" description="compiles source files">
+      <mkdir dir="${build.classes.dir}"/>
+      <javac destdir="${build.classes.dir}"
+             srcdir="${src.java.dir}"
+             classpath="${classpath}"
+             debug="${javac.debug}"
+             deprecation="${javac.deprecation}"
+             optimize="${javac.optimize}"
+             source="1.3"
+             target="1.3"/>
+   </target>
+   
+   <target name="compile-test" depends="compile">
+      <mkdir dir="${build.test-classes.dir}"/>
+      <javac destdir="${build.test-classes.dir}"
+             srcdir="${src.test.dir}"
+             debug="${javac.debug}"
+             deprecation="${javac.deprecation}"
+             optimize="${javac.optimize}"
+             source="1.3"
+             target="1.3">
+        <classpath>
+          <pathelement location="${build.classes.dir}" /> 
+          <pathelement location="${build.test-classes.dir}" /> 
+          <pathelement path="${classpath}" /> 
+        </classpath>
+      </javac>
+   </target>
+
+   <target name="test" depends="compile-test" description="runs (junit) unit tests">
+      <echo message="Because we need to sleep to test the eviction threads, this takes a little while (around 35 seconds)..."/>
+      <java classname="${test.runner}" fork="yes" failonerror="${test.failonerror}">
+        <arg value="${test.entry}"/> 
+        <classpath>
+          <pathelement location="${build.classes.dir}" /> 
+          <pathelement location="${build.test-classes.dir}" /> 
+          <pathelement path="${classpath}" /> 
+        </classpath>
+      </java>
+   </target>
+
+   <target name="build-jar" depends="compile">
+      <mkdir dir="${dist.dir}"/>
+      <jar jarfile="${dist.jar}">
+         <fileset dir="${build.classes.dir}"/>
+         <metainf dir="${basedir}" includes="LICENSE.txt,NOTICE.txt"/>
+         <manifest>
+            <attribute name="Built-By" value="${user.name}"/>
+            <attribute name="Package" value="${package}"/>
+            <attribute name="Extension-Name" value="${name}"/>
+            <attribute name="Specification-Vendor" value="Apache Software Foundation"/>
+            <attribute name="Specification-Title" value="${title}"/>
+            <attribute name="Implementation-Version" value="${version}"/>
+            <attribute name="Implementation-Vendor" value="Apache Software Foundation"/>
+
+         </manifest>
+      </jar>
+   </target>
+
+   <target name="build" depends="clean,build-jar,javadoc">
+      <copy todir="${dist.dir}" file="${basedir}/LICENSE.txt"/>
+      <copy todir="${dist.dir}" file="${basedir}/NOTICE.txt"/>
+      <copy todir="${dist.dir}" file="${basedir}/README.txt"/>
+   </target>
+
+   <target name="dist" depends="build" description="gump target"/>
+   
+</project>

Added: branches/commons-pool/upstream/1.3/commons-pool-1.3.jar
===================================================================
(Binary files differ)


Property changes on: branches/commons-pool/upstream/1.3/commons-pool-1.3.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/commons-pool/upstream/1.3/maven.xml
===================================================================
--- branches/commons-pool/upstream/1.3/maven.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/maven.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,94 @@
+ <!--
+   Copyright 2002-2004,2006 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+  -->
+<project
+    xmlns:j="jelly:core"
+    xmlns:ant="jelly:ant">
+
+  <!-- ============== DIST ================== -->
+  <!-- Copied from Commons-Collections        -->
+  <postGoal name="dist:prepare-bin-filesystem">
+    <j:set var="maven.dist.bin.assembly.dir" value="${pom.getPluginContext('maven-dist-plugin').getVariable('maven.dist.bin.assembly.dir')}" />
+    
+    <!-- Copy Files -->
+    <ant:copy todir="${maven.dist.bin.assembly.dir}">
+      <ant:fileset dir=".">
+        <ant:include name="NOTICE.txt"/>
+        <ant:include name="RELEASE-NOTES.txt"/>
+      </ant:fileset>
+    </ant:copy>
+
+    <!-- Copy Jars -->
+    <ant:copy todir="${maven.dist.bin.assembly.dir}">
+      <ant:fileset dir="${maven.build.dir}">
+        <ant:include name="*.jar"/>
+      </ant:fileset>
+    </ant:copy>
+
+  </postGoal>
+  
+  <postGoal name="dist:prepare-src-filesystem">
+    <j:set var="maven.dist.src.assembly.dir" value="${pom.getPluginContext('maven-dist-plugin').getVariable('maven.dist.src.assembly.dir')}" />
+    
+    <!-- Copy Files -->
+    <ant:copy todir="${maven.dist.src.assembly.dir}">
+      <ant:fileset dir=".">
+        <ant:include name="NOTICE.txt"/>
+        <ant:include name="RELEASE-NOTES.txt"/>
+        <ant:include name="build.properties.sample"/>
+      </ant:fileset>
+    </ant:copy>
+
+    <!-- Copy Jars -->
+    <ant:copy todir="${maven.dist.src.assembly.dir}">
+      <ant:fileset dir="${maven.build.dir}">
+        <ant:include name="*.jar"/>
+      </ant:fileset>
+    </ant:copy>
+    
+    <!-- Copy XDocs -->
+    <ant:copy todir="${maven.dist.src.assembly.dir}/xdocs">
+      <ant:fileset dir="xdocs" />
+    </ant:copy>
+    
+  </postGoal>
+  
+  <postGoal name="dist:build-bin">
+    <j:set var="distDir" value="${pom.getPluginContext('maven-dist-plugin').getVariable('maven.dist.dir')}"/>
+    <j:set var="finalName" value="${pom.getPluginContext('maven-dist-plugin').getVariable('maven.final.name')}"/>
+
+    <!-- create checksum for binary tar.gz -->
+    <ant:checksum file="${distDir}/${finalName}.tar.gz" property="tar.gz.md5"/>
+    <ant:echo message="${tar.gz.md5} *${finalName}.tar.gz" file="${distDir}/${finalName}.tar.gz.md5" />
+
+    <!-- create checksum for binary zip -->
+    <ant:checksum file="${distDir}/${finalName}.zip" property="zip.md5"/>
+    <ant:echo message="${zip.md5} *${finalName}.zip" file="${distDir}/${finalName}.zip.md5" />
+  </postGoal>
+  
+  <postGoal name="dist:build-src">
+    <j:set var="distDir" value="${pom.getPluginContext('maven-dist-plugin').getVariable('maven.dist.dir')}"/>
+    <j:set var="finalName" value="${pom.getPluginContext('maven-dist-plugin').getVariable('maven.final.name')}"/>
+
+    <!-- create checksum for source tar.gz -->
+    <ant:checksum file="${distDir}/${finalName}-src.tar.gz" property="src.tar.gz.md5"/>
+    <ant:echo message="${src.tar.gz.md5} *${finalName}-src.tar.gz" file="${distDir}/${finalName}-src.tar.gz.md5" />
+
+    <!-- create checksum for source zip -->
+    <ant:checksum file="${distDir}/${finalName}-src.zip" property="src.zip.md5"/>
+    <ant:echo message="${src.zip.md5} *${finalName}-src.zip" file="${distDir}/${finalName}-src.zip.md5" />
+  </postGoal>
+  
+</project>

Added: branches/commons-pool/upstream/1.3/project.properties
===================================================================
--- branches/commons-pool/upstream/1.3/project.properties	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/project.properties	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,54 @@
+#   Copyright 2003-2004,2006 The Apache Software Foundation
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+maven.checkstyle.properties = checkstyle.xml
+
+# uncomment the next line to work in offline mode (no jar download & no linkcheck)
+#maven.mode.online=
+maven.changelog.factory=org.apache.maven.svnlib.SvnChangeLogFactory
+maven.changelog.type=date
+maven.changelog.date=2004-06-07
+
+maven.javadoc.author=false
+maven.javadoc.overview=src/java/org/apache/commons/pool/overview.html
+maven.javadoc.links=http://java.sun.com/j2se/1.3/docs/api
+
+# Jar Manifest Additional Attributes
+maven.jar.manifest.attributes.list=Implementation-Vendor-Id,X-Compile-Source-JDK,X-Compile-Target-JDK
+maven.jar.manifest.attribute.Implementation-Vendor-Id=org.apache
+maven.jar.manifest.attribute.X-Compile-Source-JDK=${maven.compile.source}
+maven.jar.manifest.attribute.X-Compile-Target-JDK=${maven.compile.target}
+
+
+maven.xdoc.date=left
+maven.xdoc.poweredby.image=maven-feather.png
+maven.xdoc.version=${pom.currentVersion}
+maven.xdoc.developmentProcessUrl=http://jakarta.apache.org/commons/charter.html
+
+maven.compile.debug=on
+maven.compile.deprecation=off
+maven.compile.optimize=off
+maven.compile.source=1.3
+maven.compile.target=1.3
+
+maven.dist.src.assembly.dir=${maven.dist.assembly.dir}/src/${maven.final.name}-src
+
+maven.jdiff.new.tag=CURRENT
+maven.jdiff.old.tag=POOL_1_2
+
+maven.jarResources.basedir=src/java
+maven.jar.excludes=**/package.html
+maven.junit.fork=true
+
+clover.excludes=**/Test*.java

Added: branches/commons-pool/upstream/1.3/project.xml
===================================================================
--- branches/commons-pool/upstream/1.3/project.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/project.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,255 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2003-2004,2006 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project> 
+  <pomVersion>3</pomVersion>
+  
+  <name>Commons Pool</name>
+  <groupId>commons-pool</groupId>
+  <artifactId>commons-pool</artifactId>
+  <inceptionYear>2001</inceptionYear>
+  <currentVersion>1.3</currentVersion>
+  <shortDescription>Commons Object Pooling Library</shortDescription>
+  <description>Commons Object Pooling Library</description>
+  <logo>/images/pool-logo-white.png</logo>
+  
+  <url>http://jakarta.apache.org/commons/${pom.artifactId.substring(8)}/</url>
+  <package>org.apache.commons.${pom.artifactId.substring(8)}</package>
+
+  <organization>
+    <name>The Apache Software Foundation</name>
+    <url>http://jakarta.apache.org</url>
+    <logo>http://jakarta.apache.org/images/original-jakarta-logo.gif</logo>
+  </organization>
+
+  <licenses>
+    <license>
+        <name>The Apache Software License, Version 2.0</name>
+        <url>/LICENSE.txt</url>
+        <distribution>repo</distribution>
+    </license>
+  </licenses>
+  
+  <gumpRepositoryId>jakarta</gumpRepositoryId>
+  <issueTrackingUrl>http://issues.apache.org/bugzilla/</issueTrackingUrl>
+  <siteAddress>jakarta.apache.org</siteAddress>
+  <siteDirectory>/www/jakarta.apache.org/commons/${pom.artifactId.substring(8)}/</siteDirectory>
+  <distributionDirectory>/www/jakarta.apache.org/builds/jakarta-commons/${pom.artifactId.substring(8)}/</distributionDirectory>
+  
+  <repository>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/jakarta/commons/proper/${pom.artifactId.substring(8)}/trunk</connection>
+    <url>http://svn.apache.org/repos/asf/jakarta/commons/proper/${pom.artifactId.substring(8)}/trunk</url>
+  </repository>
+  
+  <mailingLists>
+    <mailingList>
+      <name>Commons Dev List</name>
+      <subscribe>commons-dev-subscribe at jakarta.apache.org</subscribe>
+      <unsubscribe>commons-dev-unsubscribe at jakarta.apache.org</unsubscribe>
+      <archive>http://mail-archives.apache.org/eyebrowse/SummarizeList?listName=commons-dev@jakarta.apache.org</archive>
+    </mailingList>
+    <mailingList>
+      <name>Commons User List</name>
+      <subscribe>commons-user-subscribe at jakarta.apache.org</subscribe>
+      <unsubscribe>commons-user-unsubscribe at jakarta.apache.org</unsubscribe>
+      <archive>http://mail-archives.apache.org/eyebrowse/SummarizeList?listName=commons-user@jakarta.apache.org</archive>
+    </mailingList>
+  </mailingLists>
+  
+  <versions>
+    <version>
+      <id>1.0</id>
+      <name>1.0</name>
+      <tag>POOL_1_0</tag>
+    </version>
+    <version>
+      <id>1.0.1</id>
+      <name>1.0.1</name>
+      <tag>POOL_1_0_1</tag>
+    </version>
+    <version>
+      <id>1.1</id>
+      <name>1.1</name>
+      <tag>POOL_1_1</tag>
+    </version>
+    <version>
+      <id>1.2</id>
+      <name>1.2</name>
+      <tag>POOL_1_2</tag>
+    </version>
+  </versions>
+
+  <developers>
+    <developer>
+      <name>Morgan Delagrange</name>
+      <id>morgand</id>
+      <email></email>
+      <organization></organization>
+    </developer>
+    <developer>
+      <name>Geir Magnusson</name>
+      <id>geirm</id>
+      <email></email>
+      <organization></organization>
+    </developer>
+    <developer>
+      <name>Craig McClanahan</name>
+      <id>craigmcc</id>
+      <email></email>
+      <organization></organization>
+    </developer>
+    <developer>
+      <name>Rodney Waldhoff</name>
+      <id>rwaldhoff</id>
+      <email></email>
+      <organization></organization>
+    </developer>
+    <developer>
+      <name>David Weinrich</name>
+      <id>dweinr1</id>
+      <email></email>
+      <organization></organization>
+    </developer>
+    <developer>
+      <name>Dirk Verbeeck</name>
+      <id>dirkv</id>
+      <email></email>
+      <organization></organization>
+    </developer>
+    <developer>
+      <name>Robert Burrell Donkin</name>
+      <id>rdonkin</id>
+      <email></email>
+      <organization>Apache Software Foundation</organization>
+    </developer>
+    <developer>
+      <name>Sandy McArthur</name>
+      <id>sandymac</id>
+      <email></email>
+      <organization>Apache Software Foundation</organization>
+    </developer>
+  </developers>
+  <contributors>
+    <contributor>
+      <name>Todd Carmichael</name>
+      <email>toddc at concur.com</email>
+    </contributor>
+  </contributors>
+  
+  <dependencies>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <properties>
+          <comment>Only required to run unit tests</comment>
+          <scope>test</scope>
+      </properties>
+    </dependency>
+
+    <dependency>
+      <groupId>maven</groupId>
+      <artifactId>maven-plugin-plugin</artifactId>
+      <version>1.7</version>
+      <url>http://maven.apache.org/maven-1.x/plugins/plugin/</url>
+      <type>plugin</type>
+      <properties>
+          <comment>
+              &lt;strong&gt;Site Only&lt;/strong&gt; - v1.7 (minimum)
+          </comment>
+      </properties>
+    </dependency>
+
+    <dependency>
+      <groupId>maven</groupId>
+      <artifactId>maven-scm-plugin</artifactId>
+      <version>1.5</version>
+      <url>http://maven.apache.org/maven-1.x/plugins/scm/</url>
+      <type>plugin</type>
+      <properties>
+          <comment>
+              &lt;strong&gt;Site Only&lt;/strong&gt; - v1.5 (minimum)
+          </comment>
+      </properties>
+    </dependency>
+
+    <dependency>
+      <groupId>maven</groupId>
+      <artifactId>maven-jdiff-plugin</artifactId>
+      <version>1.5</version>
+      <url>http://maven.apache.org/maven-1.x/plugins/jdiff/</url>
+      <type>plugin</type>
+      <properties>
+          <comment>
+              &lt;strong&gt;Site Only&lt;/strong&gt; - v1.5 (minimum)
+          </comment>
+      </properties>
+    </dependency>
+
+    <dependency>
+      <groupId>maven</groupId>
+      <artifactId>maven-changes-plugin</artifactId>
+      <version>1.6</version>
+      <url>http://maven.apache.org/maven-1.x/plugins/changes/</url>
+      <type>plugin</type>
+      <properties>
+          <comment>
+              &lt;strong&gt;Site Only&lt;/strong&gt; - v1.6 (minimum)
+          </comment>
+      </properties>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <nagEmailAddress>commons-dev at jakarta.apache.org</nagEmailAddress>
+    <sourceDirectory>src/java</sourceDirectory>
+    <unitTestSourceDirectory>src/test</unitTestSourceDirectory>
+    <unitTest>
+      <includes>
+        <include>org/apache/commons/pool/Test*Factory.java</include>
+        <include>org/apache/commons/pool/TestBaseObjectPool.java</include>
+        <include>org/apache/commons/pool/TestBaseKeyedObjectPool.java</include>
+        <include>org/apache/commons/pool/TestPoolUtils.java</include>
+        <include>org/apache/commons/pool/impl/Test*Pool.java</include>
+      </includes>
+    </unitTest>
+
+    <resources>
+      <resource>
+        <directory>${basedir}</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>NOTICE.txt</include>
+        </includes>
+      </resource>
+    </resources>
+  </build>
+  
+  <reports>
+    <report>maven-changes-plugin</report>
+    <report>maven-javadoc-plugin</report>
+    <report>maven-jdepend-plugin</report>
+    <report>maven-jdiff-plugin</report>
+    <report>maven-junit-report-plugin</report>
+    <report>maven-jxr-plugin</report>
+    <report>maven-license-plugin</report>
+    <report>maven-tasklist-plugin</report>
+  </reports>
+  
+</project>
+

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BaseKeyedObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BaseKeyedObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BaseKeyedObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,97 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+/**
+ * A simple base impementation of {@link ObjectPool}.
+ * All optional operations are implemented as throwing
+ * {@link UnsupportedOperationException}.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $
+ */
+public abstract class BaseKeyedObjectPool implements KeyedObjectPool {
+    public abstract Object borrowObject(Object key) throws Exception;
+    public abstract void returnObject(Object key, Object obj) throws Exception;
+    public abstract void invalidateObject(Object key, Object obj) throws Exception;
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public void addObject(Object key) throws Exception, UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public int getNumIdle(Object key) throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public int getNumActive(Object key) throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public int getNumIdle() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public int getNumActive() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public void clear() throws Exception, UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public void clear(Object key)
+    throws Exception, UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Does nothing this base implementation.
+     */
+    public void close() throws Exception {
+    }
+
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public void setFactory(KeyedPoolableObjectFactory factory)
+    throws IllegalStateException, UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BaseKeyedPoolableObjectFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BaseKeyedPoolableObjectFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BaseKeyedPoolableObjectFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,55 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+/**
+ * A base implemenation of {@link KeyedPoolableObjectFactory KeyedPoolableObjectFactory}.
+ * <p>
+ * All operations defined here are essentially no-op's.
+ *
+ * @see KeyedPoolableObjectFactory
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ */
+public abstract class BaseKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory {
+    public abstract Object makeObject(Object key)
+        throws Exception;
+
+    /** No-op. */
+    public void destroyObject(Object key, Object obj)
+        throws Exception {
+    }
+
+    /**
+     * 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)
+        throws Exception {
+    }
+
+    /** No-op. */
+    public void passivateObject(Object key, Object obj) 
+        throws Exception {
+    }
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BaseObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BaseObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BaseObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,83 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+/**
+ * A simple base impementation of {@link ObjectPool}.
+ * All optional operations are implemented as throwing
+ * {@link UnsupportedOperationException}.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 383290 $ $Date: 2006-03-05 02:00:15 -0500 (Sun, 05 Mar 2006) $
+ */
+public abstract class BaseObjectPool implements ObjectPool {
+    public abstract Object borrowObject() throws Exception;
+    public abstract void returnObject(Object obj) throws Exception;
+    public abstract void invalidateObject(Object obj) throws Exception;
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public int getNumIdle() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public int getNumActive() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public void clear() throws Exception, UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public void addObject() throws Exception, UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+    public void close() throws Exception {
+        assertOpen();
+        closed = true;
+    }
+
+    /**
+     * Not supported in this base implementation.
+     */
+    public void setFactory(PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+    
+    protected final boolean isClosed() {
+        return closed;
+    }
+    
+    protected final void assertOpen() throws IllegalStateException {
+        if(isClosed()) {
+            throw new IllegalStateException("Pool not open");
+        }
+    }
+    
+    private volatile boolean closed = false;
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BasePoolableObjectFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BasePoolableObjectFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/BasePoolableObjectFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,56 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+/**
+ * A base implemenation of {@link PoolableObjectFactory <tt>PoolableObjectFactory</tt>}.
+ * <p>
+ * All operations defined here are essentially no-op's.
+ *
+ * @see PoolableObjectFactory
+ * @see BaseKeyedPoolableObjectFactory
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ */
+public abstract class BasePoolableObjectFactory implements PoolableObjectFactory {
+    public abstract Object makeObject()
+        throws Exception;
+
+    /** No-op. */
+    public void destroyObject(Object obj)
+        throws Exception  {
+    }
+
+    /**
+     * 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)
+        throws Exception {
+    }
+
+    /** No-op. */
+    public void passivateObject(Object obj) 
+        throws Exception {
+    }
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/KeyedObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/KeyedObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/KeyedObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,197 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+/**
+ * A  "keyed" pooling interface.
+ * <p>
+ * A keyed pool pools instances of multiple types. Each
+ * type may be accessed using an arbitrary key.
+ * <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 = pool.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) {
+ *       pool.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 {@link java.util.Map Map} of
+ * {@link ObjectPool pools}).
+ * </p>
+ *
+ * @see KeyedPoolableObjectFactory
+ * @see KeyedObjectPoolFactory
+ * @see ObjectPool
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $
+ */
+public interface KeyedObjectPool {
+    /**
+     * Obtain an instance from my pool
+     * for 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 instance in the first place.
+     *
+     * @param key the key used to obtain the object
+     * @return an instance from my pool.
+     */
+    Object borrowObject(Object key) throws Exception;
+
+    /**
+     * Return an instance 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} instance to be returned.
+     */
+    void returnObject(Object key, Object obj) throws Exception;
+
+    /**
+     * Invalidates an object from the pool
+     * By contract, <i>obj</i> MUST have been obtained
+     * using {@link #borrowObject borrowObject}
+     * 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.
+     * <p>
+     * This method should be used when an object that has been borrowed
+     * is determined (due to an exception or other problem) to be invalid.
+     * If the connection should be validated before or after borrowing,
+     * then the {@link PoolableObjectFactory#validateObject} method should be
+     * used instead.
+     *
+     * @param obj a {@link #borrowObject borrowed} instance to be returned.
+     */
+    void invalidateObject(Object key, Object obj) throws Exception;
+
+    /**
+     * Create an object using my {@link #setFactory factory} or other
+     * implementation dependent mechanism, and place it into the pool.
+     * addObject() is useful for "pre-loading" a pool with idle objects.
+     * (Optional operation).
+     */
+    void addObject(Object key) throws Exception;
+
+    /**
+     * Returns the number of instances
+     * corresponding to the given <i>key</i>
+     * currently idle in my pool (optional operation).
+     * Throws {@link UnsupportedOperationException}
+     * if this information is not available.
+     *
+     * @param key the key
+     * @return the number of instances corresponding to the given <i>key</i> currently idle in my pool
+     * @throws UnsupportedOperationException when this implementation doesn't support the operation
+     */
+    int getNumIdle(Object key) throws UnsupportedOperationException;
+
+    /**
+     * Returns the number of instances
+     * currently borrowed from but not yet returned
+     * to my pool corresponding to the
+     * given <i>key</i> (optional operation).
+     * Throws {@link UnsupportedOperationException}
+     * if this information is not available.
+     *
+     * @param key the key
+     * @return the number of instances corresponding to the given <i>key</i> currently borrowed in my pool
+     * @throws UnsupportedOperationException when this implementation doesn't support the operation
+     */
+    int getNumActive(Object key) throws UnsupportedOperationException;
+
+    /**
+     * Returns the total number of instances
+     * currently idle in my pool (optional operation).
+     * Throws {@link UnsupportedOperationException}
+     * if this information is not available.
+     *
+     * @return the total number of instances currently idle in my pool
+     * @throws UnsupportedOperationException when this implementation doesn't support the operation
+     */
+    int getNumIdle() throws UnsupportedOperationException;
+
+    /**
+     * Returns the total number of instances
+     * current borrowed from my pool but not
+     * yet returned (optional operation).
+     * Throws {@link UnsupportedOperationException}
+     * if this information is not available.
+     *
+     * @return the total number of instances currently borrowed from my pool
+     * @throws UnsupportedOperationException when this implementation doesn't support the operation
+     */
+    int getNumActive() throws UnsupportedOperationException;
+
+    /**
+     * Clears my pool, removing all pooled instances
+     * (optional operation).
+     * Throws {@link UnsupportedOperationException}
+     * if the pool cannot be cleared.
+     * @throws UnsupportedOperationException when this implementation doesn't support the operation
+     */
+    void clear() throws Exception, UnsupportedOperationException;
+
+    /**
+     * Clears the specified pool, removing all
+     * pooled instances corresponding to
+     * the given <i>key</i>  (optional operation).
+     * Throws {@link UnsupportedOperationException}
+     * if the pool cannot be cleared.
+     * @param key the key to clear
+     * @throws UnsupportedOperationException when this implementation doesn't support the operation
+     */
+    void clear(Object key) throws Exception, UnsupportedOperationException;
+
+    /**
+     * Close this pool, and free any resources associated with it.
+     */
+    void close() throws Exception;
+
+    /**
+     * Sets the {@link KeyedPoolableObjectFactory factory} I use
+     * to create new instances (optional operation).
+     * @param factory the {@link KeyedPoolableObjectFactory} I use to create new instances.
+     * @throws IllegalStateException when the factory cannot be set at this time
+     * @throws UnsupportedOperationException when this implementation doesn't support the operation
+     */
+    void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException;
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/KeyedObjectPoolFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/KeyedObjectPoolFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/KeyedObjectPoolFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,33 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+/**
+ * A factory for creating {@link KeyedObjectPool}s.
+ *
+ * @see KeyedObjectPool
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ */
+public interface KeyedObjectPoolFactory {
+    /**
+     * Create a new {@link KeyedObjectPool}.
+     * @return a new {@link KeyedObjectPool}
+     */
+    KeyedObjectPool createPool();
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/KeyedPoolableObjectFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/KeyedPoolableObjectFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/KeyedPoolableObjectFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,100 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+/**
+ * An interface defining life-cycle methods for
+ * instances to be served by a
+ * {@link KeyedObjectPool KeyedObjectPool}.
+ * <p>
+ * By contract, when an {@link KeyedObjectPool KeyedObjectPool}
+ * delegates to a <tt>KeyedPoolableObjectFactory</tt>,
+ * <ol>
+ *  <li>
+ *   {@link #makeObject makeObject} 
+ *   is called  whenever a new instance is needed.
+ *  </li>
+ *  <li>
+ *   {@link #activateObject activateObject} 
+ *   is invoked on every instance before it is returned from the
+ *   pool.
+ *  </li>
+ *  <li>
+ *   {@link #passivateObject passivateObject} 
+ *   is invoked on every instance when it is returned to the
+ *   pool.
+ *  </li>
+ *  <li>
+ *   {@link #destroyObject destroyObject} 
+ *   is invoked on every instance when it is being "dropped" from the
+ *   pool (whether due to the response from
+ *   {@link #validateObject validateObject}, or
+ *   for reasons specific to the pool implementation.)
+ *  </li>
+ *  <li>
+ *   {@link #validateObject validateObject} 
+ *   is invoked in an implementation-specific fashion to determine if an instance
+ *   is still valid to be returned by the pool.
+ *   It will only be invoked on an {@link #activateObject "activated"}
+ *   instance.
+ *  </li>
+ * </ol>
+ *
+ * @see KeyedObjectPool
+ * 
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ */
+public interface KeyedPoolableObjectFactory {
+    /**
+     * Create an instance that can be served by the pool.
+     * @param key the key used when constructing the object
+     * @return an instance that can be served by the pool.
+     */
+    Object makeObject(Object key) throws Exception;
+
+    /**
+     * Destroy an instance no longer needed by the pool.
+     * @param key the key used when selecting the instance
+     * @param obj the instance to be destroyed
+     */
+    void destroyObject(Object key, Object obj) throws Exception;
+
+    /**
+     * Ensures that the instance is safe to be returned by the pool.
+     * Returns <tt>false</tt> if this instance should be destroyed.
+     * @param key the key used when selecting the object
+     * @param obj the instance 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.
+     */
+    boolean validateObject(Object key, Object obj);
+
+    /**
+     * Reinitialize an instance to be returned by the pool.
+     * @param key the key used when selecting the object
+     * @param obj the instance to be activated
+     */
+    void activateObject(Object key, Object obj) throws Exception;
+
+    /**
+     * Uninitialize an instance to be returned to the pool.
+     * @param key the key used when selecting the object
+     * @param obj the instance to be passivated
+     */
+    void passivateObject(Object key, Object obj) throws Exception;
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/ObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/ObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/ObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,142 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+/**
+ * A pooling interface.
+ * <p>
+ * <code>ObjectPool</code> defines a trivially simple pooling interface. The only 
+ * required methods are {@link #borrowObject borrowObject} and {@link #returnObject returnObject}.
+ * <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>
+ * See {@link org.apache.commons.pool.BaseObjectPool BaseObjectPool} for a simple base implementation.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ *
+ */
+public interface ObjectPool {
+    /**
+     * Obtain an instance from my pool.
+     * By contract, clients MUST return
+     * the borrowed instance using
+     * {@link #returnObject(java.lang.Object) returnObject}
+     * 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 instance from my pool.
+     */
+    Object borrowObject() throws Exception;
+
+    /**
+     * Return an instance to my pool.
+     * By contract, <i>obj</i> MUST have been obtained
+     * using {@link #borrowObject() borrowObject}
+     * or a related method as defined in an implementation
+     * or sub-interface.
+     *
+     * @param obj a {@link #borrowObject borrowed} instance to be returned.
+     */
+    void returnObject(Object obj) throws Exception;
+
+    /**
+     * Invalidates an object from the pool
+     * By contract, <i>obj</i> MUST have been obtained
+     * using {@link #borrowObject() borrowObject}
+     * or a related method as defined in an implementation
+     * or sub-interface.
+     * <p>
+     * This method should be used when an object that has been borrowed
+     * is determined (due to an exception or other problem) to be invalid.
+     * If the connection should be validated before or after borrowing,
+     * then the {@link PoolableObjectFactory#validateObject} method should be
+     * used instead.
+     *
+     * @param obj a {@link #borrowObject borrowed} instance to be returned.
+     */
+    void invalidateObject(Object obj) throws Exception;
+
+    /**
+     * Create an object using my {@link #setFactory factory} or other
+     * implementation dependent mechanism, and place it into the pool.
+     * addObject() is useful for "pre-loading" a pool with idle objects.
+     * (Optional operation).
+     */
+    void addObject() throws Exception;
+
+    /**
+     * Return the number of instances
+     * currently idle in my pool (optional operation).  
+     * This may be considered an approximation of the number
+     * of objects that can be {@link #borrowObject borrowed}
+     * without creating any new instances.
+     *
+     * @return the number of instances currently idle in my pool
+     * @throws UnsupportedOperationException if this implementation does not support the operation
+     */
+    int getNumIdle() throws UnsupportedOperationException;
+
+    /**
+     * Return the number of instances
+     * currently borrowed from my pool 
+     * (optional operation).
+     *
+     * @return the number of instances currently borrowed in my pool
+     * @throws UnsupportedOperationException if this implementation does not support the operation
+     */
+    int getNumActive() throws UnsupportedOperationException;
+
+    /**
+     * Clears any objects sitting idle in the pool, releasing any
+     * associated resources (optional operation).
+     *
+     * @throws UnsupportedOperationException if this implementation does not support the operation
+     */
+    void clear() throws Exception, UnsupportedOperationException;
+
+    /**
+     * Close this pool, and free any resources associated with it.
+     */
+    void close() throws Exception;
+
+    /**
+     * Sets the {@link PoolableObjectFactory factory} I use
+     * to create new instances (optional operation).
+     * @param factory the {@link PoolableObjectFactory} I use to create new instances.
+     *
+     * @throws IllegalStateException when the factory cannot be set at this time
+     * @throws UnsupportedOperationException if this implementation does not support the operation
+     */
+    void setFactory(PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException;
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/ObjectPoolFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/ObjectPoolFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/ObjectPoolFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,33 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+/**
+ * A factory interface for creating {@link ObjectPool}s.
+ * 
+ * @see ObjectPool
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ */
+public interface ObjectPoolFactory {
+    /**
+     * Create and return a new {@link ObjectPool}.
+     * @return a new {@link ObjectPool}
+     */
+    ObjectPool createPool();
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/PoolUtils.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/PoolUtils.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/PoolUtils.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,1106 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * This class consists exclusively of static methods that operate on or return keyedPool related interfaces.
+ *
+ * @author Sandy McArthur
+ * @version $Revision: 385296 $ $Date: 2006-03-12 10:28:08 -0500 (Sun, 12 Mar 2006) $
+ * @since Pool 1.3
+ */
+public final class PoolUtils {
+
+    /**
+     * Timer used to periodically check pools idle object count.
+     * Because a {@link Timer} creates a {@link Thread} this is lazily instantiated.
+     */
+    private static Timer MIN_IDLE_TIMER;
+
+    /**
+     * PoolUtils instances should NOT be constructed in standard programming.
+     * Instead, the class should be used procedurally: PoolUtils.adapt(aPool);.
+     * This constructor is public to permit tools that require a JavaBean instance to operate.
+     */
+    public PoolUtils() {
+    }
+
+    /**
+     * Adapt a <code>KeyedPoolableObjectFactory</code> instance to work where a <code>PoolableObjectFactory</code> is
+     * needed. This method is the equivalent of calling
+     * {@link #adapt(KeyedPoolableObjectFactory, Object) PoolUtils.adapt(aKeyedPoolableObjectFactory, new Object())}.
+     *
+     * @param keyedFactory the {@link KeyedPoolableObjectFactory} to delegate to.
+     * @return a {@link PoolableObjectFactory} that delegates to <code>keyedFactory</code> with an internal key.
+     * @throws IllegalArgumentException when <code>keyedFactory</code> is <code>null</code>.
+     * @see #adapt(KeyedPoolableObjectFactory, Object)
+     * @since Pool 1.3
+     */
+    public static PoolableObjectFactory adapt(final KeyedPoolableObjectFactory keyedFactory) throws IllegalArgumentException {
+        return adapt(keyedFactory, new Object());
+    }
+
+    /**
+     * Adapt a <code>KeyedPoolableObjectFactory</code> instance to work where a <code>PoolableObjectFactory</code> is
+     * needed using the specified <code>key</code> when delegating.
+     *
+     * @param keyedFactory the {@link KeyedPoolableObjectFactory} to delegate to.
+     * @param key the key to use when delegating.
+     * @return a {@link PoolableObjectFactory} that delegates to <code>keyedFactory</code> with the specified key.
+     * @throws IllegalArgumentException when <code>keyedFactory</code> or <code>key</code> is <code>null</code>.
+     * @see #adapt(KeyedPoolableObjectFactory)
+     * @since Pool 1.3
+     */
+    public static PoolableObjectFactory adapt(final KeyedPoolableObjectFactory keyedFactory, final Object key) throws IllegalArgumentException {
+        return new PoolableObjectFactoryAdaptor(keyedFactory, key);
+    }
+
+    /**
+     * Adapt a <code>PoolableObjectFactory</code> instance to work where a <code>KeyedPoolableObjectFactory</code> is
+     * needed. The key is ignored.
+     *
+     * @param factory the {@link PoolableObjectFactory} to delegate to.
+     * @return a {@link KeyedPoolableObjectFactory} that delegates to <code>factory</code> ignoring the key.
+     * @throws IllegalArgumentException when <code>factory</code> is <code>null</code>.
+     * @since Pool 1.3
+     */
+    public static KeyedPoolableObjectFactory adapt(final PoolableObjectFactory factory) throws IllegalArgumentException {
+        return new KeyedPoolableObjectFactoryAdaptor(factory);
+    }
+
+    /**
+     * Adapt a <code>KeyedObjectPool</code> instance to work where an <code>ObjectPool</code> is needed. This is the
+     * equivalent of calling {@link #adapt(KeyedObjectPool, Object) PoolUtils.adapt(aKeyedObjectPool, new Object())}.
+     *
+     * @param keyedPool the {@link KeyedObjectPool} to delegate to.
+     * @return an {@link ObjectPool} that delegates to <code>keyedPool</code> with an internal key.
+     * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code>.
+     * @see #adapt(KeyedObjectPool, Object)
+     * @since Pool 1.3
+     */
+    public static ObjectPool adapt(final KeyedObjectPool keyedPool) throws IllegalArgumentException {
+        return adapt(keyedPool, new Object());
+    }
+
+    /**
+     * Adapt a <code>KeyedObjectPool</code> instance to work where an <code>ObjectPool</code> is needed using the
+     * specified <code>key</code> when delegating.
+     *
+     * @param keyedPool the {@link KeyedObjectPool} to delegate to.
+     * @param key the key to use when delegating.
+     * @return an {@link ObjectPool} that delegates to <code>keyedPool</code> with the specified key.
+     * @throws IllegalArgumentException when <code>keyedPool</code> or <code>key</code> is <code>null</code>.
+     * @see #adapt(KeyedObjectPool)
+     * @since Pool 1.3
+     */
+    public static ObjectPool adapt(final KeyedObjectPool keyedPool, final Object key) throws IllegalArgumentException {
+        return new ObjectPoolAdaptor(keyedPool, key);
+    }
+
+    /**
+     * Adapt an <code>ObjectPool</code> to work where an <code>KeyedObjectPool</code> is needed.
+     * The key is ignored.
+     *
+     * @param pool the {@link ObjectPool} to delegate to.
+     * @return a {@link KeyedObjectPool} that delegates to <code>keyedPool</code> ignoring the key.
+     * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code>.
+     * @since Pool 1.3
+     */
+    public static KeyedObjectPool adapt(final ObjectPool pool) throws IllegalArgumentException {
+        return new KeyedObjectPoolAdaptor(pool);
+    }
+
+    /**
+     * Wraps an <code>ObjectPool</code> and dynamically checks the type of objects borrowed and returned to the keyedPool.
+     * If an object is passed to the keyedPool that isn't of type <code>type</code> a {@link ClassCastException} will be thrown.
+     *
+     * @param pool the keyedPool to enforce type safety on
+     * @return an <code>ObjectPool</code> that will only allow objects of <code>type</code>
+     * @since Pool 1.3
+     */
+    public static ObjectPool checkedPool(final ObjectPool pool, final Class type) {
+        if (pool == null) {
+            throw new IllegalArgumentException("pool must not be null.");
+        }
+        if (type == null) {
+            throw new IllegalArgumentException("type must not be null.");
+        }
+        return new CheckedObjectPool(pool, type);
+    }
+
+    /**
+     * Wraps an <code>KeyedObjectPool</code> and dynamically checks the type of objects borrowed and returned to the keyedPool.
+     * If an object is passed to the keyedPool that isn't of type <code>type</code> a {@link ClassCastException} will be thrown.
+     *
+     * @param keyedPool the keyedPool to enforce type safety on
+     * @return an <code>KeyedObjectPool</code> that will only allow objects of <code>type</code>
+     * @since Pool 1.3
+     */
+    public static KeyedObjectPool checkedPool(final KeyedObjectPool keyedPool, final Class type) {
+        if (keyedPool == null) {
+            throw new IllegalArgumentException("keyedPool must not be null.");
+        }
+        if (type == null) {
+            throw new IllegalArgumentException("type must not be null.");
+        }
+        return new CheckedKeyedObjectPool(keyedPool, type);
+    }
+
+    /**
+     * Periodically check the idle object count for the keyedPool. At most one idle object will be added per period.
+     * If there is an exception when calling {@link ObjectPool#addObject()} then no more checks will be performed.
+     *
+     * @param pool the keyedPool to check periodically.
+     * @param minIdle if the {@link ObjectPool#getNumIdle()} is less than this then add an idle object.
+     * @param period the frequency to check the number of idle objects in a keyedPool, see
+     *      {@link Timer#schedule(TimerTask, long, long)}.
+     * @return the {@link TimerTask} that will periodically check the pools idle object count.
+     * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code> or
+     *      when <code>minIdle</code> is negative or when <code>period</code> isn't
+     *      valid for {@link Timer#schedule(TimerTask, long, long)}.
+     * @since Pool 1.3
+     */
+    public static TimerTask checkMinIdle(final ObjectPool pool, final int minIdle, final long period) throws IllegalArgumentException {
+        if (pool == null) {
+            throw new IllegalArgumentException("keyedPool must not be null.");
+        }
+        if (minIdle < 0) {
+            throw new IllegalArgumentException("minIdle must be non-negative.");
+        }
+        final TimerTask task = new ObjectPoolMinIdleTimerTask(pool, minIdle);
+        getMinIdleTimer().schedule(task, 0L, period);
+        return task;
+    }
+
+    /**
+     * Periodically check the idle object count for the key in the keyedPool. At most one idle object will be added per period.
+     * If there is an exception when calling {@link KeyedObjectPool#addObject(Object)} then no more checks for that key
+     * will be performed.
+     *
+     * @param keyedPool the keyedPool to check periodically.
+     * @param key the key to check the idle count of.
+     * @param minIdle if the {@link KeyedObjectPool#getNumIdle(Object)} is less than this then add an idle object.
+     * @param period the frequency to check the number of idle objects in a keyedPool, see
+     *      {@link Timer#schedule(TimerTask, long, long)}.
+     * @return the {@link TimerTask} that will periodically check the pools idle object count.
+     * @throws IllegalArgumentException when <code>keyedPool</code>, <code>key</code> is <code>null</code> or
+     *      when <code>minIdle</code> is negative or when <code>period</code> isn't
+     *      valid for {@link Timer#schedule(TimerTask, long, long)}.
+     * @since Pool 1.3
+     */
+    public static TimerTask checkMinIdle(final KeyedObjectPool keyedPool, final Object key, final int minIdle, final long period) throws IllegalArgumentException {
+        if (keyedPool == null) {
+            throw new IllegalArgumentException("keyedPool must not be null.");
+        }
+        if (key == null) {
+            throw new IllegalArgumentException("key must not be null.");
+        }
+        if (minIdle < 0) {
+            throw new IllegalArgumentException("minIdle must be non-negative.");
+        }
+        final TimerTask task = new KeyedObjectPoolMinIdleTimerTask(keyedPool, key, minIdle);
+        getMinIdleTimer().schedule(task, 0L, period);
+        return task;
+    }
+
+    /**
+     * Periodically check the idle object count for each key in the <code>Collection</code> <code>keys</code> in the keyedPool.
+     * At most one idle object will be added per period.
+     *
+     * @param keyedPool the keyedPool to check periodically.
+     * @param keys a collection of keys to check the idle object count.
+     * @param minIdle if the {@link KeyedObjectPool#getNumIdle(Object)} is less than this then add an idle object.
+     * @param period the frequency to check the number of idle objects in a keyedPool, see
+     *      {@link Timer#schedule(TimerTask, long, long)}.
+     * @return a {@link Map} of key and {@link TimerTask} pairs that will periodically check the pools idle object count.
+     * @throws IllegalArgumentException when <code>keyedPool</code>, <code>keys</code>, or any of the values in the
+     *      collection is <code>null</code> or when <code>minIdle</code> is negative or when <code>period</code> isn't
+     *      valid for {@link Timer#schedule(TimerTask, long, long)}.
+     * @see #checkMinIdle(KeyedObjectPool, Object, int, long)
+     * @since Pool 1.3
+     */
+    public static Map checkMinIdle(final KeyedObjectPool keyedPool, final Collection keys, final int minIdle, final long period) throws IllegalArgumentException {
+        if (keys == null) {
+            throw new IllegalArgumentException("keys must not be null.");
+        }
+        final Map tasks = new HashMap(keys.size());
+        final Iterator iter = keys.iterator();
+        while (iter.hasNext()) {
+            final Object key = iter.next();
+            final TimerTask task = checkMinIdle(keyedPool, key, minIdle, period);
+            tasks.put(key, task);
+        }
+        return tasks;
+    }
+
+    /**
+     * Call <code>addObject()</code> on <code>keyedPool</code> <code>count</code> number of times.
+     *
+     * @param pool the keyedPool to prefill.
+     * @param count the number of idle objects to add.
+     * @throws Exception when {@link ObjectPool#addObject()} fails.
+     * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code>.
+     * @since Pool 1.3
+     */
+    public static void prefill(final ObjectPool pool, final int count) throws Exception, IllegalArgumentException {
+        if (pool == null) {
+            throw new IllegalArgumentException("keyedPool must not be null.");
+        }
+        for (int i = 0; i < count; i++) {
+            pool.addObject();
+        }
+    }
+
+    /**
+     * Call <code>addObject(Object)</code> on <code>keyedPool</code> with <code>key</code> <code>count</code>
+     * number of times.
+     *
+     * @param keyedPool the keyedPool to prefill.
+     * @param key the key to add objects for.
+     * @param count the number of idle objects to add for <code>key</code>.
+     * @throws Exception when {@link KeyedObjectPool#addObject(Object)} fails.
+     * @throws IllegalArgumentException when <code>keyedPool</code> or <code>key</code> is <code>null</code>.
+     * @since Pool 1.3
+     */
+    public static void prefill(final KeyedObjectPool keyedPool, final Object key, final int count) throws Exception, IllegalArgumentException {
+        if (keyedPool == null) {
+            throw new IllegalArgumentException("keyedPool must not be null.");
+        }
+        if (key == null) {
+            throw new IllegalArgumentException("key must not be null.");
+        }
+        for (int i = 0; i < count; i++) {
+            keyedPool.addObject(key);
+        }
+    }
+
+    /**
+     * Call <code>addObject(Object)</code> on <code>keyedPool</code> with each key in <code>keys</code> for
+     * <code>count</code> number of times. This has the same effect as calling
+     * {@link #prefill(KeyedObjectPool, Object, int)} for each key in the <code>keys</code> collection.
+     *
+     * @param keyedPool the keyedPool to prefill.
+     * @param keys {@link Collection} of keys to add objects for.
+     * @param count the number of idle objects to add for each <code>key</code>.
+     * @throws Exception when {@link KeyedObjectPool#addObject(Object)} fails.
+     * @throws IllegalArgumentException when <code>keyedPool</code>, <code>keys</code>, or
+     *      any value in <code>keys</code> is <code>null</code>.
+     * @see #prefill(KeyedObjectPool, Object, int)
+     * @since Pool 1.3
+     */
+    public static void prefill(final KeyedObjectPool keyedPool, final Collection keys, final int count) throws Exception, IllegalArgumentException {
+        if (keys == null) {
+            throw new IllegalArgumentException("keys must not be null.");
+        }
+        final Iterator iter = keys.iterator();
+        while (iter.hasNext()) {
+            prefill(keyedPool, iter.next(), count);
+        }
+    }
+
+    /**
+     * Returns a synchronized (thread-safe) ObjectPool backed by the specified ObjectPool.
+     *
+     * @param pool the ObjectPool to be "wrapped" in a synchronized ObjectPool.
+     * @return a synchronized view of the specified ObjectPool.
+     * @since Pool 1.3
+     */
+    public static ObjectPool synchronizedPool(final ObjectPool pool) {
+        return new SynchronizedObjectPool(pool);
+    }
+
+    /**
+     * Returns a synchronized (thread-safe) KeyedObjectPool backed by the specified KeyedObjectPool.
+     * 
+     * @param keyedPool the KeyedObjectPool to be "wrapped" in a synchronized KeyedObjectPool.
+     * @return a synchronized view of the specified KeyedObjectPool.
+     * @since Pool 1.3
+     */
+    public static KeyedObjectPool synchronizedPool(final KeyedObjectPool keyedPool) {
+        return new SynchronizedKeyedObjectPool(keyedPool);
+    }
+
+    /**
+     * Returns a synchronized (thread-safe) PoolableObjectFactory backed by the specified PoolableObjectFactory.
+     *
+     * @param factory the PoolableObjectFactory to be "wrapped" in a synchronized PoolableObjectFactory.
+     * @return a synchronized view of the specified PoolableObjectFactory.
+     * @since Pool 1.3
+     */
+    public static PoolableObjectFactory synchronizedPoolableFactory(final PoolableObjectFactory factory) {
+        return new SynchronizedPoolableObjectFactory(factory);
+    }
+
+    /**
+     * Returns a synchronized (thread-safe) KeyedPoolableObjectFactory backed by the specified KeyedPoolableObjectFactory.
+     *
+     * @param keyedFactory the KeyedPoolableObjectFactory to be "wrapped" in a synchronized KeyedPoolableObjectFactory.
+     * @return a synchronized view of the specified KeyedPoolableObjectFactory.
+     * @since Pool 1.3
+     */
+    public static KeyedPoolableObjectFactory synchronizedPoolableFactory(final KeyedPoolableObjectFactory keyedFactory) {
+        return new SynchronizedKeyedPoolableObjectFactory(keyedFactory);
+    }
+
+    /**
+     * Get the <code>Timer</code> for checking keyedPool's idle count. Lazily create the {@link Timer} as needed.
+     *
+     * @return the {@link Timer} for checking keyedPool's idle count.
+     * @since Pool 1.3
+     */
+    private static synchronized Timer getMinIdleTimer() {
+        if (MIN_IDLE_TIMER == null) {
+            MIN_IDLE_TIMER = new Timer(true);
+        }
+        return MIN_IDLE_TIMER;
+    }
+
+    private static class PoolableObjectFactoryAdaptor implements PoolableObjectFactory {
+        private final Object key;
+        private final KeyedPoolableObjectFactory keyedFactory;
+
+        PoolableObjectFactoryAdaptor(final KeyedPoolableObjectFactory keyedFactory, final Object key) throws IllegalArgumentException {
+            if (keyedFactory == null) {
+                throw new IllegalArgumentException("keyedFactory must not be null.");
+            }
+            if (key == null) {
+                throw new IllegalArgumentException("key must not be null.");
+            }
+            this.keyedFactory = keyedFactory;
+            this.key = key;
+        }
+
+        public Object makeObject() throws Exception {
+            return keyedFactory.makeObject(key);
+        }
+
+        public void destroyObject(final Object obj) throws Exception {
+            keyedFactory.destroyObject(key, obj);
+        }
+
+        public boolean validateObject(final Object obj) {
+            return keyedFactory.validateObject(key, obj);
+        }
+
+        public void activateObject(final Object obj) throws Exception {
+            keyedFactory.activateObject(key, obj);
+        }
+
+        public void passivateObject(final Object obj) throws Exception {
+            keyedFactory.passivateObject(key, obj);
+        }
+
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+            sb.append("PoolableObjectFactoryAdaptor");
+            sb.append("{key=").append(key);
+            sb.append(", keyedFactory=").append(keyedFactory);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    private static class KeyedPoolableObjectFactoryAdaptor implements KeyedPoolableObjectFactory {
+        private final PoolableObjectFactory factory;
+
+        KeyedPoolableObjectFactoryAdaptor(final PoolableObjectFactory factory) throws IllegalArgumentException {
+            if (factory == null) {
+                throw new IllegalArgumentException("factory must not be null.");
+            }
+            this.factory = factory;
+        }
+
+        public Object makeObject(final Object key) throws Exception {
+            return factory.makeObject();
+        }
+
+        public void destroyObject(final Object key, final Object obj) throws Exception {
+            factory.destroyObject(obj);
+        }
+
+        public boolean validateObject(final Object key, final Object obj) {
+            return factory.validateObject(obj);
+        }
+
+        public void activateObject(final Object key, final Object obj) throws Exception {
+            factory.activateObject(obj);
+        }
+
+        public void passivateObject(final Object key, final Object obj) throws Exception {
+            factory.passivateObject(obj);
+        }
+
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+            sb.append("KeyedPoolableObjectFactoryAdaptor");
+            sb.append("{factory=").append(factory);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    private static class ObjectPoolAdaptor implements ObjectPool {
+        private final Object key;
+        private final KeyedObjectPool keyedPool;
+
+        ObjectPoolAdaptor(final KeyedObjectPool keyedPool, final Object key) throws IllegalArgumentException {
+            if (keyedPool == null) {
+                throw new IllegalArgumentException("keyedPool must not be null.");
+            }
+            if (key == null) {
+                throw new IllegalArgumentException("key must not be null.");
+            }
+            this.keyedPool = keyedPool;
+            this.key = key;
+        }
+
+        public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
+            return keyedPool.borrowObject(key);
+        }
+
+        public void returnObject(final Object obj) throws Exception {
+            keyedPool.returnObject(key, obj);
+        }
+
+        public void invalidateObject(final Object obj) throws Exception {
+            keyedPool.invalidateObject(key, obj);
+        }
+
+        public void addObject() throws Exception, IllegalStateException {
+            keyedPool.addObject(key);
+        }
+
+        public int getNumIdle() throws UnsupportedOperationException {
+            return keyedPool.getNumIdle(key);
+        }
+
+        public int getNumActive() throws UnsupportedOperationException {
+            return keyedPool.getNumActive(key);
+        }
+
+        public void clear() throws Exception, UnsupportedOperationException {
+            keyedPool.clear();
+        }
+
+        public void close() throws Exception {
+            keyedPool.close();
+        }
+
+        public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
+            keyedPool.setFactory(adapt(factory));
+        }
+
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+            sb.append("ObjectPoolAdaptor");
+            sb.append("{key=").append(key);
+            sb.append(", keyedPool=").append(keyedPool);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    private static class KeyedObjectPoolAdaptor implements KeyedObjectPool {
+        private final ObjectPool pool;
+
+        KeyedObjectPoolAdaptor(final ObjectPool pool) throws IllegalArgumentException {
+            if (pool == null) {
+                throw new IllegalArgumentException("keyedPool must not be null.");
+            }
+            this.pool = pool;
+        }
+
+        public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException {
+            return pool.borrowObject();
+        }
+
+        public void returnObject(final Object key, final Object obj) throws Exception {
+            pool.returnObject(obj);
+        }
+
+        public void invalidateObject(final Object key, final Object obj) throws Exception {
+            pool.invalidateObject(obj);
+        }
+
+        public void addObject(final Object key) throws Exception, IllegalStateException {
+            pool.addObject();
+        }
+
+        public int getNumIdle(final Object key) throws UnsupportedOperationException {
+            return pool.getNumIdle();
+        }
+
+        public int getNumActive(final Object key) throws UnsupportedOperationException {
+            return pool.getNumActive();
+        }
+
+        public int getNumIdle() throws UnsupportedOperationException {
+            return pool.getNumIdle();
+        }
+
+        public int getNumActive() throws UnsupportedOperationException {
+            return pool.getNumActive();
+        }
+
+        public void clear() throws Exception, UnsupportedOperationException {
+            pool.clear();
+        }
+
+        public void clear(final Object key) throws Exception, UnsupportedOperationException {
+            pool.clear();
+        }
+
+        public void close() throws Exception {
+            pool.close();
+        }
+
+        public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
+            pool.setFactory(adapt(factory));
+        }
+
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+            sb.append("KeyedObjectPoolAdaptor");
+            sb.append("{keyedPool=").append(pool);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    private static class CheckedObjectPool implements ObjectPool {
+        private final Class type;
+        private final ObjectPool pool;
+
+        CheckedObjectPool(final ObjectPool pool, final Class type) {
+            if (pool == null) {
+                throw new IllegalArgumentException("pool must not be null.");
+            }
+            if (type == null) {
+                throw new IllegalArgumentException("type must not be null.");
+            }
+            this.pool = pool;
+            this.type = type;
+        }
+
+        public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
+            final Object obj = pool.borrowObject();
+            if (type.isInstance(obj)) {
+                return obj;
+            } else {
+                throw new ClassCastException("Borrowed object is not of type: " + type.getName() + " was: " + obj);
+            }
+        }
+
+        public void returnObject(final Object obj) throws Exception {
+            if (type.isInstance(obj)) {
+                pool.returnObject(obj);
+            } else {
+                throw new ClassCastException("Returned object is not of type: " + type.getName() + " was: " + obj);
+            }
+        }
+
+        public void invalidateObject(final Object obj) throws Exception {
+            if (type.isInstance(obj)) {
+                pool.invalidateObject(obj);
+            } else {
+                throw new ClassCastException("Invalidated object is not of type: " + type.getName() + " was: " + obj);
+            }
+        }
+
+        public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {
+            pool.addObject();
+        }
+
+        public int getNumIdle() throws UnsupportedOperationException {
+            return pool.getNumIdle();
+        }
+
+        public int getNumActive() throws UnsupportedOperationException {
+            return pool.getNumActive();
+        }
+
+        public void clear() throws Exception, UnsupportedOperationException {
+            pool.clear();
+        }
+
+        public void close() throws Exception {
+            pool.close();
+        }
+
+        public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
+            pool.setFactory(factory);
+        }
+
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+            sb.append("CheckedObjectPool");
+            sb.append("{type=").append(type);
+            sb.append(", keyedPool=").append(pool);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    private static class CheckedKeyedObjectPool implements KeyedObjectPool {
+        private final Class type;
+        private final KeyedObjectPool keyedPool;
+
+        CheckedKeyedObjectPool(final KeyedObjectPool keyedPool, final Class type) {
+            if (keyedPool == null) {
+                throw new IllegalArgumentException("keyedPool must not be null.");
+            }
+            if (type == null) {
+                throw new IllegalArgumentException("type must not be null.");
+            }
+            this.keyedPool = keyedPool;
+            this.type = type;
+        }
+
+        public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException {
+            Object obj = keyedPool.borrowObject(key);
+            if (type.isInstance(obj)) {
+                return obj;
+            } else {
+                throw new ClassCastException("Borrowed object for key: " + key + " is not of type: " + type.getName() + " was: " + obj);
+            }
+        }
+
+        public void returnObject(final Object key, final Object obj) throws Exception {
+            if (type.isInstance(obj)) {
+                keyedPool.returnObject(key, obj);
+            } else {
+                throw new ClassCastException("Returned object for key: " + key + " is not of type: " + type.getName() + " was: " + obj);
+            }
+        }
+
+        public void invalidateObject(final Object key, final Object obj) throws Exception {
+            if (type.isInstance(obj)) {
+                keyedPool.invalidateObject(key, obj);
+            } else {
+                throw new ClassCastException("Invalidated object for key: " + key + " is not of type: " + type.getName() + " was: " + obj);
+            }
+        }
+
+        public void addObject(final Object key) throws Exception, IllegalStateException, UnsupportedOperationException {
+            keyedPool.addObject(key);
+        }
+
+        public int getNumIdle(final Object key) throws UnsupportedOperationException {
+            return keyedPool.getNumIdle(key);
+        }
+
+        public int getNumActive(final Object key) throws UnsupportedOperationException {
+            return keyedPool.getNumActive(key);
+        }
+
+        public int getNumIdle() throws UnsupportedOperationException {
+            return keyedPool.getNumIdle();
+        }
+
+        public int getNumActive() throws UnsupportedOperationException {
+            return keyedPool.getNumActive();
+        }
+
+        public void clear() throws Exception, UnsupportedOperationException {
+            keyedPool.clear();
+        }
+
+        public void clear(final Object key) throws Exception, UnsupportedOperationException {
+            keyedPool.clear(key);
+        }
+
+        public void close() throws Exception {
+            keyedPool.close();
+        }
+
+        public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
+            keyedPool.setFactory(factory);
+        }
+
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+            sb.append("CheckedKeyedObjectPool");
+            sb.append("{type=").append(type);
+            sb.append(", keyedPool=").append(keyedPool);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    private static class ObjectPoolMinIdleTimerTask extends TimerTask {
+        private final int minIdle;
+        private final ObjectPool pool;
+
+        ObjectPoolMinIdleTimerTask(final ObjectPool pool, final int minIdle) throws IllegalArgumentException {
+            if (pool == null) {
+                throw new IllegalArgumentException("poll must not be null.");
+            }
+            this.pool = pool;
+            this.minIdle = minIdle;
+        }
+
+        public void run() {
+            boolean success = false;
+            try {
+                if (pool.getNumIdle() < minIdle) {
+                    pool.addObject();
+                }
+                success = true;
+
+            } catch (Exception e) {
+                cancel();
+
+            } finally {
+                // detect other types of Throwable and cancel this Timer
+                if (!success) {
+                    cancel();
+                }
+            }
+        }
+
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+            sb.append("ObjectPoolMinIdleTimerTask");
+            sb.append("{minIdle=").append(minIdle);
+            sb.append(", keyedPool=").append(pool);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    private static class KeyedObjectPoolMinIdleTimerTask extends TimerTask {
+        private final int minIdle;
+        private final Object key;
+        private final KeyedObjectPool pool;
+
+        KeyedObjectPoolMinIdleTimerTask(final KeyedObjectPool pool, final Object key, final int minIdle) throws IllegalArgumentException {
+            if (pool == null) {
+                throw new IllegalArgumentException("keyedPool must not be null.");
+            }
+            this.pool = pool;
+            this.key = key;
+            this.minIdle = minIdle;
+        }
+
+        public void run() {
+            boolean success = false;
+            try {
+                if (pool.getNumIdle(key) < minIdle) {
+                    pool.addObject(key);
+                }
+                success = true;
+
+            } catch (Exception e) {
+                cancel();
+
+            } finally {
+                // detect other types of Throwable and cancel this Timer
+                if (!success) {
+                    cancel();
+                }
+            }
+        }
+
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+            sb.append("KeyedObjectPoolMinIdleTimerTask");
+            sb.append("{minIdle=").append(minIdle);
+            sb.append(", key=").append(key);
+            sb.append(", keyedPool=").append(pool);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    private static class SynchronizedObjectPool implements ObjectPool {
+        private final Object lock;
+        private final ObjectPool pool;
+
+        SynchronizedObjectPool(final ObjectPool pool) throws IllegalArgumentException {
+            if (pool == null) {
+                throw new IllegalArgumentException("keyedPool must not be null.");
+            }
+            this.pool = pool;
+            lock = new Object();
+        }
+
+        public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
+            synchronized (lock) {
+                return pool.borrowObject();
+            }
+        }
+
+        public void returnObject(final Object obj) throws Exception {
+            synchronized (lock) {
+                pool.returnObject(obj);
+            }
+        }
+
+        public void invalidateObject(final Object obj) throws Exception {
+            synchronized (lock) {
+                pool.invalidateObject(obj);
+            }
+        }
+
+        public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {
+            synchronized (lock) {
+                pool.addObject();
+            }
+        }
+
+        public int getNumIdle() throws UnsupportedOperationException {
+            synchronized (lock) {
+                return pool.getNumIdle();
+            }
+        }
+
+        public int getNumActive() throws UnsupportedOperationException {
+            synchronized (lock) {
+                return pool.getNumActive();
+            }
+        }
+
+        public void clear() throws Exception, UnsupportedOperationException {
+            synchronized (lock) {
+                pool.clear();
+            }
+        }
+
+        public void close() throws Exception {
+            synchronized (lock) {
+                pool.close();
+            }
+        }
+
+        public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
+            synchronized (lock) {
+                pool.setFactory(factory);
+            }
+        }
+
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+            sb.append("SynchronizedObjectPool");
+            sb.append("{keyedPool=").append(pool);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    private static class SynchronizedKeyedObjectPool implements KeyedObjectPool {
+        private final Object lock;
+        private final KeyedObjectPool keyedPool;
+
+        SynchronizedKeyedObjectPool(final KeyedObjectPool keyedPool) throws IllegalArgumentException {
+            if (keyedPool == null) {
+                throw new IllegalArgumentException("keyedPool must not be null.");
+            }
+            this.keyedPool = keyedPool;
+            lock = new Object();
+        }
+
+        public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException {
+            synchronized (lock) {
+                return keyedPool.borrowObject(key);
+            }
+        }
+
+        public void returnObject(final Object key, final Object obj) throws Exception {
+            synchronized (lock) {
+                keyedPool.returnObject(key, obj);
+            }
+        }
+
+        public void invalidateObject(final Object key, final Object obj) throws Exception {
+            synchronized (lock) {
+                keyedPool.invalidateObject(key, obj);
+            }
+        }
+
+        public void addObject(final Object key) throws Exception, IllegalStateException, UnsupportedOperationException {
+            synchronized (lock) {
+                keyedPool.addObject(key);
+            }
+        }
+
+        public int getNumIdle(final Object key) throws UnsupportedOperationException {
+            synchronized (lock) {
+                return keyedPool.getNumIdle(key);
+            }
+        }
+
+        public int getNumActive(final Object key) throws UnsupportedOperationException {
+            synchronized (lock) {
+                return keyedPool.getNumActive(key);
+            }
+        }
+
+        public int getNumIdle() throws UnsupportedOperationException {
+            synchronized (lock) {
+                return keyedPool.getNumIdle();
+            }
+        }
+
+        public int getNumActive() throws UnsupportedOperationException {
+            synchronized (lock) {
+                return keyedPool.getNumActive();
+            }
+        }
+
+        public void clear() throws Exception, UnsupportedOperationException {
+            synchronized (lock) {
+                keyedPool.clear();
+            }
+        }
+
+        public void clear(final Object key) throws Exception, UnsupportedOperationException {
+            synchronized (lock) {
+                keyedPool.clear(key);
+            }
+        }
+
+        public void close() throws Exception {
+            synchronized (lock) {
+                keyedPool.close();
+            }
+        }
+
+        public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
+            synchronized (lock) {
+                keyedPool.setFactory(factory);
+            }
+        }
+
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+            sb.append("SynchronizedKeyedObjectPool");
+            sb.append("{keyedPool=").append(keyedPool);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    private static class SynchronizedPoolableObjectFactory implements PoolableObjectFactory {
+        private final Object lock;
+        private final PoolableObjectFactory factory;
+
+        SynchronizedPoolableObjectFactory(final PoolableObjectFactory factory) throws IllegalArgumentException {
+            if (factory == null) {
+                throw new IllegalArgumentException("factory must not be null.");
+            }
+            this.factory = factory;
+            lock = new Object();
+        }
+
+        public Object makeObject() throws Exception {
+            synchronized (lock) {
+                return factory.makeObject();
+            }
+        }
+
+        public void destroyObject(final Object obj) throws Exception {
+            synchronized (lock) {
+                factory.destroyObject(obj);
+            }
+        }
+
+        public boolean validateObject(final Object obj) {
+            synchronized (lock) {
+                return factory.validateObject(obj);
+            }
+        }
+
+        public void activateObject(final Object obj) throws Exception {
+            synchronized (lock) {
+                factory.activateObject(obj);
+            }
+        }
+
+        public void passivateObject(final Object obj) throws Exception {
+            synchronized (lock) {
+                factory.passivateObject(obj);
+            }
+        }
+
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+            sb.append("SynchronizedPoolableObjectFactory");
+            sb.append("{factory=").append(factory);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+    private static class SynchronizedKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory {
+        private final Object lock;
+        private final KeyedPoolableObjectFactory keyedFactory;
+
+        SynchronizedKeyedPoolableObjectFactory(final KeyedPoolableObjectFactory keyedFactory) throws IllegalArgumentException {
+            if (keyedFactory == null) {
+                throw new IllegalArgumentException("keyedFactory must not be null.");
+            }
+            this.keyedFactory = keyedFactory;
+            lock = new Object();
+        }
+
+        public Object makeObject(final Object key) throws Exception {
+            synchronized (lock) {
+                return keyedFactory.makeObject(key);
+            }
+        }
+
+        public void destroyObject(final Object key, final Object obj) throws Exception {
+            synchronized (lock) {
+                keyedFactory.destroyObject(key, obj);
+            }
+        }
+
+        public boolean validateObject(final Object key, final Object obj) {
+            synchronized (lock) {
+                return keyedFactory.validateObject(key, obj);
+            }
+        }
+
+        public void activateObject(final Object key, final Object obj) throws Exception {
+            synchronized (lock) {
+                keyedFactory.activateObject(key, obj);
+            }
+        }
+
+        public void passivateObject(final Object key, final Object obj) throws Exception {
+            synchronized (lock) {
+                keyedFactory.passivateObject(key, obj);
+            }
+        }
+
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+            sb.append("SynchronizedKeyedPoolableObjectFactory");
+            sb.append("{keyedFactory=").append(keyedFactory);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+}
\ No newline at end of file

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/PoolableObjectFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/PoolableObjectFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/PoolableObjectFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,95 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+/**
+ * An interface defining life-cycle methods for
+ * instances to be used in an
+ * {@link ObjectPool ObjectPool}.
+ * <p>
+ * By contract, when an {@link ObjectPool ObjectPool}
+ * delegates to a <tt>PoolableObjectFactory</tt>,
+ * <ol>
+ *  <li>
+ *   {@link #makeObject makeObject} 
+ *   is called  whenever a new instance is needed.
+ *  </li>
+ *  <li>
+ *   {@link #activateObject activateObject} 
+ *   is invoked on every instance before it is returned from the
+ *   pool.
+ *  </li>
+ *  <li>
+ *   {@link #passivateObject passivateObject} 
+ *   is invoked on every instance when it is returned to the
+ *   pool.
+ *  </li>
+ *  <li>
+ *   {@link #destroyObject destroyObject} 
+ *   is invoked on every instance when it is being "dropped" from the
+ *   pool (whether due to the response from
+ *   {@link #validateObject validateObject}, or
+ *   for reasons specific to the pool implementation.)
+ *  </li>
+ *  <li>
+ *   {@link #validateObject validateObject} 
+ *   is invoked in an implementation-specific fashion to determine if an instance
+ *   is still valid to be returned by the pool.
+ *   It will only be invoked on an {@link #activateObject "activated"}
+ *   instance.
+ *  </li>
+ * </ol>
+ *
+ * @see ObjectPool
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ */
+public interface PoolableObjectFactory {
+  /**
+   * Creates an instance that can be returned by the pool.
+   * @return an instance that can be returned by the pool.
+   */
+  Object makeObject() throws Exception;
+
+  /**
+   * Destroys an instance no longer needed by the pool.
+   * @param obj the instance to be destroyed
+   */
+  void destroyObject(Object obj) throws Exception;
+
+  /**
+   * Ensures that the instance is safe to be returned by the pool.
+   * Returns <tt>false</tt> if this object should be destroyed.
+   * @param obj the instance 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.
+   */
+  boolean validateObject(Object obj);
+
+  /**
+   * Reinitialize an instance to be returned by the pool.
+   * @param obj the instance to be activated
+   */
+  void activateObject(Object obj) throws Exception;
+
+  /**
+   * Uninitialize an instance to be returned to the pool.
+   * @param obj the instance to be passivated
+   */
+  void passivateObject(Object obj) throws Exception;
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,1552 @@
+/*
+ * Copyright 1999-2004,2006 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.LinkedList;
+import java.util.HashSet;
+import java.util.TimerTask;
+
+import org.apache.commons.pool.BaseKeyedObjectPool;
+import org.apache.commons.pool.KeyedObjectPool;
+import org.apache.commons.pool.KeyedPoolableObjectFactory;
+
+/**
+ * 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 negative, 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 KeyedPoolableObjectFactory#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 KeyedPoolableObjectFactory#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 KeyedPoolableObjectFactory#validateObject} method.  Objects
+ *   that fail to validate will be dropped from the pool.
+ *  </li>
+ * </ul>
+ * <p>
+ * GenericKeyedObjectPool is not usable without a {@link KeyedPoolableObjectFactory}.  A
+ * non-<code>null</code> factory must be provided either as a constructor argument
+ * or via a call to {@link #setFactory} before the pool is used.
+ * </p>
+ * @see GenericObjectPool
+ * @author Rodney Waldhoff
+ * @author Dirk Verbeeck
+ * @version $Revision: 386116 $ $Date: 2006-03-15 12:15:58 -0500 (Wed, 15 Mar 2006) $
+ */
+public class GenericKeyedObjectPool extends BaseKeyedObjectPool 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 cap on the the maximum number of objects that can exists at one time.
+     * @see #getMaxTotal
+     * @see #setMaxTotal
+     */
+    public static final int DEFAULT_MAX_TOTAL  = -1;
+
+    /**
+     * 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;
+
+    /**
+     * The default minimum level of idle objects in the pool.
+     * @see #setMinIdle
+     * @see #getMinIdle
+     */
+    public static final int DEFAULT_MIN_IDLE = 0;
+    
+    //--- constructors -----------------------------------------------
+
+    /**
+     * Create a new <tt>GenericKeyedObjectPool</tt>..
+     */
+    public GenericKeyedObjectPool() {
+        this(null,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
+     */
+    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.maxTotal,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) {
+        this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
+    }
+
+    /**
+     * 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 maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal})
+     * @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, int maxTotal, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
+        this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, GenericKeyedObjectPool.DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
+    }
+    
+    /**
+     * 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 maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal})
+     * @param minIdle the minimum number of idle objects to have in the pool at any one time (see {@link #setMinIdle})
+     * @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, int maxTotal, int minIdle, 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;
+        _maxTotal = maxTotal;
+        _minIdle = minIdle;
+        _testOnBorrow = testOnBorrow;
+        _testOnReturn = testOnReturn;
+        _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+        _numTestsPerEvictionRun = numTestsPerEvictionRun;
+        _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+        _testWhileIdle = testWhileIdle;
+
+        _poolMap = new HashMap();
+        _activeMap = new HashMap();
+
+        startEvictor(_timeBetweenEvictionRunsMillis);
+    }
+
+    //--- public methods ---------------------------------------------
+
+    //--- configuration methods --------------------------------------
+
+    /**
+     * Returns the cap on the number of active instances from my pool (per key).
+     * @return the cap on the number of active instances from my pool (per key).
+     * @see #setMaxActive
+     */
+    public synchronized int getMaxActive() {
+        return _maxActive;
+    }
+
+    /**
+     * Sets the cap on the number of active instances from my pool (per key).
+     * @param maxActive The cap on the number of active instances from my pool (per key).
+     *                  Use a negative value for an infinite number of instances.
+     * @see #getMaxActive
+     */
+    public synchronized void setMaxActive(int maxActive) {
+        _maxActive = maxActive;
+        notifyAll();
+    }
+
+    /**
+     * Returns the cap on the total number of instances from my pool if non-positive.
+     * @return the cap on the total number of instances from my pool if non-positive.
+     * @see #setMaxTotal
+     */
+    public synchronized int getMaxTotal() {
+        return _maxTotal;
+    }
+
+    /**
+     * Sets the cap on the total number of instances from my pool if non-positive.
+     * @param maxTotal The cap on the total number of instances from my pool.
+     *                  Use a non-positive value for an infinite number of instances.
+     * @see #getMaxTotal
+     */
+    public synchronized void setMaxTotal(int maxTotal) {
+        _maxTotal = maxTotal;
+        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 synchronized 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 synchronized 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 synchronized void setMaxIdle(int maxIdle) {
+        _maxIdle = maxIdle;
+        notifyAll();
+    }
+
+    /**
+     * Sets the minimum number of idle objects in pool to maintain (per key)
+     * @param poolSize - The minimum size of the pool
+     * @see #getMinIdle
+     */
+    public synchronized void setMinIdle(int poolSize) {
+        _minIdle = poolSize;
+    }
+
+    /**
+     * Returns the minimum number of idle objects in pool to maintain (per key)
+     * @return the minimum number of idle objects in pool to maintain (per key)
+     * @see #setMinIdle
+     */
+    public synchronized int getMinIdle() {
+        return _minIdle;
+    }
+
+    /**
+     * When <tt>true</tt>, objects will be
+     * {@link org.apache.commons.pool.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 synchronized boolean getTestOnBorrow() {
+        return _testOnBorrow;
+    }
+
+    /**
+     * When <tt>true</tt>, objects will be
+     * {@link org.apache.commons.pool.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 synchronized void setTestOnBorrow(boolean testOnBorrow) {
+        _testOnBorrow = testOnBorrow;
+    }
+
+    /**
+     * When <tt>true</tt>, objects will be
+     * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
+     * before being returned to the pool within the
+     * {@link #returnObject}.
+     *
+     * @see #setTestOnReturn
+     */
+    public synchronized boolean getTestOnReturn() {
+        return _testOnReturn;
+    }
+
+    /**
+     * When <tt>true</tt>, objects will be
+     * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
+     * before being returned to the pool within the
+     * {@link #returnObject}.
+     *
+     * @see #getTestOnReturn
+     */
+    public synchronized 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) {
+        _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+        startEvictor(_timeBetweenEvictionRunsMillis);
+    }
+
+    /**
+     * Returns the number of objects to examine during each run of the
+     * idle object evictor thread (if any).
+     *
+     * @see #setNumTestsPerEvictionRun
+     * @see #setTimeBetweenEvictionRunsMillis
+     */
+    public synchronized 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 #getNumIdle})/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 synchronized 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 org.apache.commons.pool.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 synchronized boolean getTestWhileIdle() {
+        return _testWhileIdle;
+    }
+
+    /**
+     * When <tt>true</tt>, objects will be
+     * {@link org.apache.commons.pool.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 synchronized 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);
+        setMaxTotal(conf.maxTotal);
+        setMinIdle(conf.minIdle);
+        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) throws Exception {
+        long starttime = System.currentTimeMillis();
+        boolean newlyCreated = false;
+        for(;;) {
+            LinkedList pool = (LinkedList)(_poolMap.get(key));
+            if(null == pool) {
+                pool = new LinkedList();
+                _poolMap.put(key,pool);
+            }
+            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) {
+                // if there is a totalMaxActive and we are at the limit then
+                // we have to make room
+                if ((_maxTotal > 0) && (_totalActive + _totalIdle >= _maxTotal)) {
+                    clearOldest();
+                }
+
+                // check if we can create one
+                // (note we know that the num sleeping is 0, else we wouldn't be here)
+                int active = getActiveCount(key);
+                if ((_maxActive < 0 || active < _maxActive) &&
+                    (_maxTotal < 0 || _totalActive + _totalIdle < _maxTotal)) {
+                    Object obj = _factory.makeObject(key);
+                    pair = new ObjectTimestampPair(obj);
+                    newlyCreated = true;
+                } 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 {
+                                    // this code may be executed again after a notify then continue cycle
+                                    // so, need to calculate the amount of time to wait
+                                    final long elapsed = (System.currentTimeMillis() - starttime);
+                                    final long waitTime = _maxWait - elapsed;
+                                    if (waitTime > 0)
+                                    {
+                                        wait(waitTime);
+                                    }
+                                }
+                            } 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)) {
+                _factory.destroyObject(key,pair.value);
+                if(newlyCreated) {
+                    throw new NoSuchElementException("Could not create a validated object");
+                } // else keep looping
+            } else {
+                incrementActiveCount(key);
+                return pair.value;
+            }
+        }
+    }
+
+    public synchronized void clear() {
+        for(Iterator keyiter = _poolMap.keySet().iterator(); keyiter.hasNext(); ) {
+            Object key = keyiter.next();
+            final LinkedList list = (LinkedList)(_poolMap.get(key));
+            for(Iterator it = list.iterator(); it.hasNext(); ) {
+                try {
+                    _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
+                } catch(Exception e) {
+                    // ignore error, keep destroying the rest
+                }
+                it.remove();
+            }
+        }
+        _poolMap.clear();
+        if (_recentlyEvictedKeys != null) {
+            _recentlyEvictedKeys.clear();
+        }
+        _totalIdle = 0;
+        notifyAll();
+    }
+
+    /**
+     * Method clears oldest 15% of objects in pool.  The method sorts the
+     * objects into a TreeMap and then iterates the first 15% for removal
+     */
+    public synchronized void clearOldest() {
+        // build sorted map of idle objects
+        TreeMap map = new TreeMap();
+        for (Iterator keyiter = _poolMap.keySet().iterator(); keyiter.hasNext();) {
+            Object key = keyiter.next();
+            LinkedList list = (LinkedList) _poolMap.get(key);
+            for (Iterator it = list.iterator(); it.hasNext();) {
+                // each item into the map uses the objectimestamppair object
+                // as the key.  It then gets sorted based on the timstamp field
+                // each value in the map is the parent list it belongs in.
+                ObjectTimestampPair pair = (ObjectTimestampPair) it.next();
+                map.put(pair, key);
+            }
+        }
+
+        // Now iterate created map and kill the first 15% plus one to account for zero
+        Set setPairKeys = map.entrySet();
+        int itemsToRemove = ((int) (map.size() * 0.15)) + 1;
+
+        Iterator iter = setPairKeys.iterator();
+        while (iter.hasNext() && itemsToRemove > 0) {
+            Map.Entry entry = (Map.Entry) iter.next();
+            // kind of backwards on naming.  In the map, each key is the objecttimestamppair
+            // because it has the ordering with the timestamp value.  Each value that the
+            // key references is the key of the list it belongs to.
+            Object key = entry.getValue();
+            ObjectTimestampPair pairTimeStamp = (ObjectTimestampPair) entry.getKey();
+            LinkedList list = (LinkedList) _poolMap.get(key);
+            list.remove(pairTimeStamp);
+
+            try {
+                _factory.destroyObject(key, pairTimeStamp.value);
+            } catch (Exception e) {
+                // ignore error, keep destroying the rest
+            }
+            // if that was the last object for that key, drop that pool
+            if (list.isEmpty()) {
+                _poolMap.remove(key);
+            }
+            _totalIdle--;
+            itemsToRemove--;
+        }
+        notifyAll();
+    }
+
+    public synchronized void clear(Object key) {
+        LinkedList pool = (LinkedList)(_poolMap.remove(key));
+        if(null == pool) {
+            return;
+        } else {
+            for(Iterator it = pool.iterator(); it.hasNext(); ) {
+                try {
+                    _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
+                } catch(Exception e) {
+                    // ignore error, keep destroying the rest
+                }
+                it.remove();
+                _totalIdle--;
+            }
+        }
+        notifyAll();
+    }
+
+    public synchronized int getNumActive() {
+        return _totalActive;
+    }
+
+    public synchronized int getNumIdle() {
+        return _totalIdle;
+    }
+
+    public synchronized int getNumActive(Object key) {
+        return getActiveCount(key);
+    }
+
+    public synchronized int getNumIdle(Object key) {
+        try {
+            return((LinkedList)(_poolMap.get(key))).size();
+        } catch(Exception e) {
+            return 0;
+        }
+    }
+
+    public synchronized void returnObject(Object key, Object obj) throws Exception {
+
+        // if we need to validate this object, do so
+        boolean success = true; // whether or not this object passed validation
+        if(_testOnReturn && !_factory.validateObject(key, obj)) {
+            success = false;
+            try {
+                _factory.destroyObject(key, obj);
+            } catch(Exception e) {
+                // ignored
+            }
+        } else {
+            try {
+                _factory.passivateObject(key, obj);
+            } catch(Exception e) {
+                success = false;
+            }
+        }
+
+        boolean shouldDestroy = false;
+        // grab the pool (list) of objects associated with the given key
+        LinkedList pool = (LinkedList) (_poolMap.get(key));
+        // if it doesn't exist, create it
+        if(null == pool) {
+            pool = new LinkedList();
+            _poolMap.put(key, pool);
+        }
+        decrementActiveCount(key);
+        // if there's no space in the pool, flag the object for destruction
+        // else if we passivated succesfully, return it to the pool
+        if(_maxIdle >= 0 && (pool.size() >= _maxIdle)) {
+            shouldDestroy = true;
+        } else if(success) {
+            pool.addLast(new ObjectTimestampPair(obj));
+            _totalIdle++;
+        }
+        notifyAll();
+
+        if(shouldDestroy) {
+            try {
+                _factory.destroyObject(key, obj);
+            } catch(Exception e) {
+                // ignored?
+            }
+        }
+    }
+
+    public synchronized void invalidateObject(Object key, Object obj) throws Exception {
+        try {
+            _factory.destroyObject(key, obj);
+        }
+        finally {
+            decrementActiveCount(key);
+            notifyAll(); // _totalActive has changed
+        }
+    }
+
+    public synchronized void addObject(Object key) throws Exception {
+        Object obj = _factory.makeObject(key);
+        incrementActiveCount(key); // returnObject will decrement this
+        returnObject(key,obj);
+    }
+
+    /**
+     * Registers a key for pool control.
+     *
+     * If <i>populateImmediately</i> is <code>true</code>, the pool will immediately commence
+     * a sustain cycle. If <i>populateImmediately</i> is <code>false</code>, the pool will be
+     * populated when the next schedules sustain task is run.
+     *
+     * @param key - The key to register for pool control.
+     * @param populateImmediately - If this is <code>true</code>, the pool
+     * will start a sustain cycle immediately.
+     */
+    public synchronized void preparePool(Object key, boolean populateImmediately) {
+        LinkedList pool = (LinkedList)(_poolMap.get(key));
+        if (null == pool) {
+            pool = new LinkedList();
+            _poolMap.put(key,pool);
+        }
+
+        if (populateImmediately) {
+            try {
+                // Create the pooled objects
+                ensureMinIdle(key);
+            }
+            catch (Exception e) {
+                //Do nothing
+            }
+        }
+    }
+
+    public synchronized void close() throws Exception {
+        clear();
+        _poolMap = null;
+        _activeMap = null;
+        _recentlyEvictedKeys = null;
+        if(null != _evictor) {
+            _evictor.cancel();
+            _evictor = null;
+        }
+    }
+
+    public synchronized void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException {
+        if(0 < getNumActive()) {
+            throw new IllegalStateException("Objects are already active");
+        } else {
+            clear();
+            _factory = factory;
+        }
+    }
+
+    public synchronized void evict() throws Exception {
+        Object key = null;
+        if (_recentlyEvictedKeys == null) {
+            _recentlyEvictedKeys = new HashSet(_poolMap.size());
+        }
+        Set remainingKeys = new HashSet(_poolMap.keySet());
+        remainingKeys.removeAll(_recentlyEvictedKeys);
+        Iterator keyIter = remainingKeys.iterator();
+
+        ListIterator objIter = null;
+
+        for(int i=0,m=getNumTests();i<m;i++) {
+            if(_poolMap.size() > 0) {
+                // Find next idle object pool key to work on
+                if (key == null) {
+                    if (!keyIter.hasNext()) {
+                        _recentlyEvictedKeys.clear();
+                        remainingKeys = new HashSet(_poolMap.keySet());
+                        keyIter = remainingKeys.iterator();
+                    }
+                    if (!keyIter.hasNext()) {
+                        // done, there are no keyed pools
+                        return;
+                    }
+                    key = keyIter.next();
+                }
+
+                // if we don't have a keyed object pool iterator
+                if (objIter == null) {
+                    final LinkedList list = (LinkedList)_poolMap.get(key);
+                    if (_evictLastIndex < 0 || _evictLastIndex > list.size()) {
+                        _evictLastIndex = list.size();
+                    }
+                    objIter = list.listIterator(_evictLastIndex);
+                }
+
+                // if the _evictionCursor has a previous object, then test it
+                if(objIter.hasPrevious()) {
+                    ObjectTimestampPair pair = (ObjectTimestampPair)(objIter.previous());
+                    boolean removeObject=false;
+                    if(_minEvictableIdleTimeMillis > 0 &&
+                       System.currentTimeMillis() - pair.tstamp > _minEvictableIdleTimeMillis) {
+                       removeObject=true;
+                    }
+                    if(_testWhileIdle && removeObject == false) {
+                        boolean active = false;
+                        try {
+                            _factory.activateObject(key,pair.value);
+                            active = true;
+                        } catch(Exception e) {
+                            removeObject=true;
+                        }
+                        if(active) {
+                            if(!_factory.validateObject(key,pair.value)) {
+                                removeObject=true;
+                            } else {
+                                try {
+                                    _factory.passivateObject(key,pair.value);
+                                } catch(Exception e) {
+                                    removeObject=true;
+                                }
+                            }
+                        }
+                    }
+                    if(removeObject) {
+                        try {
+                            objIter.remove();
+                            _totalIdle--;
+                            _factory.destroyObject(key,pair.value);
+
+                            // Do not remove the key from the _poolList or _poolmap, even if the list
+                            // stored in the _poolMap for this key is empty when the
+                            // {@link #getMinIdle <i>minIdle</i>} is > 0.
+                            //
+                            // Otherwise if it was the last object for that key, drop that pool
+                            if ((_minIdle == 0) && (((LinkedList)(_poolMap.get(key))).isEmpty())) {
+                                _poolMap.remove(key);
+                            }
+                        } catch(Exception e) {
+                            ; // ignored
+                        }
+                    }
+                } else {
+                    // else done evicting keyed pool
+                    _recentlyEvictedKeys.add(key);
+                    _evictLastIndex = -1;
+                    objIter = null;
+                }
+            }
+        }
+    }
+
+    /**
+     * Iterates through all the known keys and creates any necessary objects to maintain
+     * the minimum level of pooled objects.
+     * @see #getMinIdle
+     * @see #setMinIdle
+     * @throws Exception If there was an error whilst creating the pooled objects.
+     */
+    private synchronized void ensureMinIdle() throws Exception {
+        Iterator iterator = _poolMap.keySet().iterator();
+
+        //Check if should sustain the pool
+        if (_minIdle > 0) {
+            // Loop through all elements in _poolList
+            // Find out the total number of max active and max idle for that class
+            // If the number is less than the minIdle, do creation loop to boost numbers
+            // Increment idle count + 1
+            while (iterator.hasNext()) {
+                //Get the next key to process
+                Object key = iterator.next();
+                ensureMinIdle(key);
+            }
+        }
+    }
+
+    /**
+     * Re-creates any needed objects to maintain the minimum levels of
+     * pooled objects for the specified key.
+     *
+     * This method uses {@link #calculateDefecit} to calculate the number
+     * of objects to be created. {@link #calculateDefecit} can be overridden to
+     * provide a different method of calculating the number of objects to be
+     * created.
+     * @param key The key to process
+     * @throws Exception If there was an error whilst creating the pooled objects
+     */
+    private synchronized void ensureMinIdle(Object key) throws Exception {
+        // Calculate current pool objects
+        int numberToCreate = calculateDefecit(key);
+
+        //Create required pool objects, if none to create, this loop will not be run.
+        for (int i = 0; i < numberToCreate; i++) {
+            addObject(key);
+        }
+    }
+
+    //--- non-public methods ----------------------------------------
+
+    /**
+     * Start the eviction thread or service, or when
+     * <i>delay</i> is non-positive, stop it
+     * if it is already running.
+     */
+    protected synchronized void startEvictor(long delay) {
+        if(null != _evictor) {
+            _evictor.cancel();
+            _evictor = null;
+        }
+        if(delay > 0) {
+            _evictor = new Evictor();
+            GenericObjectPool.EVICTION_TIMER.schedule(_evictor, delay, delay);
+        }
+    }
+
+    synchronized String debugInfo() {
+        StringBuffer buf = new StringBuffer();
+        buf.append("Active: ").append(getNumActive()).append("\n");
+        buf.append("Idle: ").append(getNumIdle()).append("\n");
+        Iterator it = _poolMap.keySet().iterator();
+        while(it.hasNext()) {
+            buf.append("\t").append(_poolMap.get(it.next())).append("\n");
+        }
+        return buf.toString();
+    }
+
+    private int getNumTests() {
+        if(_numTestsPerEvictionRun >= 0) {
+            return _numTestsPerEvictionRun;
+        } else {
+            return(int)(Math.ceil((double)_totalIdle/Math.abs((double)_numTestsPerEvictionRun)));
+        }
+    }
+
+    private void incrementActiveCount(Object key) {
+        _totalActive++;
+        Integer active = (Integer)(_activeMap.get(key));
+        if(null == active) {
+            _activeMap.put(key,new Integer(1));
+        } else {
+            _activeMap.put(key,new Integer(active.intValue() + 1));
+        }
+    }
+
+    private void decrementActiveCount(Object key) {
+        _totalActive--;
+        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));
+        }
+    }
+
+    private int getActiveCount(Object key) {
+        int active = 0;
+        Integer act = (Integer)(_activeMap.get(key));
+        if(null != act) {
+            active = act.intValue();
+        }
+        return active;
+    }
+
+    /**
+     * This returns the number of objects to create during the pool
+     * sustain cycle. This will ensure that the minimum number of idle
+     * connections is maintained without going past the maxPool value.
+     * <p>
+     * This method has been left public so derived classes can override
+     * the way the defecit is calculated. ie... Increase/decrease the pool
+     * size at certain times of day to accomodate for usage patterns.
+     *
+     * @param key - The key of the pool to calculate the number of
+     *              objects to be re-created
+     * @return The number of objects to be created
+     */
+    private int calculateDefecit(Object key) {
+        int objectDefecit = 0;
+
+        //Calculate no of objects needed to be created, in order to have
+        //the number of pooled objects < maxActive();
+        objectDefecit = getMinIdle() - getNumIdle(key);
+        if (getMaxActive() > 0) {
+            int growLimit = Math.max(0, getMaxActive() - getNumActive(key) - getNumIdle(key));
+            objectDefecit = Math.min(objectDefecit, growLimit);
+        }
+
+        // Take the maxTotal limit into account
+        if (getMaxTotal() > 0) {
+            int growLimit = Math.max(0, getMaxTotal() - getNumActive() - getNumIdle());
+            objectDefecit = Math.min(objectDefecit, growLimit);
+        }
+
+        return objectDefecit;
+    }
+
+    //--- inner classes ----------------------------------------------
+
+    /**
+     * A simple "struct" encapsulating an object instance and a timestamp.
+     *
+     * Implements Comparable, objects are sorted from old to new.
+     *
+     * This is also used by {@link GenericObjectPool}.
+     */
+    static class ObjectTimestampPair implements Comparable {
+        Object value;
+        long tstamp;
+
+        ObjectTimestampPair(Object val) {
+            this(val, System.currentTimeMillis());
+        }
+
+        ObjectTimestampPair(Object val, long time) {
+            value = val;
+            tstamp = time;
+        }
+
+        public String toString() {
+            return value + ";" + tstamp;
+        }
+
+        public int compareTo(Object obj) {
+            return compareTo((ObjectTimestampPair) obj);
+        }
+
+        public int compareTo(ObjectTimestampPair other) {
+            return (int) (this.tstamp - other.tstamp);
+        }
+    }
+
+    /**
+     * The idle object evictor {@link TimerTask}.
+     * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
+     */
+    private class Evictor extends TimerTask {
+        public void run() {
+            //Evict from the pool
+            try {
+                evict();
+            } catch(Exception e) {
+                // ignored
+            }
+            //Re-create the connections.
+            try {
+                ensureMinIdle();
+            } catch (Exception e) {
+                // ignored
+            }
+        }
+    }
+
+    /**
+     * 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 int maxTotal = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;
+        public int minIdle = GenericKeyedObjectPool.DEFAULT_MIN_IDLE;
+        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
+     */
+    private int _maxIdle = DEFAULT_MAX_IDLE;
+
+    /**
+     * The minimum no of idle objects to keep in the pool (per key)
+     * @see #setMinIdle
+     * @see #getMinIdle
+     */
+    private int _minIdle = DEFAULT_MIN_IDLE;
+
+    /**
+     * The cap on the number of active instances from the pool (per key).
+     * @see #setMaxActive
+     * @see #getMaxActive
+     */
+    private int _maxActive = DEFAULT_MAX_ACTIVE;
+
+    /**
+     * The cap on the total number of instances from the pool if non-positive.
+     * @see #setMaxTotal
+     * @see #getMaxTotal
+     */
+    private int _maxTotal = DEFAULT_MAX_TOTAL;
+    
+    /**
+     * 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
+     */
+    private 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
+     */
+    private byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION;
+
+    /**
+     * When <tt>true</tt>, objects will be
+     * {@link org.apache.commons.pool.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
+     */
+    private boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW;
+
+    /**
+     * When <tt>true</tt>, objects will be
+     * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
+     * before being returned to the pool within the
+     * {@link #returnObject}.
+     *
+     * @see #getTestOnReturn
+     * @see #setTestOnReturn
+     */
+    private boolean _testOnReturn = DEFAULT_TEST_ON_RETURN;
+
+    /**
+     * When <tt>true</tt>, objects will be
+     * {@link org.apache.commons.pool.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
+     */
+    private 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
+     */
+    private 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 #getNumIdle})/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
+     */
+    private 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
+     */
+    private long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
+
+    /** My hash of pools (CursorableLinkedLists). */
+    private HashMap _poolMap = null;
+
+    /** Count of active objects, per key. */
+    private HashMap _activeMap = null;
+
+    /** The total number of active instances. */
+    private int _totalActive = 0;
+
+    /** The total number of idle instances. */
+    private int _totalIdle = 0;
+
+    /** My {@link KeyedPoolableObjectFactory}. */
+    private KeyedPoolableObjectFactory _factory = null;
+
+    /**
+     * My idle object eviction {@link TimerTask}, if any.
+     */
+    private Evictor _evictor = null;
+
+    /**
+     * Idle object pool keys that have been evicted recently.
+     */
+    private Set _recentlyEvictedKeys = null;
+
+    /**
+     * Position in the _pool where the _evictor last stopped.
+     */
+    private int _evictLastIndex = -1;
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPoolFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPoolFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericKeyedObjectPoolFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,110 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import org.apache.commons.pool.KeyedObjectPool;
+import org.apache.commons.pool.KeyedObjectPoolFactory;
+import org.apache.commons.pool.KeyedPoolableObjectFactory;
+
+/**
+ * A factory for creating {@link GenericKeyedObjectPool} instances.
+ *
+ * @see GenericKeyedObjectPool
+ * @see KeyedObjectPoolFactory
+ *
+ * @author Rodney Waldhoff
+ * @author Dirk Verbeeck
+ * @version $Revision: 390792 $ $Date: 2006-04-02 03:13:42 -0400 (Sun, 02 Apr 2006) $ 
+ */
+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_MAX_TOTAL,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_MAX_TOTAL,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, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL,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_MAX_TOTAL,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, int maxTotal) {
+        this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle, maxTotal, 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, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL,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) {
+        this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
+    }
+
+    public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
+        this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, GenericKeyedObjectPool.DEFAULT_MIN_IDLE , testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
+    }
+
+    public GenericKeyedObjectPoolFactory(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
+        _maxIdle = maxIdle;
+        _maxActive = maxActive;
+        _maxTotal = maxTotal;
+        _minIdle = minIdle;
+        _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,_maxTotal,_minIdle,_testOnBorrow,_testOnReturn,_timeBetweenEvictionRunsMillis,_numTestsPerEvictionRun,_minEvictableIdleTimeMillis,_testWhileIdle);
+    }
+
+    //--- protected attributes ---------------------------------------
+
+    protected int _maxIdle = GenericKeyedObjectPool.DEFAULT_MAX_IDLE;
+    protected int _maxActive = GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE;
+    protected int _maxTotal = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;
+    protected int _minIdle = GenericKeyedObjectPool.DEFAULT_MIN_IDLE;
+    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;
+
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,1311 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.apache.commons.pool.BaseObjectPool;
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.PoolableObjectFactory;
+import org.apache.commons.pool.impl.GenericKeyedObjectPool.ObjectTimestampPair;
+
+/**
+ * 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 negative, 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>
+ * <p>
+ * GenericObjectPool is not usable without a {@link PoolableObjectFactory}.  A
+ * non-<code>null</code> factory must be provided either as a constructor argument
+ * or via a call to {@link #setFactory} before the pool is used.
+ *
+ * @see GenericKeyedObjectPool
+ * @author Rodney Waldhoff
+ * @author Dirk Verbeeck
+ * @version $Revision: 390563 $ $Date: 2006-03-31 20:28:14 -0500 (Fri, 31 Mar 2006) $
+ */
+public class GenericObjectPool extends BaseObjectPool 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 minimum number of "sleeping" instances in the pool
+     * before before the evictor thread (if active) spawns new objects.
+     * @see #getMinIdle
+     * @see #setMinIdle
+     */
+    public static final int DEFAULT_MIN_IDLE = 0;
+
+    /**
+     * 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;
+
+    /**
+     * The default value for {@link #getSoftMinEvictableIdleTimeMillis}.
+     * @see #getSoftMinEvictableIdleTimeMillis
+     * @see #setSoftMinEvictableIdleTimeMillis
+     */
+    public static final long DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1;
+
+    //--- package constants -------------------------------------------
+
+    /**
+     * Idle object evition Timer. Shared between all {@link GenericObjectPool}s and {@link GenericKeyedObjectPool} s.
+     */
+    static final Timer EVICTION_TIMER = new Timer(true);
+
+    //--- constructors -----------------------------------------------
+
+    /**
+     * Create a new <tt>GenericObjectPool</tt>.
+     */
+    public GenericObjectPool() {
+        this(null,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_MIN_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
+     */
+    public GenericObjectPool(PoolableObjectFactory factory) {
+        this(factory,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_MIN_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.minIdle,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_MIN_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_MIN_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,DEFAULT_MIN_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_MIN_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 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,DEFAULT_MIN_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 #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) {
+        this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, 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})
+     * @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 minIdle the minimum number of idle objects in my pool (see {@link #setMinIdle})
+     * @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, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
+        this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, minIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle, DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
+    }
+
+    /**
+     * 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 minIdle the minimum number of idle objects in my pool (see {@link #setMinIdle})
+     * @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})
+     * @param softMinEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition with the extra condition that at least "minIdle" amount of object remain in the pool. (see {@link #setSoftMinEvictableIdleTimeMillis})
+     */
+    public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, long softMinEvictableIdleTimeMillis) {
+        _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;
+        _minIdle = minIdle;
+        _testOnBorrow = testOnBorrow;
+        _testOnReturn = testOnReturn;
+        _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+        _numTestsPerEvictionRun = numTestsPerEvictionRun;
+        _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+        _softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
+        _testWhileIdle = testWhileIdle;
+
+        _pool = new LinkedList();
+        startEvictor(_timeBetweenEvictionRunsMillis);
+    }
+
+    //--- 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 synchronized 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 synchronized void setMaxActive(int maxActive) {
+        _maxActive = maxActive;
+        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 synchronized 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;
+        notifyAll();
+    }
+
+    /**
+     * 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 synchronized 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 synchronized void setMaxIdle(int maxIdle) {
+        _maxIdle = maxIdle;
+        notifyAll();
+    }
+
+    /**
+     * Sets the minimum number of objects allowed in the pool
+     * before the evictor thread (if active) spawns new objects.
+     * (Note no objects are created when: numActive + numIdle >= maxActive)
+     *
+     * @param minIdle The minimum number of objects.
+     * @see #getMinIdle
+     */
+    public synchronized void setMinIdle(int minIdle) {
+        _minIdle = minIdle;
+        notifyAll();
+    }
+
+    /**
+     * Returns the minimum number of objects allowed in the pool
+     * before the evictor thread (if active) spawns new objects.
+     * (Note no objects are created when: numActive + numIdle >= maxActive)
+     *
+     * @return The minimum number of objects.
+     * @see #setMinIdle
+     */
+    public synchronized int getMinIdle() {
+        return _minIdle;
+    }
+
+    /**
+     * 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 synchronized 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 synchronized 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 synchronized 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 synchronized 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) {
+        _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+        startEvictor(_timeBetweenEvictionRunsMillis);
+    }
+
+    /**
+     * Returns the max number of objects to examine during each run of the
+     * idle object evictor thread (if any).
+     *
+     * @see #setNumTestsPerEvictionRun
+     * @see #setTimeBetweenEvictionRunsMillis
+     */
+    public synchronized int getNumTestsPerEvictionRun() {
+        return _numTestsPerEvictionRun;
+    }
+
+    /**
+     * Sets the max 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 #getNumIdle})/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 synchronized 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;
+    }
+
+    /**
+     * 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), with the extra condition that at least
+     * "minIdle" amount of object remain in the pool.
+     *
+     * @see #setSoftMinEvictableIdleTimeMillis
+     */
+    public synchronized long getSoftMinEvictableIdleTimeMillis() {
+        return _softMinEvictableIdleTimeMillis;
+    }
+
+    /**
+     * 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), with the extra condition that at least
+     * "minIdle" amount of object remain in the pool.
+     * When non-positive, no objects will be evicted from the pool
+     * due to idle time alone.
+     *
+     * @see #getSoftMinEvictableIdleTimeMillis
+     */
+    public synchronized void setSoftMinEvictableIdleTimeMillis(long softMinEvictableIdleTimeMillis) {
+        _softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
+    }
+
+    /**
+     * 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 synchronized 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 synchronized void setTestWhileIdle(boolean testWhileIdle) {
+        _testWhileIdle = testWhileIdle;
+    }
+
+    /**
+     * Sets my configuration.
+     * @see GenericObjectPool.Config
+     */
+    public synchronized void setConfig(GenericObjectPool.Config conf) {
+        setMaxIdle(conf.maxIdle);
+        setMinIdle(conf.minIdle);
+        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() throws Exception {
+        assertOpen();
+        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) {
+                    // allow new object to be created
+                } else {
+                    // the pool is exhausted
+                    switch(_whenExhaustedAction) {
+                        case WHEN_EXHAUSTED_GROW:
+                            // allow new object to be created
+                            break;
+                        case WHEN_EXHAUSTED_FAIL:
+                            throw new NoSuchElementException("Pool exhausted");
+                        case WHEN_EXHAUSTED_BLOCK:
+                            try {
+                                if(_maxWait <= 0) {
+                                    wait();
+                                } else {
+                                    // this code may be executed again after a notify then continue cycle
+                                    // so, need to calculate the amount of time to wait
+                                    final long elapsed = (System.currentTimeMillis() - starttime);
+                                    final long waitTime = _maxWait - elapsed;
+                                    if (waitTime > 0)
+                                    {
+                                        wait(waitTime);
+                                    }
+                                }
+                            } 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 property " + _whenExhaustedAction + " not recognized.");
+                    }
+                }
+            }
+            _numActive++;
+
+            // create new object when needed
+            boolean newlyCreated = false;
+            if(null == pair) {
+                try {
+                    Object obj = _factory.makeObject();
+                    pair = new ObjectTimestampPair(obj);
+                    newlyCreated = true;
+                } finally {
+                    if (!newlyCreated) {
+                        // object cannot be created
+                        _numActive--;
+                        notifyAll();
+                    }
+                }
+            }
+
+            // activate & validate the object
+            try {
+                _factory.activateObject(pair.value);
+                if(_testOnBorrow && !_factory.validateObject(pair.value)) {
+                    throw new Exception("ValidateObject failed");
+                }
+                return pair.value;
+            }
+            catch (Throwable e) {
+                // object cannot be activated or is invalid
+                _numActive--;
+                notifyAll();
+                try {
+                    _factory.destroyObject(pair.value);
+                }
+                catch (Throwable e2) {
+                    // cannot destroy broken object
+                }
+                if(newlyCreated) {
+                    throw new NoSuchElementException("Could not create a validated object, cause: " + e.getMessage());
+                }
+                else {
+                    continue; // keep looping
+                }
+            }
+        }
+    }
+
+    public synchronized void invalidateObject(Object obj) throws Exception {
+        assertOpen();
+        try {
+            _factory.destroyObject(obj);
+        }
+        finally {
+            _numActive--;
+            notifyAll(); // _numActive has changed
+        }
+    }
+
+    public synchronized void clear() {
+        assertOpen();
+        for(Iterator it = _pool.iterator(); it.hasNext(); ) {
+            try {
+                _factory.destroyObject(((ObjectTimestampPair)(it.next())).value);
+            } catch(Exception e) {
+                // ignore error, keep destroying the rest
+            }
+            it.remove();
+        }
+        _pool.clear();
+        notifyAll(); // num sleeping has changed
+    }
+
+    public synchronized int getNumActive() {
+        assertOpen();
+        return _numActive;
+    }
+
+    public synchronized int getNumIdle() {
+        assertOpen();
+        return _pool.size();
+    }
+
+    public synchronized void returnObject(Object obj) throws Exception {
+        assertOpen();
+        addObjectToPool(obj, true);
+    }
+
+    private void addObjectToPool(Object obj, boolean decrementNumActive) throws Exception {
+        boolean success = true;
+        if(_testOnReturn && !(_factory.validateObject(obj))) {
+            success = false;
+        } else {
+            try {
+                _factory.passivateObject(obj);
+            } catch(Exception e) {
+                success = false;
+            }
+        }
+
+        boolean shouldDestroy = !success;
+
+        if (decrementNumActive) {
+            _numActive--;
+        }
+        if((_maxIdle >= 0) && (_pool.size() >= _maxIdle)) {
+            shouldDestroy = true;
+        } else if(success) {
+            _pool.addLast(new ObjectTimestampPair(obj));
+        }
+        notifyAll(); // _numActive has changed
+
+        if(shouldDestroy) {
+            try {
+                _factory.destroyObject(obj);
+            } catch(Exception e) {
+                // ignored
+            }
+        }
+    }
+
+    public synchronized void close() throws Exception {
+        clear();
+        _pool = null;
+        _factory = null;
+        startEvictor(-1L);
+        super.close();
+    }
+
+    public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException {
+        assertOpen();
+        if(0 < getNumActive()) {
+            throw new IllegalStateException("Objects are already active");
+        } else {
+            clear();
+            _factory = factory;
+        }
+    }
+
+    public synchronized void evict() throws Exception {
+        assertOpen();
+        if(!_pool.isEmpty()) {
+            ListIterator iter;
+            if (evictLastIndex < 0) {
+                iter = _pool.listIterator(_pool.size());
+            } else {
+                iter = _pool.listIterator(evictLastIndex);
+            }
+            for(int i=0,m=getNumTests();i<m;i++) {
+                if(!iter.hasPrevious()) {
+                    iter = _pool.listIterator(_pool.size());
+                }
+                boolean removeObject = false;
+                final ObjectTimestampPair pair = (ObjectTimestampPair)(iter.previous());
+                final long idleTimeMilis = System.currentTimeMillis() - pair.tstamp;
+                if ((_minEvictableIdleTimeMillis > 0)
+                        && (idleTimeMilis > _minEvictableIdleTimeMillis)) {
+                    removeObject = true;
+                } else if ((_softMinEvictableIdleTimeMillis > 0)
+                        && (idleTimeMilis > _softMinEvictableIdleTimeMillis)
+                        && (getNumIdle() > getMinIdle())) {
+                    removeObject = true;
+                }
+                if(_testWhileIdle && !removeObject) {
+                    boolean active = false;
+                    try {
+                        _factory.activateObject(pair.value);
+                        active = true;
+                    } catch(Exception e) {
+                        removeObject=true;
+                    }
+                    if(active) {
+                        if(!_factory.validateObject(pair.value)) {
+                            removeObject=true;
+                        } else {
+                            try {
+                                _factory.passivateObject(pair.value);
+                            } catch(Exception e) {
+                                removeObject=true;
+                            }
+                        }
+                    }
+                }
+                if(removeObject) {
+                    try {
+                        iter.remove();
+                        _factory.destroyObject(pair.value);
+                    } catch(Exception e) {
+                        // ignored
+                    }
+                }
+            }
+            evictLastIndex = iter.previousIndex(); // resume from here
+        } // if !empty
+    }
+
+    /**
+     * Check to see if we are below our minimum number of objects
+     * if so enough to bring us back to our minimum.
+     */
+    private void ensureMinIdle() throws Exception {
+        // this method isn't synchronized so the
+        // calculateDeficit is done at the beginning
+        // as a loop limit and a second time inside the loop
+        // to stop when another thread already returned the
+        // needed objects
+        int objectDeficit = calculateDeficit();
+        for ( int j = 0 ; j < objectDeficit && calculateDeficit() > 0 ; j++ ) {
+            addObject();
+        }
+    }
+
+    private synchronized int calculateDeficit() {
+        int objectDeficit = getMinIdle() - getNumIdle();
+        if (_maxActive > 0) {
+            int growLimit = Math.max(0, getMaxActive() - getNumActive() - getNumIdle());
+            objectDeficit = Math.min(objectDeficit, growLimit);
+        }
+        return objectDeficit;
+    }
+
+    /**
+     * Create an object, and place it into the pool.
+     * addObject() is useful for "pre-loading" a pool with idle objects.
+     */
+    public synchronized void addObject() throws Exception {
+        assertOpen();
+        Object obj = _factory.makeObject();
+        addObjectToPool(obj, false);
+    }
+
+    //--- non-public methods ----------------------------------------
+
+    /**
+     * Start the eviction thread or service, or when
+     * <i>delay</i> is non-positive, stop it
+     * if it is already running.
+     */
+    protected synchronized void startEvictor(long delay) {
+        if(null != _evictor) {
+            _evictor.cancel();
+            _evictor = null;
+        }
+        if(delay > 0) {
+            _evictor = new Evictor();
+            EVICTION_TIMER.schedule(_evictor, delay, delay);
+        }
+    }
+
+    synchronized String debugInfo() {
+        StringBuffer buf = new StringBuffer();
+        buf.append("Active: ").append(getNumActive()).append("\n");
+        buf.append("Idle: ").append(getNumIdle()).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();
+    }
+
+    private int getNumTests() {
+        if(_numTestsPerEvictionRun >= 0) {
+            return Math.min(_numTestsPerEvictionRun, _pool.size());
+        } else {
+            return(int)(Math.ceil((double)_pool.size()/Math.abs((double)_numTestsPerEvictionRun)));
+        }
+    }
+
+    //--- inner classes ----------------------------------------------
+
+    /**
+     * The idle object evictor {@link TimerTask}.
+     * @see GenericObjectPool#setTimeBetweenEvictionRunsMillis
+     */
+    private class Evictor extends TimerTask {
+        public void run() {
+            try {
+                evict();
+            } catch(Exception e) {
+                // ignored
+            }
+            try {
+                ensureMinIdle();
+            } catch(Exception e) {
+                // ignored
+            }
+        }
+    }
+
+    /**
+     * 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 minIdle = GenericObjectPool.DEFAULT_MIN_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;
+        public long softMinEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
+    }
+
+    //--- private attributes ---------------------------------------
+
+    /**
+     * The cap on the number of idle instances in the pool.
+     * @see #setMaxIdle
+     * @see #getMaxIdle
+     */
+    private int _maxIdle = DEFAULT_MAX_IDLE;
+
+    /**
+    * The cap on the minimum number of idle instances in the pool.
+    * @see #setMinIdle
+    * @see #getMinIdle
+    */
+    private int _minIdle = DEFAULT_MIN_IDLE;
+
+    /**
+     * The cap on the total number of active instances from the pool.
+     * @see #setMaxActive
+     * @see #getMaxActive
+     */
+    private 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
+     */
+    private 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
+     */
+    private 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
+     */
+    private 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
+     */
+    private 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
+     */
+    private 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
+     */
+    private long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
+
+    /**
+     * The max 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 #getNumIdle})/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
+     */
+    private 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
+     */
+    private long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
+
+    /**
+     * 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), with the extra condition that at least
+     * "minIdle" amount of object remain in the pool.
+     * When non-positive, no objects will be evicted from the pool
+     * due to idle time alone.
+     *
+     * @see #setSoftMinEvictableIdleTimeMillis
+     * @see #getSoftMinEvictableIdleTimeMillis
+     */
+    private long _softMinEvictableIdleTimeMillis = DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
+
+    /** My pool. */
+    private LinkedList _pool = null;
+
+    /** My {@link PoolableObjectFactory}. */
+    private PoolableObjectFactory _factory = null;
+
+    /**
+     * The number of objects {@link #borrowObject} borrowed
+     * from the pool, but not yet returned.
+     */
+    private int _numActive = 0;
+
+    /**
+     * My idle object eviction {@link TimerTask}, if any.
+     */
+    private Evictor _evictor = null;
+
+    /**
+     * Position in the _pool where the _evictor last stopped.
+     */
+    private int evictLastIndex = -1;
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericObjectPoolFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericObjectPoolFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/GenericObjectPoolFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,104 @@
+/*
+ * Copyright 1999-2004,2006 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.ObjectPoolFactory;
+import org.apache.commons.pool.PoolableObjectFactory;
+
+/**
+ * A factory for creating {@link GenericObjectPool} instances.
+ *
+ * @see GenericObjectPool
+ * @see ObjectPoolFactory
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 390563 $ $Date: 2006-03-31 20:28:14 -0500 (Fri, 31 Mar 2006) $ 
+ */
+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_MIN_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.minIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle,config.softMinEvictableIdleTimeMillis);
+    }
+
+    public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive) {
+        this(factory,maxActive,GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,GenericObjectPool.DEFAULT_MAX_WAIT,GenericObjectPool.DEFAULT_MAX_IDLE,GenericObjectPool.DEFAULT_MIN_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_MIN_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,GenericObjectPool.DEFAULT_MIN_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_MIN_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, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
+        this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,GenericObjectPool.DEFAULT_MIN_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, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
+        this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,GenericObjectPool.DEFAULT_MIN_IDLE,testOnBorrow,testOnReturn,timeBetweenEvictionRunsMillis,numTestsPerEvictionRun,minEvictableIdleTimeMillis,testWhileIdle, GenericObjectPool.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
+    }
+    
+    public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
+        this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,minIdle,testOnBorrow,testOnReturn,timeBetweenEvictionRunsMillis,numTestsPerEvictionRun,minEvictableIdleTimeMillis,testWhileIdle, GenericObjectPool.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
+    }
+
+    public GenericObjectPoolFactory(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, long softMinEvictableIdleTimeMillis) {
+        _maxIdle = maxIdle;
+        _minIdle = minIdle;
+        _maxActive = maxActive;
+        _maxWait = maxWait;
+        _whenExhaustedAction = whenExhaustedAction;
+        _testOnBorrow = testOnBorrow;
+        _testOnReturn = testOnReturn;
+        _testWhileIdle = testWhileIdle;
+        _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+        _numTestsPerEvictionRun = numTestsPerEvictionRun;
+        _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+        _softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
+        _factory = factory;
+    }
+
+    public ObjectPool createPool() {
+        return new GenericObjectPool(_factory,_maxActive,_whenExhaustedAction,_maxWait,_maxIdle,_minIdle,_testOnBorrow,_testOnReturn,_timeBetweenEvictionRunsMillis,_numTestsPerEvictionRun,_minEvictableIdleTimeMillis,_testWhileIdle,_softMinEvictableIdleTimeMillis);
+    }
+
+    protected int _maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
+    protected int _minIdle = GenericObjectPool.DEFAULT_MIN_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 long _softMinEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
+    protected PoolableObjectFactory _factory = null;
+
+
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/SoftReferenceObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/SoftReferenceObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/SoftReferenceObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,187 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.apache.commons.pool.BaseObjectPool;
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.PoolableObjectFactory;
+
+/**
+ * A {@link java.lang.ref.SoftReference SoftReference} based
+ * {@link ObjectPool}.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 383290 $ $Date: 2006-03-05 02:00:15 -0500 (Sun, 05 Mar 2006) $
+ */
+public class SoftReferenceObjectPool extends BaseObjectPool implements ObjectPool {
+    public SoftReferenceObjectPool() {
+        _pool = new ArrayList();
+        _factory = null;
+    }
+
+    public SoftReferenceObjectPool(PoolableObjectFactory factory) {
+        _pool = new ArrayList();
+        _factory = factory;
+    }
+
+    public SoftReferenceObjectPool(PoolableObjectFactory factory, int initSize) throws Exception {
+        _pool = new ArrayList();
+        _factory = factory;
+        if(null != _factory) {
+            for(int i=0;i<initSize;i++) {
+                Object obj = _factory.makeObject();
+                _factory.passivateObject(obj);
+                _pool.add(new SoftReference(obj));
+            }
+        }
+    }
+
+    public synchronized Object borrowObject() throws Exception {        
+        assertOpen();
+        Object obj = null;
+        while(null == obj) {
+            if(_pool.isEmpty()) {
+                if(null == _factory) {
+                    throw new NoSuchElementException();
+                } else {
+                    obj = _factory.makeObject();
+                }
+            } else {
+                SoftReference ref = (SoftReference)(_pool.remove(_pool.size() - 1));
+                obj = ref.get();
+            }
+            if(null != _factory && null != obj) {
+                _factory.activateObject(obj);
+            }
+            if (null != _factory && null != obj && !_factory.validateObject(obj)) {
+                _factory.destroyObject(obj);
+                obj = null;
+            }
+        }
+        _numActive++;
+        return obj;
+    }
+
+    public synchronized void returnObject(Object obj) throws Exception {
+        assertOpen();
+        boolean success = true;
+        if(!(_factory.validateObject(obj))) {
+            success = false;
+        } else {
+            try {
+                _factory.passivateObject(obj);
+            } catch(Exception e) {
+                success = false;
+            }
+        }
+
+        boolean shouldDestroy = !success;
+        _numActive--;
+        if(success) {
+            _pool.add(new SoftReference(obj));
+        }
+        notifyAll(); // _numActive has changed
+
+        if(shouldDestroy) {
+            try {
+                _factory.destroyObject(obj);
+            } catch(Exception e) {
+                // ignored
+            }
+        }
+
+    }
+
+    public synchronized void invalidateObject(Object obj) throws Exception {
+        assertOpen();
+        _numActive--;
+        _factory.destroyObject(obj);
+        notifyAll(); // _numActive has changed
+    }
+
+    /**
+     * Create an object, and place it into the pool.
+     * addObject() is useful for "pre-loading" a pool with idle objects.
+     */
+    public synchronized void addObject() throws Exception {
+        assertOpen();
+        Object obj = _factory.makeObject();
+        _numActive++;   // A little slimy - must do this because returnObject decrements it.
+        returnObject(obj);
+    }
+
+    /** Returns an approximation not less than the of the number of idle instances in the pool. */
+    public synchronized int getNumIdle() {
+        assertOpen();
+        return _pool.size();
+    }
+
+    public synchronized int getNumActive() {
+        assertOpen();
+        return _numActive;
+    }
+
+    public synchronized void clear() {
+        assertOpen();
+        if(null != _factory) {
+            Iterator iter = _pool.iterator();
+            while(iter.hasNext()) {
+                try {
+                    Object obj = ((SoftReference)iter.next()).get();
+                    if(null != obj) {
+                        _factory.destroyObject(obj);
+                    }
+                } catch(Exception e) {
+                    // ignore error, keep destroying the rest
+                }
+            }
+        }
+        _pool.clear();
+    }
+
+    public synchronized void close() throws Exception {
+        clear();
+        _pool = null;
+        _factory = null;
+        super.close();
+    }
+
+    public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException {
+        assertOpen();
+        if(0 < getNumActive()) {
+            throw new IllegalStateException("Objects are already active");
+        } else {
+            clear();
+            _factory = factory;
+        }
+    }
+
+    /** My pool. */
+    private List _pool = null;
+
+    /** My {@link PoolableObjectFactory}. */
+    private PoolableObjectFactory _factory = null;
+
+    /** Number of active objects. */
+    private int _numActive = 0;
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackKeyedObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackKeyedObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackKeyedObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,343 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Stack;
+
+import org.apache.commons.pool.BaseKeyedObjectPool;
+import org.apache.commons.pool.KeyedObjectPool;
+import org.apache.commons.pool.KeyedPoolableObjectFactory;
+
+/**
+ * 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 $Revision: 328937 $ $Date: 2005-10-27 15:23:53 -0400 (Thu, 27 Oct 2005) $ 
+ */
+public class StackKeyedObjectPool extends BaseKeyedObjectPool 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}.
+     *
+     * @param max cap on the number of "sleeping" instances in the pool
+     */
+    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}.
+     *
+     * @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(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) throws Exception {
+        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);
+        }
+        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);
+        }
+        incrementActiveCount(key);
+        return obj;
+    }
+
+    public synchronized void returnObject(Object key, Object obj) throws Exception {
+        decrementActiveCount(key);
+        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);
+            }
+            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);
+            }
+        }
+    }
+
+    public synchronized void invalidateObject(Object key, Object obj) throws Exception {
+        decrementActiveCount(key);
+        if(null != _factory) {
+            _factory.destroyObject(key,obj);
+        }
+        notifyAll(); // _totalActive has changed
+    }
+
+    public synchronized void addObject(Object key) throws Exception {
+        Object obj = _factory.makeObject(key);
+        incrementActiveCount(key); // returnObject will decrement this
+        returnObject(key,obj);
+    }
+
+    public int getNumIdle() {
+        return _totIdle;
+    }
+
+    public int getNumActive() {
+        return _totActive;
+    }
+
+    public synchronized int getNumActive(Object key) {
+        return getActiveCount(key);
+    }
+
+    public synchronized int getNumIdle(Object key) {
+        try {
+            return((Stack)(_pools.get(key))).size();
+        } catch(Exception e) {
+            return 0;
+        }
+    }
+
+    public synchronized void clear() {
+        Iterator it = _pools.keySet().iterator();
+        while(it.hasNext()) {
+            Object key = it.next();
+            Stack stack = (Stack)(_pools.get(key));
+            destroyStack(key,stack);
+        }
+        _totIdle = 0;
+        _pools.clear();
+        _activeCount.clear();
+    }
+
+    public synchronized void clear(Object key) {
+        Stack stack = (Stack)(_pools.remove(key));
+        destroyStack(key,stack);
+    }
+
+    private synchronized void destroyStack(Object key, Stack stack) {
+        if(null == stack) {
+            return;
+        } else {
+            if(null != _factory) {
+                Iterator it = stack.iterator();
+                while(it.hasNext()) {
+                    try {
+                        _factory.destroyObject(key,it.next());
+                    } catch(Exception e) {
+                        // ignore error, keep destroying the rest
+                    }
+                }
+            }
+            _totIdle -= stack.size();
+            _activeCount.remove(key);
+            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();
+    }
+
+    public synchronized void close() throws Exception {
+        clear();
+        _pools = null;
+        _factory = null;
+        _activeCount = null;
+    }
+
+    public synchronized void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException {
+        if(0 < getNumActive()) {
+            throw new IllegalStateException("Objects are already active");
+        } else {
+            clear();
+            _factory = factory;
+        }
+    }
+
+    private int getActiveCount(Object key) {
+        try {
+            return ((Integer)_activeCount.get(key)).intValue();
+        } catch(NoSuchElementException e) {
+            return 0;
+        } catch(NullPointerException e) {
+            return 0;
+        }
+    }
+
+    private void incrementActiveCount(Object key) {
+        _totActive++;
+        Integer old = (Integer)(_activeCount.get(key));
+        if(null == old) { 
+            _activeCount.put(key,new Integer(1));
+        } else {
+            _activeCount.put(key,new Integer(old.intValue() + 1));
+        }
+    }
+
+    private void decrementActiveCount(Object key) {
+        _totActive--;
+        Integer active = (Integer)(_activeCount.get(key));
+        if(null == active) {
+            // do nothing, either null or zero is OK
+        } else if(active.intValue() <= 1) {
+            _activeCount.remove(key);
+        } else {
+            _activeCount.put(key, new Integer(active.intValue() - 1));
+        }
+    }
+
+    /** 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;
+
+    /** Total number of object borrowed and not yet retuened for all pools */
+    protected int _totActive = 0;
+
+    /** Total number of objects "sleeping" for all pools */
+    protected int _totIdle = 0;
+
+    /** Number of active objects borrowed and not yet returned by pool */
+    protected HashMap _activeCount = null;
+
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackKeyedObjectPoolFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackKeyedObjectPoolFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackKeyedObjectPoolFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,67 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import org.apache.commons.pool.KeyedObjectPool;
+import org.apache.commons.pool.KeyedObjectPoolFactory;
+import org.apache.commons.pool.KeyedPoolableObjectFactory;
+
+/**
+ * A factory for creating {@link StackKeyedObjectPool} instances.
+ *
+ * @see StackKeyedObjectPool
+ * @see KeyedObjectPoolFactory
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ */
+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;
+
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,269 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Stack;
+
+import org.apache.commons.pool.BaseObjectPool;
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.PoolableObjectFactory;
+
+/**
+ * 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
+ * @author Dirk Verbeeck
+ * @version $Revision: 383290 $ $Date: 2006-03-05 02:00:15 -0500 (Sun, 05 Mar 2006) $
+ */
+public class StackObjectPool extends BaseObjectPool 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}.
+     *
+     * @param maxIdle cap on the number of "sleeping" instances in the pool
+     */
+    public StackObjectPool(int maxIdle) {
+        this((PoolableObjectFactory)null,maxIdle,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}.
+     *
+     * @param maxIdle cap on the number of "sleeping" instances in the pool
+     * @param initIdleCapacity initial size of the pool (this specifies the size of the container,
+     *             it does not cause the pool to be pre-populated.)
+     */
+    public StackObjectPool(int maxIdle, int initIdleCapacity) {
+        this((PoolableObjectFactory)null,maxIdle,initIdleCapacity);
+    }
+
+    /**
+     * 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 maxIdle cap on the number of "sleeping" instances in the pool
+     */
+    public StackObjectPool(PoolableObjectFactory factory, int maxIdle) {
+        this(factory,maxIdle,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 maxIdle cap on the number of "sleeping" instances in the pool
+     * @param initIdleCapacity 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 maxIdle, int initIdleCapacity) {
+        _factory = factory;
+        _maxSleeping = (maxIdle < 0 ? DEFAULT_MAX_SLEEPING : maxIdle);
+        int initcapacity = (initIdleCapacity < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : initIdleCapacity);
+        _pool = new Stack();
+        _pool.ensureCapacity( initcapacity > _maxSleeping ? _maxSleeping : initcapacity);
+    }
+
+    public synchronized Object borrowObject() throws Exception {
+        assertOpen();
+        Object obj = null;
+        while (null == obj) {
+            if (!_pool.empty()) {
+                obj = _pool.pop();
+            } else {
+                if(null == _factory) {
+                    throw new NoSuchElementException();
+                } else {
+                    obj = _factory.makeObject();
+                }
+            }
+            if(null != _factory && null != obj) {
+                _factory.activateObject(obj);
+            }
+            if (null != _factory && null != obj && !_factory.validateObject(obj)) {
+                _factory.destroyObject(obj);
+                obj = null;
+            }
+        }
+        _numActive++;
+        return obj;
+    }
+
+    public synchronized void returnObject(Object obj) throws Exception {
+        assertOpen();
+        boolean success = true;
+        if(null != _factory) {
+            if(!(_factory.validateObject(obj))) {
+                success = false;
+            } else {
+                try {
+                    _factory.passivateObject(obj);
+                } catch(Exception e) {
+                    success = false;
+                }
+            }
+        }
+
+        boolean shouldDestroy = !success;
+
+        _numActive--;
+        if (success) {
+            Object toBeDestroyed = null;
+            if(_pool.size() >= _maxSleeping) {
+                shouldDestroy = true;
+                toBeDestroyed = _pool.remove(0); // remove the stalest object
+            }
+            _pool.push(obj);
+            obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed
+        }
+        notifyAll(); // _numActive has changed
+
+        if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null
+            try {
+                _factory.destroyObject(obj);
+            } catch(Exception e) {
+                // ignored
+            }
+        }
+    }
+
+    public synchronized void invalidateObject(Object obj) throws Exception {
+        assertOpen();
+        _numActive--;
+        if(null != _factory ) {
+            _factory.destroyObject(obj);
+        }
+        notifyAll(); // _numActive has changed
+    }
+
+    public synchronized int getNumIdle() {
+        assertOpen();
+        return _pool.size();
+    }
+
+    public synchronized int getNumActive() {
+        assertOpen();
+        return _numActive;
+    }
+
+    public synchronized void clear() {
+        assertOpen();
+        if(null != _factory) {
+            Iterator it = _pool.iterator();
+            while(it.hasNext()) {
+                try {
+                    _factory.destroyObject(it.next());
+                } catch(Exception e) {
+                    // ignore error, keep destroying the rest
+                }
+            }
+        }
+        _pool.clear();
+    }
+
+    public synchronized void close() throws Exception {
+        clear();
+        _pool = null;
+        _factory = null;
+        super.close();
+    }
+
+    /**
+     * Create an object, and place it into the pool.
+     * addObject() is useful for "pre-loading" a pool with idle objects.
+     * @throws Exception when the {@link #_factory} has a problem creating an object.
+     */
+    public synchronized void addObject() throws Exception {
+        assertOpen();
+        Object obj = _factory.makeObject();
+        _numActive++;   // A little slimy - must do this because returnObject decrements it.
+        this.returnObject(obj);
+    }
+
+    public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException {
+        assertOpen();
+        if(0 < getNumActive()) {
+            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;
+
+    /** Number of object borrowed but not yet returned to the pool. */
+    protected int _numActive = 0;
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackObjectPoolFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackObjectPoolFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/StackObjectPoolFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,67 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.ObjectPoolFactory;
+import org.apache.commons.pool.PoolableObjectFactory;
+
+/**
+ * A factory for creating {@link StackObjectPool} instances.
+ *
+ * @see StackObjectPool
+ * @see StackKeyedObjectPoolFactory
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ */
+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;
+
+}

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/package.html
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/package.html	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/impl/package.html	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,40 @@
+<!-- $Id: package.html 155430 2005-02-26 13:13:28Z dirkv $ -->
+<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>

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/overview.html
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/overview.html	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/overview.html	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,105 @@
+<!-- $Id: overview.html 155430 2005-02-26 13:13:28Z dirkv $ -->
+<html>
+   <head>
+      <title>Overview of the org.apache.commons.pool component</title>
+   </head>
+   <body>
+      <p>
+         Generic Object pooling API with several implementations.
+      </p>
+      <p>
+         The <code>org.apache.commons.pool</code> package defines a simple 
+         interface for a pool of object instances, and a handful of base 
+         classes that may be useful when creating pool implementations.
+         The api supports pooling of unique objects which can be requested
+         via a key as well as pools where all objects are equivalent.
+      </p>
+      <p>
+         The <code>org.apache.commons.pool.impl</code> package contains
+         several pool implementations.  
+         {@link org.apache.commons.pool.impl.StackObjectPool StackObjectPool}
+         is useful for supporting reuse of a limited number of instances while
+         allowing new instances to be created as needed to support high demand.
+         {@link org.apache.commons.pool.impl.GenericObjectPool 
+         GenericObjectPool} has many configuration options and can support
+         a limited set of objects such as would be useful in a database
+         connection pool.
+         {@link org.apache.commons.pool.impl.SoftReferenceObjectPool 
+         SoftReferenceObjectPool} has no limit on the number of objects in the
+         pool, but garbage collector can remove idle objects from the pool as
+         needed.  There are also keyed versions of the first two.
+      </p>
+      <p>
+         Here is a simple example of pooling <code>HashMap</code>'s.  First 
+         create an {@link org.apache.commons.pool.ObjectPoolFactory 
+         ObjectPoolFactory}
+      </p>
+<pre>
+    public class HashMapFactory 
+        extends {@link org.apache.commons.pool.BasePoolableObjectFactory BasePoolableObjectFactory}
+    {
+        /**
+         * Creates an instance that can be returned by the pool.
+         * @return an instance that can be returned by the pool.
+         */
+        public Object makeObject() 
+            throws Exception
+        {
+            return new HashMap();
+        }
+        
+        /**
+         * Uninitialize an instance to be returned to the pool.
+         * @param obj the instance to be passivated
+         */
+        public void passivateObject(Object obj) 
+            throws Exception
+        {
+            Map map = (Map)obj;
+            map.clear();
+        }
+    }
+</pre>
+      <p>
+         A class that makes frequent use of a Map could then use a pool
+         as shown below:
+      </p>
+<pre>
+    public class Foo
+    {
+        private {@link org.apache.commons.pool.ObjectPool ObjectPool} pool;
+        public Foo()
+        {
+            {@link org.apache.commons.pool.PoolableObjectFactory PoolableObjectFactory} factory = new HashMapFactory();
+            pool = new StackObjectPool(factory, 1000);
+        }
+
+        public doSomething()
+        {
+            ...
+            Map map = null;
+            try
+            {
+                map = (Map)pool.borrowObject();
+                // use map
+                ...
+            }
+            finally
+            {
+                if (map != null)
+                {
+                    pool.returnObject(map);
+                }
+            }
+            ...
+        }
+    }
+</pre>
+
+<p>
+The above example shows how one would use an 
+{@link org.apache.commons.pool.ObjectPool ObjectPool}.  The other supplied 
+implementations or another special purpose pool would be used similarly.
+</p>
+   </body>
+</html>
\ No newline at end of file

Added: branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/package.html
===================================================================
--- branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/package.html	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/java/org/apache/commons/pool/package.html	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,53 @@
+<!-- $Id: package.html 155430 2005-02-26 13:13:28Z dirkv $ -->
+<html>
+   <head>
+      <title>Package Documentation for org.apache.commons.pool</title>
+   </head>
+   <body>
+      <p>
+         Object pooling API.
+      </p>
+      <p>
+         The <code>org.apache.commons.pool</code> package defines a simple 
+         interface for a pool of object instances, and a handful of base 
+         classes that may be useful when creating pool implementations.
+      </p>
+      <p>
+         The <code>pool</code> package itself doesn't define a specific object
+         pooling implementation, but rather a contract that implementations may
+         support in order to be fully interchangeable.         
+      </p>
+      <p>
+         The <code>pool</code> package separates the way in which instances are
+         pooled from the way in which they are created, resulting in a pair of 
+         interfaces:
+      </p>
+      <dl>
+        <dt>{@link org.apache.commons.pool.ObjectPool ObjectPool}</dt>
+        <dd>
+          defines a simple object pooling interface, with methods for 
+          borrowing instances from and returning them to the pool.
+        </dd>
+        <dt>{@link org.apache.commons.pool.PoolableObjectFactory PoolableObjectFactory}</dt>
+        <dd>
+          defines lifecycle methods for object instances contained within a pool.
+          By associating a factory with a pool, the pool can create new object
+          instances as needed.
+        </dd>
+      </dl>        
+      <p>
+        {@link org.apache.commons.pool.ObjectPoolFactory ObjectPoolFactory}
+        defines a simple factory for <code>ObjectPool</code>s, which may be
+        useful for some applications.
+      </p>
+      <p>
+         The <code>pool</code> package also provides a keyed pool interface,
+         which pools instances of multiple types, accessed according to an 
+         arbitrary key. See
+         {@link org.apache.commons.pool.KeyedObjectPool KeyedObjectPool},
+         {@link org.apache.commons.pool.KeyedPoolableObjectFactory KeyedPoolableObjectFactory},
+         and 
+         {@link org.apache.commons.pool.KeyedObjectPoolFactory KeyedObjectPoolFactory}.
+      </p>
+   </body>
+</html>

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestAll.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestAll.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestAll.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,47 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Revision: 384433 $ $Date: 2006-03-09 00:19:21 -0500 (Thu, 09 Mar 2006) $
+ */
+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.TestBaseObjectPool.suite());
+        suite.addTest(org.apache.commons.pool.TestBaseKeyedObjectPool.suite());
+        suite.addTest(org.apache.commons.pool.TestBasePoolableObjectFactory.suite());
+        suite.addTest(org.apache.commons.pool.TestBaseKeyedPoolableObjectFactory.suite());
+        suite.addTest(org.apache.commons.pool.TestPoolUtils.suite());
+        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);
+    }
+}

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBaseKeyedObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBaseKeyedObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBaseKeyedObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,106 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.pool;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $
+ */
+public class TestBaseKeyedObjectPool extends TestCase {
+    public TestBaseKeyedObjectPool(String testName) {
+        super(testName);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestBaseKeyedObjectPool.class);
+    }
+    
+    // tests
+    public void testUnsupportedOperations() throws Exception {
+        KeyedObjectPool pool = new BaseKeyedObjectPool() { 
+            public Object borrowObject(Object key) throws Exception {
+                return null;
+            }
+            public void returnObject(Object key, Object obj) throws Exception {                
+            }
+            public void invalidateObject(Object key, Object obj) throws Exception {                
+            }            
+        };   
+        
+        try {
+            pool.addObject("key");
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+
+        try {
+            pool.getNumIdle();
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+
+        try {
+            pool.getNumActive();
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+
+        try {
+            pool.clear();
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+
+        try {
+            pool.getNumIdle("key");
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+
+        try {
+            pool.getNumActive("key");
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+
+        try {
+            pool.clear("key");
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+
+        try {
+            pool.setFactory(null);
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+
+        pool.close(); // a no-op, probably should be remove
+
+    }
+}

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBaseKeyedPoolableObjectFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBaseKeyedPoolableObjectFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBaseKeyedPoolableObjectFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,48 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.pool;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $
+ */
+public class TestBaseKeyedPoolableObjectFactory extends TestCase {
+    public TestBaseKeyedPoolableObjectFactory(String testName) {
+        super(testName);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestBaseKeyedPoolableObjectFactory.class);
+    }
+    
+    // tests
+    public void testDefaultMethods() throws Exception {
+        KeyedPoolableObjectFactory factory = new BaseKeyedPoolableObjectFactory() { 
+            public Object makeObject(Object key) throws Exception {
+                return null;
+            }
+        };   
+        
+        factory.activateObject("key",null); // a no-op
+        factory.passivateObject("key",null); // a no-op
+        factory.destroyObject("key",null); // a no-op
+        assertTrue(factory.validateObject("key",null)); // constant true
+    }
+}

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBaseObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBaseObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBaseObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,82 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.pool;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ */
+public class TestBaseObjectPool extends TestCase {
+    public TestBaseObjectPool(String testName) {
+        super(testName);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestBaseObjectPool.class);
+    }
+    
+    // tests
+    public void testUnsupportedOperations() throws Exception {
+        ObjectPool pool = new BaseObjectPool() { 
+            public Object borrowObject() throws Exception {
+                return null;
+            }
+            public void returnObject(Object obj) throws Exception {                
+            }
+            public void invalidateObject(Object obj) throws Exception {                
+            }            
+        };   
+        
+        try {
+            pool.getNumIdle();
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+
+        try {
+            pool.getNumActive();
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+
+        try {
+            pool.clear();
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+
+        try {
+            pool.addObject();
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+
+        try {
+            pool.setFactory(null);
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException e) {
+            // expected
+        }
+    }
+}

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBasePoolableObjectFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBasePoolableObjectFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestBasePoolableObjectFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,48 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.pool;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ */
+public class TestBasePoolableObjectFactory extends TestCase {
+    public TestBasePoolableObjectFactory(String testName) {
+        super(testName);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestBasePoolableObjectFactory.class);
+    }
+    
+    // tests
+    public void testDefaultMethods() throws Exception {
+        PoolableObjectFactory factory = new BasePoolableObjectFactory() { 
+            public Object makeObject() throws Exception {
+                return null;
+            }
+        };   
+        
+        factory.activateObject(null); // a no-op
+        factory.passivateObject(null); // a no-op
+        factory.destroyObject(null); // a no-op
+        assertTrue(factory.validateObject(null)); // constant true
+    }
+}

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestKeyedObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestKeyedObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestKeyedObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,281 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.pool;
+
+import junit.framework.TestCase;
+
+/**
+ * Abstract {@link TestCase} for {@link ObjectPool} implementations.
+ * @author Rodney Waldhoff
+ * @version $Revision: 383290 $ $Date: 2006-03-05 02:00:15 -0500 (Sun, 05 Mar 2006) $
+ */
+public abstract class TestKeyedObjectPool extends TestCase {
+    public TestKeyedObjectPool(String testName) {
+        super(testName);
+    }
+
+    /** 
+     * Create an {@link KeyedObjectPool} instance
+     * that can contain at least <i>mincapacity</i>
+     * idle and active objects, or
+     * throw {@link IllegalArgumentException}
+     * if such a pool cannot be created.
+     */
+    protected abstract KeyedObjectPool makeEmptyPool(int mincapacity);
+
+    /**
+     * Return what we expect to be the n<sup>th</sup>
+     * object (zero indexed) created by the pool
+     * for the given key.
+     */
+    protected abstract Object getNthObject(Object key, int n);
+
+    protected abstract Object makeKey(int n);
+
+    /**
+     * Is the implementations LIFO?
+     * @return
+     */
+    protected abstract boolean isLifo();
+    
+    /**
+     * Is the implementationn FIFO?
+     * @return
+     */
+    protected abstract boolean isFifo();
+
+    public void setUp() throws Exception {
+    }
+    
+    public void tearDown() throws Exception {
+        _pool = null;
+    }
+    
+    public void testBaseBorrow() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        Object keya = makeKey(0);
+        Object keyb = makeKey(1);
+        assertEquals("1",getNthObject(keya,0),_pool.borrowObject(keya));
+        assertEquals("2",getNthObject(keyb,0),_pool.borrowObject(keyb));
+        assertEquals("3",getNthObject(keyb,1),_pool.borrowObject(keyb));
+        assertEquals("4",getNthObject(keya,1),_pool.borrowObject(keya));
+        assertEquals("5",getNthObject(keyb,2),_pool.borrowObject(keyb));
+        assertEquals("6",getNthObject(keya,2),_pool.borrowObject(keya));
+    }
+
+    public void testBaseBorrowReturn() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        Object keya = makeKey(0);
+        Object obj0 = _pool.borrowObject(keya);
+        assertEquals(getNthObject(keya,0),obj0);
+        Object obj1 = _pool.borrowObject(keya);
+        assertEquals(getNthObject(keya,1),obj1);
+        Object obj2 = _pool.borrowObject(keya);
+        assertEquals(getNthObject(keya,2),obj2);
+        _pool.returnObject(keya,obj2);
+        obj2 = _pool.borrowObject(keya);
+        assertEquals(getNthObject(keya,2),obj2);
+        _pool.returnObject(keya,obj1);
+        obj1 = _pool.borrowObject(keya);
+        assertEquals(getNthObject(keya,1),obj1);
+        _pool.returnObject(keya,obj0);
+        _pool.returnObject(keya,obj2);
+        obj2 = _pool.borrowObject(keya);
+        if (isLifo()) {
+            assertEquals(getNthObject(keya,2),obj2);
+        }
+        if (isFifo()) {
+            assertEquals(getNthObject(keya,0),obj2);
+        }
+        obj0 = _pool.borrowObject(keya);
+        if (isLifo()) {
+            assertEquals(getNthObject(keya,0),obj0);
+        }
+        if (isFifo()) {
+            assertEquals(getNthObject(keya,2),obj0);
+        }
+    }
+
+    public void testBaseNumActiveNumIdle() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        Object keya = makeKey(0);
+        assertEquals(0,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+        Object obj0 = _pool.borrowObject(keya);
+        assertEquals(1,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+        Object obj1 = _pool.borrowObject(keya);
+        assertEquals(2,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+        _pool.returnObject(keya,obj1);
+        assertEquals(1,_pool.getNumActive(keya));
+        assertEquals(1,_pool.getNumIdle(keya));
+        _pool.returnObject(keya,obj0);
+        assertEquals(0,_pool.getNumActive(keya));
+        assertEquals(2,_pool.getNumIdle(keya));
+        
+        assertEquals(0,_pool.getNumActive("xyzzy12345"));
+        assertEquals(0,_pool.getNumIdle("xyzzy12345"));
+    }
+
+    public void testBaseNumActiveNumIdle2() throws Exception {
+        try {
+            _pool = makeEmptyPool(6);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        Object keya = makeKey(0);
+        Object keyb = makeKey(1);
+        assertEquals(0,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+        assertEquals(0,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+        assertEquals(0,_pool.getNumActive(keyb));
+        assertEquals(0,_pool.getNumIdle(keyb));
+
+        Object objA0 = _pool.borrowObject(keya);
+        Object objB0 = _pool.borrowObject(keyb);
+
+        assertEquals(2,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+        assertEquals(1,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+        assertEquals(1,_pool.getNumActive(keyb));
+        assertEquals(0,_pool.getNumIdle(keyb));
+
+        Object objA1 = _pool.borrowObject(keya);
+        Object objB1 = _pool.borrowObject(keyb);
+
+        assertEquals(4,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+        assertEquals(2,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+        assertEquals(2,_pool.getNumActive(keyb));
+        assertEquals(0,_pool.getNumIdle(keyb));
+
+        _pool.returnObject(keya,objA0);
+        _pool.returnObject(keyb,objB0);
+
+        assertEquals(2,_pool.getNumActive());
+        assertEquals(2,_pool.getNumIdle());
+        assertEquals(1,_pool.getNumActive(keya));
+        assertEquals(1,_pool.getNumIdle(keya));
+        assertEquals(1,_pool.getNumActive(keyb));
+        assertEquals(1,_pool.getNumIdle(keyb));
+
+        _pool.returnObject(keya,objA1);
+        _pool.returnObject(keyb,objB1);
+
+        assertEquals(0,_pool.getNumActive());
+        assertEquals(4,_pool.getNumIdle());
+        assertEquals(0,_pool.getNumActive(keya));
+        assertEquals(2,_pool.getNumIdle(keya));
+        assertEquals(0,_pool.getNumActive(keyb));
+        assertEquals(2,_pool.getNumIdle(keyb));
+    }
+
+    public void testBaseClear() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        Object keya = makeKey(0);
+        assertEquals(0,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+        Object obj0 = _pool.borrowObject(keya);
+        Object obj1 = _pool.borrowObject(keya);
+        assertEquals(2,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+        _pool.returnObject(keya,obj1);
+        _pool.returnObject(keya,obj0);
+        assertEquals(0,_pool.getNumActive(keya));
+        assertEquals(2,_pool.getNumIdle(keya));
+        _pool.clear(keya);
+        assertEquals(0,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+        Object obj2 = _pool.borrowObject(keya);
+        assertEquals(getNthObject(keya,2),obj2);
+    }
+
+    public void testBaseInvalidateObject() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        Object keya = makeKey(0);
+        assertEquals(0,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+        Object obj0 = _pool.borrowObject(keya);
+        Object obj1 = _pool.borrowObject(keya);
+        assertEquals(2,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+        _pool.invalidateObject(keya,obj0);
+        assertEquals(1,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+        _pool.invalidateObject(keya,obj1);
+        assertEquals(0,_pool.getNumActive(keya));
+        assertEquals(0,_pool.getNumIdle(keya));
+    }
+
+    public void testBaseAddObject() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        Object key = makeKey(0);
+        try {
+            assertEquals(0,_pool.getNumIdle());
+            assertEquals(0,_pool.getNumActive());
+            assertEquals(0,_pool.getNumIdle(key));
+            assertEquals(0,_pool.getNumActive(key));
+            _pool.addObject(key);
+            assertEquals(1,_pool.getNumIdle());
+            assertEquals(0,_pool.getNumActive());
+            assertEquals(1,_pool.getNumIdle(key));
+            assertEquals(0,_pool.getNumActive(key));
+            Object obj = _pool.borrowObject(key);
+            assertEquals(getNthObject(key,0),obj);
+            assertEquals(0,_pool.getNumIdle());
+            assertEquals(1,_pool.getNumActive());
+            assertEquals(0,_pool.getNumIdle(key));
+            assertEquals(1,_pool.getNumActive(key));
+            _pool.returnObject(key,obj);
+            assertEquals(1,_pool.getNumIdle());
+            assertEquals(0,_pool.getNumActive());
+            assertEquals(1,_pool.getNumIdle(key));
+            assertEquals(0,_pool.getNumActive(key));
+        } catch(UnsupportedOperationException e) {
+            return; // skip this test if one of those calls is unsupported
+        }
+    }
+
+    private KeyedObjectPool _pool = null;
+}

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,238 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.pool;
+
+import junit.framework.TestCase;
+
+/**
+ * Abstract {@link TestCase} for {@link ObjectPool} implementations.
+ * @author Rodney Waldhoff
+ * @version $Revision: 383290 $ $Date: 2006-03-05 02:00:15 -0500 (Sun, 05 Mar 2006) $
+ */
+public abstract class TestObjectPool extends TestCase {
+    public TestObjectPool(String testName) {
+        super(testName);
+    }
+
+    /** 
+     * Create an {@link ObjectPool} instance
+     * that can contain at least <i>mincapacity</i>
+     * idle and active objects, or
+     * throw {@link IllegalArgumentException}
+     * if such a pool cannot be created.
+     */
+    protected abstract ObjectPool makeEmptyPool(int mincapacity);
+
+    /**
+     * Return what we expect to be the n<sup>th</sup>
+     * object (zero indexed) created by the _pool.
+     */
+    protected abstract Object getNthObject(int n);
+    
+    /**
+     * Is the implementations LIFO?
+     * @return
+     */
+    protected abstract boolean isLifo();
+    
+    /**
+     * Is the implementationn FIFO?
+     * @return
+     */
+    protected abstract boolean isFifo();
+
+    public void setUp() throws Exception {
+    }
+    
+    public void tearDown() throws Exception {
+        _pool = null;
+    }
+    
+    public void testBaseBorrow() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        assertEquals(getNthObject(0),_pool.borrowObject());
+        assertEquals(getNthObject(1),_pool.borrowObject());
+        assertEquals(getNthObject(2),_pool.borrowObject());
+    }
+
+    public void testBaseAddObject() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        try {
+            assertEquals(0,_pool.getNumIdle());
+            assertEquals(0,_pool.getNumActive());
+            _pool.addObject();
+            assertEquals(1,_pool.getNumIdle());
+            assertEquals(0,_pool.getNumActive());
+            Object obj = _pool.borrowObject();
+            assertEquals(getNthObject(0),obj);
+            assertEquals(0,_pool.getNumIdle());
+            assertEquals(1,_pool.getNumActive());
+            _pool.returnObject(obj);
+            assertEquals(1,_pool.getNumIdle());
+            assertEquals(0,_pool.getNumActive());
+        } catch(UnsupportedOperationException e) {
+            return; // skip this test if one of those calls is unsupported
+        }
+    }
+    
+    public void testBaseBorrowReturn() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        Object obj0 = _pool.borrowObject();
+        assertEquals(getNthObject(0),obj0);
+        Object obj1 = _pool.borrowObject();
+        assertEquals(getNthObject(1),obj1);
+        Object obj2 = _pool.borrowObject();
+        assertEquals(getNthObject(2),obj2);
+        _pool.returnObject(obj2);
+        obj2 = _pool.borrowObject();
+        assertEquals(getNthObject(2),obj2);
+        _pool.returnObject(obj1);
+        obj1 = _pool.borrowObject();
+        assertEquals(getNthObject(1),obj1);
+        _pool.returnObject(obj0);
+        _pool.returnObject(obj2);
+        obj2 = _pool.borrowObject();
+        if (isLifo()) {
+            assertEquals(getNthObject(2),obj2);
+        }
+        if (isFifo()) {
+            assertEquals(getNthObject(0),obj2);
+        }
+            
+        obj0 = _pool.borrowObject();
+        if (isLifo()) {
+            assertEquals(getNthObject(0),obj0);
+        }
+        if (isFifo()) {
+            assertEquals(getNthObject(2),obj0);
+        }
+    }
+
+    public void testBaseNumActiveNumIdle() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        assertEquals(0,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+        Object obj0 = _pool.borrowObject();
+        assertEquals(1,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+        Object obj1 = _pool.borrowObject();
+        assertEquals(2,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+        _pool.returnObject(obj1);
+        assertEquals(1,_pool.getNumActive());
+        assertEquals(1,_pool.getNumIdle());
+        _pool.returnObject(obj0);
+        assertEquals(0,_pool.getNumActive());
+        assertEquals(2,_pool.getNumIdle());
+    }
+
+    public void testBaseClear() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        assertEquals(0,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+        Object obj0 = _pool.borrowObject();
+        Object obj1 = _pool.borrowObject();
+        assertEquals(2,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+        _pool.returnObject(obj1);
+        _pool.returnObject(obj0);
+        assertEquals(0,_pool.getNumActive());
+        assertEquals(2,_pool.getNumIdle());
+        _pool.clear();
+        assertEquals(0,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+        Object obj2 = _pool.borrowObject();
+        assertEquals(getNthObject(2),obj2);
+    }
+
+    public void testBaseInvalidateObject() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        assertEquals(0,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+        Object obj0 = _pool.borrowObject();
+        Object obj1 = _pool.borrowObject();
+        assertEquals(2,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+        _pool.invalidateObject(obj0);
+        assertEquals(1,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+        _pool.invalidateObject(obj1);
+        assertEquals(0,_pool.getNumActive());
+        assertEquals(0,_pool.getNumIdle());
+    }
+    
+    public void testBaseClosePool() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        Object obj = _pool.borrowObject();
+        _pool.returnObject(obj);
+        
+        _pool.close();
+        try {
+            _pool.borrowObject();
+            fail("Expected IllegalStateException");
+        } catch(IllegalStateException e) {
+            // expected
+        }
+    }
+
+    public void testBaseCantCloseTwice() throws Exception {
+        try {
+            _pool = makeEmptyPool(3);
+        } catch(IllegalArgumentException e) {
+            return; // skip this test if unsupported
+        }
+        Object obj = _pool.borrowObject();
+        _pool.returnObject(obj);
+        
+        _pool.close();
+        try {
+            _pool.close();
+            fail("Expected IllegalStateException");
+        } catch(IllegalStateException e) {
+            // expected
+        }
+    }
+
+    private ObjectPool _pool = null;
+}

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestPoolUtils.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestPoolUtils.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/TestPoolUtils.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,658 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool;
+
+import junit.framework.TestCase;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import java.lang.reflect.Proxy;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.TimerTask;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link PoolUtils}.
+ *
+ * @author Sandy McArthur
+ * @version $Revision: 384433 $ $Date: 2006-03-09 00:19:21 -0500 (Thu, 09 Mar 2006) $
+ */
+public class TestPoolUtils extends TestCase {
+
+    /** Period between checks for minIdle tests. Increase this if you happen to get too many false failures. */
+    private static final int CHECK_PERIOD = 300;
+
+    /** Times to let the minIdle check run. */
+    private static final int CHECK_COUNT = 4;
+
+    /** Sleep time to let the minIdle tests run CHECK_COUNT times. */
+    private static final int CHECK_SLEEP_PERIOD = CHECK_PERIOD * (CHECK_COUNT - 1) + CHECK_PERIOD / 2;
+
+    public static Test suite() {
+        return new TestSuite(TestPoolUtils.class);
+    }
+
+    public void testJavaBeanInstantiation() {
+        new PoolUtils();
+    }
+
+    public void testAdaptKeyedPoolableObjectFactory() throws Exception {
+        try {
+            PoolUtils.adapt((KeyedPoolableObjectFactory)null);
+            fail("PoolUtils.adapt(KeyedPoolableObjectFactory) must not allow null factory.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+    }
+
+    public void testAdaptKeyedPoolableObjectFactoryKey() throws Exception {
+        try {
+            PoolUtils.adapt((KeyedPoolableObjectFactory)null, new Object());
+            fail("PoolUtils.adapt(KeyedPoolableObjectFactory, key) must not allow null factory.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+        try {
+            PoolUtils.adapt((KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, null), null);
+            fail("PoolUtils.adapt(KeyedPoolableObjectFactory, key) must not allow null key.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final KeyedPoolableObjectFactory kpof =
+                (KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, calledMethods);
+
+        final PoolableObjectFactory pof = PoolUtils.adapt(kpof);
+        final List expectedMethods = invokeEveryMethod(pof);
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testAdaptPoolableObjectFactory() throws Exception {
+        try {
+            PoolUtils.adapt((PoolableObjectFactory)null);
+            fail("PoolUtils.adapt(PoolableObjectFactory) must not allow null factory.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final PoolableObjectFactory pof =
+                (PoolableObjectFactory)createProxy(PoolableObjectFactory.class, calledMethods);
+
+        final KeyedPoolableObjectFactory kpof = PoolUtils.adapt(pof);
+        final List expectedMethods = invokeEveryMethod(kpof);
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testAdaptKeyedObjectPool() throws Exception {
+        try {
+            PoolUtils.adapt((KeyedObjectPool)null);
+            fail("PoolUtils.adapt(KeyedObjectPool) must not allow a null pool.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+    }
+
+    public void testAdaptKeyedObjectPoolKey() throws Exception {
+        try {
+            PoolUtils.adapt((KeyedObjectPool)null, new Object());
+            fail("PoolUtils.adapt(KeyedObjectPool, key) must not allow a null pool.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+        try {
+            PoolUtils.adapt((KeyedObjectPool)createProxy(KeyedObjectPool.class, null), null);
+            fail("PoolUtils.adapt(KeyedObjectPool, key) must not allow a null key.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final KeyedObjectPool kop = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
+
+        final ObjectPool op = PoolUtils.adapt(kop, new Object());
+        final List expectedMethods = invokeEveryMethod(op);
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testAdaptObjectPool() throws Exception {
+        try {
+            PoolUtils.adapt((ObjectPool)null);
+            fail("PoolUtils.adapt(ObjectPool) must not allow a null pool.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final ObjectPool op = (ObjectPool)createProxy(ObjectPool.class, calledMethods);
+
+        final KeyedObjectPool kop = PoolUtils.adapt(op);
+        final List expectedMethods = invokeEveryMethod(kop);
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testCheckedPoolObjectPool() throws Exception {
+        try {
+            PoolUtils.checkedPool((ObjectPool)null, Object.class);
+            fail("PoolUtils.checkedPool(ObjectPool, Class) must not allow a null pool.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+        try {
+            PoolUtils.checkedPool((ObjectPool)createProxy(ObjectPool.class, null), null);
+            fail("PoolUtils.checkedPool(ObjectPool, Class) must not allow a null type.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        ObjectPool op = (ObjectPool)createProxy(ObjectPool.class, calledMethods);
+
+        ObjectPool cop = PoolUtils.checkedPool(op, Object.class);
+        final List expectedMethods = invokeEveryMethod(cop);
+        assertEquals(expectedMethods, calledMethods);
+
+        op = new BaseObjectPool() {
+            public Object borrowObject() throws Exception {
+                return new Integer(0);
+            }
+            public void returnObject(Object obj) {}
+            public void invalidateObject(Object obj) {}
+        };
+        cop = PoolUtils.checkedPool(op, String.class);
+
+        try {
+            cop.borrowObject();
+            fail("borrowObject should have failed as Integer !instanceof String.");
+        } catch (ClassCastException cce) {
+            // expected
+        }
+        try {
+            cop.returnObject(new Integer(1));
+            fail("returnObject should have failed as Integer !instanceof String.");
+        } catch (ClassCastException cce) {
+            // expected
+        }
+        try {
+            cop.invalidateObject(new Integer(2));
+            fail("invalidateObject should have failed as Integer !instanceof String.");
+        } catch (ClassCastException cce) {
+            // expected
+        }
+    }
+
+    public void testCheckedPoolKeyedObjectPool() throws Exception {
+        try {
+            PoolUtils.checkedPool((KeyedObjectPool)null, Object.class);
+            fail("PoolUtils.checkedPool(KeyedObjectPool, Class) must not allow a null pool.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+        try {
+            PoolUtils.checkedPool((KeyedObjectPool)createProxy(KeyedObjectPool.class, null), null);
+            fail("PoolUtils.checkedPool(KeyedObjectPool, Class) must not allow a null type.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        KeyedObjectPool op = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
+
+        KeyedObjectPool cop = PoolUtils.checkedPool(op, Object.class);
+        final List expectedMethods = invokeEveryMethod(cop);
+        assertEquals(expectedMethods, calledMethods);
+
+
+        op = new BaseKeyedObjectPool() {
+            public Object borrowObject(Object key) {
+                return new Integer(0);
+            }
+
+            public void returnObject(Object key, Object obj) {}
+
+            public void invalidateObject(Object key, Object obj) {}
+        };
+        cop = PoolUtils.checkedPool(op, String.class);
+
+        try {
+            cop.borrowObject(null);
+            fail("borrowObject should have failed as Integer !instanceof String.");
+        } catch (ClassCastException cce) {
+            // expected
+        }
+        try {
+            cop.returnObject(null, new Integer(1));
+            fail("returnObject should have failed as Integer !instanceof String.");
+        } catch (ClassCastException cce) {
+            // expected
+        }
+        try {
+            cop.invalidateObject(null, new Integer(2));
+            fail("invalidateObject should have failed as Integer !instanceof String.");
+        } catch (ClassCastException cce) {
+            // expected
+        }
+    }
+
+    public void testCheckMinIdleObjectPool() throws Exception {
+        try {
+            PoolUtils.checkMinIdle(null, 1, 1);
+            fail("PoolUtils.checkMinIdle(ObjectPool,,) must not allow null pool.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+        try {
+            final ObjectPool pool = (ObjectPool)createProxy(ObjectPool.class, null);
+            PoolUtils.checkMinIdle(pool, -1, 1);
+            fail("PoolUtils.checkMinIdle(ObjectPool,,) must not accept negative min idle values.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        // Because this isn't determinist and you can get false failures, try more than once.
+        AssertionFailedError afe = null;
+        int triesLeft = 3;
+        do {
+            afe = null;
+            try {
+                final List calledMethods = new ArrayList();
+                final ObjectPool pool = (ObjectPool)createProxy(ObjectPool.class, calledMethods);
+                final TimerTask task = PoolUtils.checkMinIdle(pool, 1, CHECK_PERIOD); // checks minIdle immediately
+
+                Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times.
+                task.cancel();
+                task.toString();
+
+                final List expectedMethods = new ArrayList();
+                for (int i=0; i < CHECK_COUNT; i++) {
+                    expectedMethods.add("getNumIdle");
+                    expectedMethods.add("addObject");
+                }
+                expectedMethods.add("toString");
+                assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler
+            } catch (AssertionFailedError e) {
+                afe = e;
+            }
+        } while (--triesLeft > 0 && afe != null);
+        if (afe != null) {
+            throw afe;
+        }
+    }
+
+    public void testCheckMinIdleKeyedObjectPool() throws Exception {
+        try {
+            PoolUtils.checkMinIdle(null, new Object(), 1, 1);
+            fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not allow null pool.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+        try {
+            final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, null);
+            PoolUtils.checkMinIdle(pool, (Object)null, 1, 1);
+            fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not accept null keys.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+        try {
+            final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, null);
+            PoolUtils.checkMinIdle(pool, new Object(), -1, 1);
+            fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not accept negative min idle values.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        // Because this isn't determinist and you can get false failures, try more than once.
+        AssertionFailedError afe = null;
+        int triesLeft = 3;
+        do {
+            afe = null;
+            try {
+                final List calledMethods = new ArrayList();
+                final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
+                final Object key = new Object();
+                final TimerTask task = PoolUtils.checkMinIdle(pool, key, 1, CHECK_PERIOD); // checks minIdle immediately
+
+                Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times.
+                task.cancel();
+                task.toString();
+
+                final List expectedMethods = new ArrayList();
+                for (int i=0; i < CHECK_COUNT; i++) {
+                    expectedMethods.add("getNumIdle");
+                    expectedMethods.add("addObject");
+                }
+                expectedMethods.add("toString");
+                assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler
+            } catch (AssertionFailedError e) {
+                afe = e;
+            }
+        } while (--triesLeft > 0 && afe != null);
+        if (afe != null) {
+            throw afe;
+        }
+    }
+
+    public void testCheckMinIdleKeyedObjectPoolKeys() throws Exception {
+        try {
+            final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, null);
+            PoolUtils.checkMinIdle(pool, null, 1, 1);
+            fail("PoolUtils.checkMinIdle(KeyedObjectPool,Collection,int,long) must not accept null keys.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        // Because this isn't determinist and you can get false failures, try more than once.
+        AssertionFailedError afe = null;
+        int triesLeft = 3;
+        do {
+            afe = null;
+            try {
+                final List calledMethods = new ArrayList();
+                final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
+                final Collection keys = new ArrayList(2);
+                keys.add("one");
+                keys.add("two");
+                final Map tasks = PoolUtils.checkMinIdle(pool, keys, 1, CHECK_PERIOD); // checks minIdle immediately
+
+                Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times.
+                final Iterator iter = tasks.values().iterator();
+                while (iter.hasNext()) {
+                    final TimerTask task = (TimerTask)iter.next();
+                    task.cancel();
+                }
+
+                final List expectedMethods = new ArrayList();
+                for (int i=0; i < CHECK_COUNT * keys.size(); i++) {
+                    expectedMethods.add("getNumIdle");
+                    expectedMethods.add("addObject");
+                }
+                assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler
+            } catch (AssertionFailedError e) {
+                afe = e;
+            }
+        } while (--triesLeft > 0 && afe != null);
+        if (afe != null) {
+            throw afe;
+        }
+    }
+
+    public void testPrefillObjectPool() throws Exception {
+        try {
+            PoolUtils.prefill(null, 1);
+            fail("PoolUtils.prefill(ObjectPool,int) must not allow null pool.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final ObjectPool pool = (ObjectPool)createProxy(ObjectPool.class, calledMethods);
+
+        PoolUtils.prefill(pool, 0);
+        final List expectedMethods = new ArrayList();
+        assertEquals(expectedMethods, calledMethods);
+
+        calledMethods.clear();
+        PoolUtils.prefill(pool, 3);
+        for (int i=0; i < 3; i++) {
+            expectedMethods.add("addObject");
+        }
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testPrefillKeyedObjectPool() throws Exception {
+        try {
+            PoolUtils.prefill(null, new Object(), 1);
+            fail("PoolUtils.prefill(KeyedObjectPool,Object,int) must not accept null pool.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+        try {
+            final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, null);
+            PoolUtils.prefill(pool, (Object)null, 1);
+            fail("PoolUtils.prefill(KeyedObjectPool,Object,int) must not accept null key.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
+
+        PoolUtils.prefill(pool, new Object(), 0);
+        final List expectedMethods = new ArrayList();
+        assertEquals(expectedMethods, calledMethods);
+
+        calledMethods.clear();
+        PoolUtils.prefill(pool, new Object(), 3);
+        for (int i=0; i < 3; i++) {
+            expectedMethods.add("addObject");
+        }
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testPrefillKeyedObjectPoolCollection() throws Exception {
+        try {
+            final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, null);
+            PoolUtils.prefill(pool, null, 1);
+            fail("PoolUtils.prefill(KeyedObjectPool,Collection,int) must not accept null keys.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
+
+        final Set keys = new HashSet();
+        PoolUtils.prefill(pool, keys, 0);
+        final List expectedMethods = new ArrayList();
+        assertEquals(expectedMethods, calledMethods);
+
+        calledMethods.clear();
+        keys.add(new Integer(1));
+        keys.add("two");
+        keys.add(new Double(3.1415926));
+        PoolUtils.prefill(pool, keys, 3);
+        for (int i=0; i < keys.size() * 3; i++) {
+            expectedMethods.add("addObject");
+        }
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testSynchronizedPoolObjectPool() throws Exception {
+        try {
+            PoolUtils.synchronizedPool((ObjectPool)null);
+            fail("PoolUtils.synchronizedPool(ObjectPool) must not allow a null pool.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final ObjectPool op = (ObjectPool)createProxy(ObjectPool.class, calledMethods);
+
+        final ObjectPool sop = PoolUtils.synchronizedPool(op);
+        final List expectedMethods = invokeEveryMethod(sop);
+        assertEquals(expectedMethods, calledMethods);
+
+        // TODO: Anyone feel motivated to construct a test that verifies proper synchronization?
+    }
+
+    public void testSynchronizedPoolKeyedObjectPool() throws Exception {
+        try {
+            PoolUtils.synchronizedPool((KeyedObjectPool)null);
+            fail("PoolUtils.synchronizedPool(KeyedObjectPool) must not allow a null pool.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final KeyedObjectPool kop = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
+
+        final KeyedObjectPool skop = PoolUtils.synchronizedPool(kop);
+        final List expectedMethods = invokeEveryMethod(skop);
+        assertEquals(expectedMethods, calledMethods);
+
+        // TODO: Anyone feel motivated to construct a test that verifies proper synchronization?
+    }
+
+    public void testSynchronizedPoolableFactoryPoolableObjectFactory() throws Exception {
+        try {
+            PoolUtils.synchronizedPoolableFactory((PoolableObjectFactory)null);
+            fail("PoolUtils.synchronizedPoolableFactory(PoolableObjectFactory) must not allow a null factory.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final PoolableObjectFactory pof =
+                (PoolableObjectFactory)createProxy(PoolableObjectFactory.class, calledMethods);
+
+        final PoolableObjectFactory spof = PoolUtils.synchronizedPoolableFactory(pof);
+        final List expectedMethods = invokeEveryMethod(spof);
+        assertEquals(expectedMethods, calledMethods);
+
+        // TODO: Anyone feel motivated to construct a test that verifies proper synchronization?
+    }
+
+    public void testSynchronizedPoolableFactoryKeyedPoolableObjectFactory() throws Exception {
+        try {
+            PoolUtils.synchronizedPoolableFactory((KeyedPoolableObjectFactory)null);
+            fail("PoolUtils.synchronizedPoolableFactory(KeyedPoolableObjectFactory) must not allow a null factory.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final KeyedPoolableObjectFactory kpof =
+                (KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, calledMethods);
+
+        final KeyedPoolableObjectFactory skpof = PoolUtils.synchronizedPoolableFactory(kpof);
+        final List expectedMethods = invokeEveryMethod(skpof);
+        assertEquals(expectedMethods, calledMethods);
+
+        // TODO: Anyone feel motivated to construct a test that verifies proper synchronization?
+    }
+
+    private static List invokeEveryMethod(ObjectPool op) throws Exception {
+        op.addObject();
+        op.borrowObject();
+        op.clear();
+        op.close();
+        op.getNumActive();
+        op.getNumIdle();
+        op.invalidateObject(new Object());
+        op.returnObject(new Object());
+        op.setFactory((PoolableObjectFactory)createProxy(PoolableObjectFactory.class, null));
+        op.toString();
+
+        final List expectedMethods = Arrays.asList(new String[] {
+                "addObject", "borrowObject", "clear", "close",
+                "getNumActive", "getNumIdle", "invalidateObject",
+                "returnObject", "setFactory", "toString"
+        });
+        return expectedMethods;
+    }
+
+    private static List invokeEveryMethod(KeyedObjectPool kop) throws Exception {
+        kop.addObject(null);
+        kop.borrowObject(null);
+        kop.clear();
+        kop.clear(null);
+        kop.close();
+        kop.getNumActive();
+        kop.getNumActive(null);
+        kop.getNumIdle();
+        kop.getNumIdle(null);
+        kop.invalidateObject(null, new Object());
+        kop.returnObject(null, new Object());
+        kop.setFactory((KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, null));
+        kop.toString();
+
+        final List expectedMethods = Arrays.asList(new String[] {
+                "addObject", "borrowObject", "clear", "clear", "close",
+                "getNumActive", "getNumActive", "getNumIdle", "getNumIdle", "invalidateObject",
+                "returnObject", "setFactory", "toString"
+        });
+        return expectedMethods;
+    }
+
+    private static List invokeEveryMethod(PoolableObjectFactory pof) throws Exception {
+        pof.activateObject(null);
+        pof.destroyObject(null);
+        pof.makeObject();
+        pof.passivateObject(null);
+        pof.validateObject(null);
+        pof.toString();
+
+        final List expectedMethods = Arrays.asList(new String[] {
+                "activateObject", "destroyObject", "makeObject",
+                "passivateObject", "validateObject", "toString",
+        });
+        return expectedMethods;
+    }
+
+    private static List invokeEveryMethod(KeyedPoolableObjectFactory kpof) throws Exception {
+        kpof.activateObject(null, null);
+        kpof.destroyObject(null, null);
+        kpof.makeObject(null);
+        kpof.passivateObject(null, null);
+        kpof.validateObject(null, null);
+        kpof.toString();
+
+        final List expectedMethods = Arrays.asList(new String[] {
+                "activateObject", "destroyObject", "makeObject",
+                "passivateObject", "validateObject", "toString",
+        });
+        return expectedMethods;
+    }
+
+    private static Object createProxy(final Class clazz, final List logger) {
+        return Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz },
+                new MethodCallLogger(logger));
+    }
+
+    private static class MethodCallLogger implements InvocationHandler {
+        private final List calledMethods;
+
+        MethodCallLogger(final List calledMethods) {
+            this.calledMethods = calledMethods;
+        }
+
+        public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+            calledMethods.add(method.getName());
+            if (boolean.class.equals(method.getReturnType())) {
+                return Boolean.FALSE;
+            } else if (int.class.equals(method.getReturnType())) {
+                return new Integer(0);
+            } else if (long.class.equals(method.getReturnType())) {
+                return new Long(0);
+            } else if (Object.class.equals(method.getReturnType())) {
+                return new Object();
+            } else {
+                return null;
+            }
+        }
+    }
+}

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestAll.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestAll.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestAll.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,49 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * JUnit test suite for the {@link org.apache.commons.pool.impl}
+ * package.
+ *
+ * @author Rodney Waldhoff
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $
+ */
+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());
+        suite.addTest(TestSoftReferenceObjectPool.suite());
+        return suite;
+    }
+
+    public static void main(String args[]) {
+        String[] testCaseName = { TestAll.class.getName() };
+        junit.textui.TestRunner.main(testCaseName);
+    }
+}

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestGenericKeyedObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,699 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import java.util.HashMap;
+import java.util.NoSuchElementException;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.commons.pool.KeyedObjectPool;
+import org.apache.commons.pool.KeyedPoolableObjectFactory;
+import org.apache.commons.pool.TestKeyedObjectPool;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Revision: 383290 $ $Date: 2006-03-05 02:00:15 -0500 (Sun, 05 Mar 2006) $
+ */
+public class TestGenericKeyedObjectPool extends TestKeyedObjectPool {
+    public TestGenericKeyedObjectPool(String testName) {
+        super(testName);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestGenericKeyedObjectPool.class);
+    }
+
+    protected KeyedObjectPool makeEmptyPool(int mincapacity) {
+        GenericKeyedObjectPool pool = new GenericKeyedObjectPool(
+            new KeyedPoolableObjectFactory()  {
+                HashMap map = new HashMap();
+                public Object makeObject(Object key) {
+                    int counter = 0;
+                    Integer Counter = (Integer)(map.get(key));
+                    if(null != Counter) {
+                        counter = Counter.intValue();
+                    }
+                    map.put(key,new Integer(counter + 1));
+                    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) { }
+            }
+        );
+        pool.setMaxActive(mincapacity);
+        pool.setMaxIdle(mincapacity);
+        return pool;
+    }
+
+    protected Object getNthObject(Object key, int n) {
+        return String.valueOf(key) + String.valueOf(n);
+    }
+
+    protected Object makeKey(int n) {
+        return String.valueOf(n);
+    }
+
+    private GenericKeyedObjectPool pool = null;
+
+    public void setUp() throws Exception {
+        super.setUp();
+        pool = new GenericKeyedObjectPool(new SimpleFactory());
+    }
+
+    public void tearDown() throws Exception {
+        super.tearDown();
+        pool.close();
+        pool = null;
+    }
+
+    public void testWithInitiallyInvalid() throws Exception {
+        GenericKeyedObjectPool pool = new GenericKeyedObjectPool(new SimpleFactory(false));
+        pool.setTestOnBorrow(true);
+        try {
+            pool.borrowObject("xyzzy");
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+    }
+
+    public void testNegativeMaxActive() throws Exception {
+        pool.setMaxActive(-1);
+        pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL);
+        Object obj = pool.borrowObject("");
+        assertEquals("0",obj);
+        pool.returnObject("",obj);
+    }
+
+    public void testNumActiveNumIdle2() throws Exception {
+        assertEquals(0,pool.getNumActive());
+        assertEquals(0,pool.getNumIdle());
+        assertEquals(0,pool.getNumActive("A"));
+        assertEquals(0,pool.getNumIdle("A"));
+        assertEquals(0,pool.getNumActive("B"));
+        assertEquals(0,pool.getNumIdle("B"));
+
+        Object objA0 = pool.borrowObject("A");
+        Object objB0 = pool.borrowObject("B");
+
+        assertEquals(2,pool.getNumActive());
+        assertEquals(0,pool.getNumIdle());
+        assertEquals(1,pool.getNumActive("A"));
+        assertEquals(0,pool.getNumIdle("A"));
+        assertEquals(1,pool.getNumActive("B"));
+        assertEquals(0,pool.getNumIdle("B"));
+
+        Object objA1 = pool.borrowObject("A");
+        Object objB1 = pool.borrowObject("B");
+
+        assertEquals(4,pool.getNumActive());
+        assertEquals(0,pool.getNumIdle());
+        assertEquals(2,pool.getNumActive("A"));
+        assertEquals(0,pool.getNumIdle("A"));
+        assertEquals(2,pool.getNumActive("B"));
+        assertEquals(0,pool.getNumIdle("B"));
+
+        pool.returnObject("A",objA0);
+        pool.returnObject("B",objB0);
+
+        assertEquals(2,pool.getNumActive());
+        assertEquals(2,pool.getNumIdle());
+        assertEquals(1,pool.getNumActive("A"));
+        assertEquals(1,pool.getNumIdle("A"));
+        assertEquals(1,pool.getNumActive("B"));
+        assertEquals(1,pool.getNumIdle("B"));
+
+        pool.returnObject("A",objA1);
+        pool.returnObject("B",objB1);
+
+        assertEquals(0,pool.getNumActive());
+        assertEquals(4,pool.getNumIdle());
+        assertEquals(0,pool.getNumActive("A"));
+        assertEquals(2,pool.getNumIdle("A"));
+        assertEquals(0,pool.getNumActive("B"));
+        assertEquals(2,pool.getNumIdle("B"));
+    }
+
+    public void testMaxIdle() throws Exception {
+        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.getNumActive(""));
+        assertEquals(0,pool.getNumIdle(""));
+        for(int i=0;i<100;i++) {
+            pool.returnObject("",active[i]);
+            assertEquals(99 - i,pool.getNumActive(""));
+            assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle(""));
+        }
+    }
+
+    public void testMaxActive() throws Exception {
+        pool.setMaxActive(3);
+        pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL);
+
+        pool.borrowObject("");
+        pool.borrowObject("");
+        pool.borrowObject("");
+        try {
+            pool.borrowObject("");
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+    }
+
+    public void testMaxActiveZero() throws Exception {
+        pool.setMaxActive(0);
+        pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
+
+        try {
+            pool.borrowObject("a");
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+    }
+
+    public void testMaxTotal() throws Exception {
+        pool.setMaxActive(2);
+        pool.setMaxTotal(3);
+        pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL);
+
+        Object o1 = pool.borrowObject("a");
+        assertNotNull(o1);
+        Object o2 = pool.borrowObject("a");
+        assertNotNull(o2);
+        Object o3 = pool.borrowObject("b");
+        assertNotNull(o3);
+        try {
+            pool.borrowObject("c");
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+
+        assertEquals(0, pool.getNumIdle());
+
+        pool.returnObject("b", o3);
+        assertEquals(1, pool.getNumIdle());
+        assertEquals(1, pool.getNumIdle("b"));
+
+        Object o4 = pool.borrowObject("b");
+        assertNotNull(o4);
+        assertEquals(0, pool.getNumIdle());
+        assertEquals(0, pool.getNumIdle("b"));
+    }
+
+    public void testMaxTotalZero() throws Exception {
+        pool.setMaxTotal(0);
+        pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
+
+        try {
+            pool.borrowObject("a");
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+    }
+
+    public void testMaxTotalLRU() throws Exception {
+        pool.setMaxActive(2);
+        pool.setMaxTotal(3);
+//        pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW);
+
+        Object o1 = pool.borrowObject("a");
+        assertNotNull(o1);
+        pool.returnObject("a", o1);
+        Thread.sleep(10);
+
+        Object o2 = pool.borrowObject("b");
+        assertNotNull(o2);
+        pool.returnObject("b", o2);
+        Thread.sleep(10);
+
+        Object o3 = pool.borrowObject("c");
+        assertNotNull(o3);
+        pool.returnObject("c", o3);
+        Thread.sleep(10);
+
+        Object o4 = pool.borrowObject("a");
+        assertNotNull(o4);
+        pool.returnObject("a", o4);
+        Thread.sleep(10);
+
+        assertSame(o1, o4);
+
+        // this should cause b to be bumped out of the pool
+        Object o5 = pool.borrowObject("d");
+        assertNotNull(o5);
+        pool.returnObject("d", o5);
+        Thread.sleep(10);
+
+        // now re-request b, we should get a different object because it should
+        // have been expelled from pool (was oldest because a was requested after b)
+        Object o6 = pool.borrowObject("b");
+        assertNotNull(o6);
+        pool.returnObject("b", o6);
+
+        assertNotSame(o1, o6);
+
+        // second a is still in there
+        Object o7 = pool.borrowObject("a");
+        assertNotNull(o7);
+        pool.returnObject("a", o7);
+
+        assertSame(o4, o7);
+    }
+
+    public void testSettersAndGetters() throws Exception {
+        GenericKeyedObjectPool pool = new GenericKeyedObjectPool();
+        {
+            pool.setFactory(new SimpleFactory());
+        }
+        {
+            pool.setMaxActive(123);
+            assertEquals(123,pool.getMaxActive());
+        }
+        {
+            pool.setMaxIdle(12);
+            assertEquals(12,pool.getMaxIdle());
+        }
+        {
+            pool.setMaxWait(1234L);
+            assertEquals(1234L,pool.getMaxWait());
+        }
+        {
+            pool.setMinEvictableIdleTimeMillis(12345L);
+            assertEquals(12345L,pool.getMinEvictableIdleTimeMillis());
+        }
+        {
+            pool.setNumTestsPerEvictionRun(11);
+            assertEquals(11,pool.getNumTestsPerEvictionRun());
+        }
+        {
+            pool.setTestOnBorrow(true);
+            assertTrue(pool.getTestOnBorrow());
+            pool.setTestOnBorrow(false);
+            assertTrue(!pool.getTestOnBorrow());
+        }
+        {
+            pool.setTestOnReturn(true);
+            assertTrue(pool.getTestOnReturn());
+            pool.setTestOnReturn(false);
+            assertTrue(!pool.getTestOnReturn());
+        }
+        {
+            pool.setTestWhileIdle(true);
+            assertTrue(pool.getTestWhileIdle());
+            pool.setTestWhileIdle(false);
+            assertTrue(!pool.getTestWhileIdle());
+        }
+        {
+            pool.setTimeBetweenEvictionRunsMillis(11235L);
+            assertEquals(11235L,pool.getTimeBetweenEvictionRunsMillis());
+        }
+        {
+            pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_BLOCK);
+            assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK,pool.getWhenExhaustedAction());
+            pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL);
+            assertEquals(GenericObjectPool.WHEN_EXHAUSTED_FAIL,pool.getWhenExhaustedAction());
+            pool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW);
+            assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW,pool.getWhenExhaustedAction());
+        }
+    }
+
+    public void testEviction() throws Exception {
+        pool.setMaxIdle(500);
+        pool.setMaxActive(500);
+        pool.setNumTestsPerEvictionRun(100);
+        pool.setMinEvictableIdleTimeMillis(250L);
+        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.sleep(1000L); } catch(Exception e) { }
+        assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 500);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 400);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 300);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 200);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 100);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertEquals("Should be zero idle, found " + pool.getNumIdle(""),0,pool.getNumIdle(""));
+
+        for(int i=0;i<500;i++) {
+            active[i] = pool.borrowObject("");
+        }
+        for(int i=0;i<500;i++) {
+            pool.returnObject("",active[i]);
+        }
+
+        try { Thread.sleep(1000L); } catch(Exception e) { }
+        assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 500);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 400);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 300);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 200);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(""),pool.getNumIdle("") < 100);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertEquals("Should be zero idle, found " + pool.getNumIdle(""),0,pool.getNumIdle(""));
+    }
+
+    public void testEviction2() throws Exception {
+        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.sleep(1000L); } catch(Exception e) { }
+        assertTrue("Should be less than 1000 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 1000);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 900 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 900);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 800 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 800);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 700 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 700);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 600 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 600);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
+    }
+
+    public void testThreaded1() throws Exception {
+        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.sleep(500L);
+                } catch(Exception e) {
+                    // ignored
+                }
+            }
+            if(threads[i].failed()) {
+                fail();
+            }
+        }
+    }
+
+    public void testMinIdle() throws Exception {
+        pool.setMaxIdle(500);
+        pool.setMinIdle(5);
+        pool.setMaxActive(10);
+        pool.setNumTestsPerEvictionRun(0);
+        pool.setMinEvictableIdleTimeMillis(50L);
+        pool.setTimeBetweenEvictionRunsMillis(100L);
+        pool.setTestWhileIdle(true);
+
+
+        //Generate a random key
+        String key = "A";
+
+        pool.preparePool(key, true);
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+
+        Object[] active = new Object[5];
+        active[0] = pool.borrowObject(key);
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+
+        for(int i=1 ; i<5 ; i++) {
+            active[i] = pool.borrowObject(key);
+        }
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+
+        for(int i=0 ; i<5 ; i++) {
+            pool.returnObject(key, active[i]);
+        }
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
+    }
+
+    public void testMinIdleMaxActive() throws Exception {
+        pool.setMaxIdle(500);
+        pool.setMinIdle(5);
+        pool.setMaxActive(10);
+        pool.setNumTestsPerEvictionRun(0);
+        pool.setMinEvictableIdleTimeMillis(50L);
+        pool.setTimeBetweenEvictionRunsMillis(100L);
+        pool.setTestWhileIdle(true);
+
+        String key = "A";
+
+        pool.preparePool(key, true);
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+
+        Object[] active = new Object[10];
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+
+        for(int i=0 ; i<5 ; i++) {
+            active[i] = pool.borrowObject(key);
+        }
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+
+        for(int i=0 ; i<5 ; i++) {
+            pool.returnObject(key, active[i]);
+        }
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
+
+        for(int i=0 ; i<10 ; i++) {
+            active[i] = pool.borrowObject(key);
+        }
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0);
+
+        for(int i=0 ; i<10 ; i++) {
+            pool.returnObject(key, active[i]);
+        }
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
+    }
+    
+    public void testMinIdleNoPopulateImmediately() throws Exception {
+        pool.setMaxIdle(500);
+        pool.setMinIdle(5);
+        pool.setMaxActive(10);
+        pool.setNumTestsPerEvictionRun(0);
+        pool.setMinEvictableIdleTimeMillis(50L);
+        pool.setTimeBetweenEvictionRunsMillis(1000L);
+        pool.setTestWhileIdle(true);
+
+
+        //Generate a random key
+        String key = "A";
+        
+        pool.preparePool(key, false);
+        
+        assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0);
+        
+        try { Thread.sleep(1500L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+    }
+    
+    public void testMinIdleNoPreparePool() throws Exception {
+        pool.setMaxIdle(500);
+        pool.setMinIdle(5);
+        pool.setMaxActive(10);
+        pool.setNumTestsPerEvictionRun(0);
+        pool.setMinEvictableIdleTimeMillis(50L);
+        pool.setTimeBetweenEvictionRunsMillis(100L);
+        pool.setTestWhileIdle(true);
+
+
+        //Generate a random key
+        String key = "A";
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0);
+
+        Object active = pool.borrowObject(key);
+        assertNotNull(active);
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+    }
+    
+    public void testFIFO() throws Exception {
+        final Object key = "key";
+        pool.addObject(key); // "key0"
+        pool.addObject(key); // "key1"
+        pool.addObject(key); // "key2"
+        assertEquals("Oldest", "key0", pool.borrowObject(key));
+        assertEquals("Middle", "key1", pool.borrowObject(key));
+        assertEquals("Youngest", "key2", pool.borrowObject(key));
+        assertEquals("new-3", "key3", pool.borrowObject(key));
+        pool.returnObject(key, "r");
+        assertEquals("returned", "r", pool.borrowObject(key));
+        assertEquals("new-4", "key4", pool.borrowObject(key));
+    }
+
+    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++) {
+                String key = String.valueOf(_random.nextInt(3));
+                try {
+                    Thread.sleep((long)_random.nextInt(_delay));
+                } catch(Exception e) {
+                    // ignored
+                }
+                Object obj = null;
+                try {
+                    obj = _pool.borrowObject(key);
+                } catch(Exception e) {
+                    _failed = true;
+                    _complete = true;
+                    break;
+                }
+
+                try {
+                    Thread.sleep((long)_random.nextInt(_delay));
+                } catch(Exception e) {
+                    // ignored
+                }
+                try {
+                    _pool.returnObject(key,obj);
+                } catch(Exception e) {
+                    _failed = true;
+                    _complete = true;
+                    break;
+                }
+            }
+            _complete = true;
+        }
+    }
+
+    static class SimpleFactory implements KeyedPoolableObjectFactory {
+        public SimpleFactory() {
+            this(true);
+        }
+        public SimpleFactory(boolean valid) {
+            this.valid = valid;
+        }
+        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 valid; }
+        public void activateObject(Object key, Object obj) { }
+        public void passivateObject(Object key, Object obj) { }
+        int counter = 0;
+        boolean valid;
+    }
+
+    protected boolean isLifo() {
+        return false;
+    }
+
+    protected boolean isFifo() {
+        return true;
+    }
+
+}
+
+

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestGenericObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,1024 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import java.util.NoSuchElementException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.commons.pool.BasePoolableObjectFactory;
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.PoolableObjectFactory;
+import org.apache.commons.pool.TestObjectPool;
+
+/**
+ * @author Rodney Waldhoff
+ * @author Dirk Verbeeck
+ * @version $Revision: 387103 $ $Date: 2006-03-19 20:48:49 -0500 (Sun, 19 Mar 2006) $
+ */
+public class TestGenericObjectPool extends TestObjectPool {
+    public TestGenericObjectPool(String testName) {
+        super(testName);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestGenericObjectPool.class);
+    }
+
+    protected ObjectPool makeEmptyPool(int mincap) {
+       GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
+       pool.setMaxActive(mincap);
+       pool.setMaxIdle(mincap);
+       return pool;
+    }
+    
+    protected Object getNthObject(int n) {
+        return String.valueOf(n);
+    }
+
+    public void setUp() throws Exception {
+        super.setUp();
+        pool = new GenericObjectPool(new SimpleFactory());
+    }
+
+    public void tearDown() throws Exception {
+        super.tearDown();
+        pool.close();
+        pool = null;
+    }
+
+    /**
+     * Activation failure on existing object doesn't fail the borrow 
+     */
+    public void testActivationException() throws Exception {
+        SimpleFactory factory = new SimpleFactory(true, false);
+        factory.setThrowExceptionOnActivate(true);
+        factory.setValidationEnabled(false);
+        GenericObjectPool pool = new GenericObjectPool(factory);
+        
+        Object obj1 = pool.borrowObject();
+        pool.returnObject(obj1);
+
+        // obj1 was returned to the pool but failed to activate the second borrow
+        // a new object obj2 needs te be created
+        Object obj2 = pool.borrowObject();
+        assertTrue(obj1 != obj2);        
+    }
+
+    /**
+     * Activation failure on new object fails the borrow 
+     */
+    public void testActivationExceptionOnNewObject() throws Exception {
+        SimpleFactory factory = new SimpleFactory(true, false);
+        factory.setThrowExceptionOnActivate(true);
+        factory.setValidationEnabled(false);
+        GenericObjectPool pool = new GenericObjectPool(factory);
+        
+        Object obj1 = pool.borrowObject();
+        try {
+            Object obj2 = pool.borrowObject();
+            System.out.println("obj1: " + obj1);
+            System.out.println("obj2: " + obj2);
+            fail("a second object should have been created and failed to activate");
+        }
+        catch (Exception e) {}
+    }
+
+    public void testWhenExhaustedGrow() throws Exception {
+        GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
+        pool.setMaxActive(1);
+        pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);
+        Object obj1 = pool.borrowObject();
+        assertNotNull(obj1);
+        Object obj2 = pool.borrowObject();
+        assertNotNull(obj2);
+        pool.returnObject(obj2);
+        pool.returnObject(obj1);
+        pool.close();
+    }
+
+    public void testWhenExhaustedFail() throws Exception {
+        GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
+        pool.setMaxActive(1);
+        pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
+        Object obj1 = pool.borrowObject();
+        assertNotNull(obj1);
+        try {
+            pool.borrowObject();
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+        pool.returnObject(obj1);
+        pool.close();
+    }
+
+    public void testWhenExhaustedBlock() throws Exception {
+        GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
+        pool.setMaxActive(1);
+        pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK);
+        pool.setMaxWait(10L);
+        Object obj1 = pool.borrowObject();
+        assertNotNull(obj1);
+        try {
+            pool.borrowObject();
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+        pool.returnObject(obj1);
+        pool.close();
+    }
+
+    public void testEvictWhileEmpty() throws Exception {
+        GenericObjectPool pool = new GenericObjectPool(new SimpleFactory(true,false));
+        pool.evict();
+        pool.evict();
+        pool.close();
+    }
+
+    public void testExceptionOnPassivateDuringReturn() throws Exception {
+        SimpleFactory factory = new SimpleFactory();        
+        GenericObjectPool pool = new GenericObjectPool(factory);
+        Object obj = pool.borrowObject();
+        factory.setThrowExceptionOnPassivate(true);
+        pool.returnObject(obj);
+        assertEquals(0,pool.getNumIdle());
+        pool.close();
+    }
+
+    public void testWithInitiallyInvalid() throws Exception {
+        GenericObjectPool pool = new GenericObjectPool(new SimpleFactory(false));
+        pool.setTestOnBorrow(true);
+        try {
+            pool.borrowObject();
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected 
+        }
+    }
+
+    public void testWithSometimesInvalid() throws Exception {
+        GenericObjectPool pool = new GenericObjectPool(new SimpleFactory(true,false));
+        pool.setMaxIdle(10);
+        pool.setTestOnBorrow(true);
+        pool.setTestOnReturn(true);
+        pool.returnObject(pool.borrowObject());  
+        assertEquals(0,pool.getNumIdle());      
+    }
+
+    public void testSetFactoryWithActiveObjects() throws Exception {
+        GenericObjectPool pool = new GenericObjectPool();
+        pool.setMaxIdle(10);
+        pool.setFactory(new SimpleFactory());
+        Object obj = pool.borrowObject();
+        assertNotNull(obj);
+        try {
+            pool.setFactory(null);
+            fail("Expected IllegalStateException");
+        } catch(IllegalStateException e) {
+            // expected
+        }
+        try {
+            pool.setFactory(new SimpleFactory());
+            fail("Expected IllegalStateException");
+        } catch(IllegalStateException e) {
+            // expected
+        }
+    }
+
+    public void testSetFactoryWithNoActiveObjects() throws Exception {
+        GenericObjectPool pool = new GenericObjectPool();
+        pool.setMaxIdle(10);
+        pool.setFactory(new SimpleFactory());
+        Object obj = pool.borrowObject();
+        pool.returnObject(obj);
+        assertEquals(1,pool.getNumIdle());
+        pool.setFactory(new SimpleFactory());
+        assertEquals(0,pool.getNumIdle());
+    }
+    
+    public void testNegativeMaxActive() throws Exception {
+        pool.setMaxActive(-1);
+        pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
+        Object obj = pool.borrowObject();
+        assertEquals(getNthObject(0),obj);
+        pool.returnObject(obj);
+    }
+
+    public void testMaxIdle() throws Exception {
+        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.getNumActive());
+        assertEquals(0,pool.getNumIdle());
+        for(int i=0;i<100;i++) {
+            pool.returnObject(active[i]);
+            assertEquals(99 - i,pool.getNumActive());
+            assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle());
+        }
+    }
+
+    public void testMaxIdleZero() throws Exception {
+        pool.setMaxActive(100);
+        pool.setMaxIdle(0);
+        Object[] active = new Object[100];
+        for(int i=0;i<100;i++) {
+            active[i] = pool.borrowObject();
+        }
+        assertEquals(100,pool.getNumActive());
+        assertEquals(0,pool.getNumIdle());
+        for(int i=0;i<100;i++) {
+            pool.returnObject(active[i]);
+            assertEquals(99 - i,pool.getNumActive());
+            assertEquals(0, pool.getNumIdle());
+        }
+    }
+
+    public void testMaxActive() throws Exception {
+        pool.setMaxActive(3);
+        pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
+
+        pool.borrowObject();
+        pool.borrowObject();
+        pool.borrowObject();
+        try {
+            pool.borrowObject();
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+    }
+
+    public void testMaxActiveZero() throws Exception {
+        pool.setMaxActive(0);
+        pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
+
+        try {
+            pool.borrowObject();
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+    }
+
+    public void testInvalidWhenExhaustedAction() throws Exception {
+        try {
+            pool.setWhenExhaustedAction(Byte.MAX_VALUE);
+            fail("Expected IllegalArgumentException");
+        } catch(IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            ObjectPool pool = new GenericObjectPool(
+                new SimpleFactory(),
+                GenericObjectPool.DEFAULT_MAX_ACTIVE, 
+                Byte.MAX_VALUE,
+                GenericObjectPool.DEFAULT_MAX_WAIT, 
+                GenericObjectPool.DEFAULT_MAX_IDLE,
+                false,
+                false,
+                GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,
+                GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN,
+                GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,
+                false
+            );
+            assertNotNull(pool);
+            fail("Expected IllegalArgumentException");
+        } catch(IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void testSettersAndGetters() throws Exception {
+        GenericObjectPool pool = new GenericObjectPool();
+        {
+            pool.setFactory(new SimpleFactory());
+        }
+        {
+            pool.setMaxActive(123);
+            assertEquals(123,pool.getMaxActive());
+        }
+        {
+            pool.setMaxIdle(12);
+            assertEquals(12,pool.getMaxIdle());
+        }
+        {
+            pool.setMaxWait(1234L);
+            assertEquals(1234L,pool.getMaxWait());
+        }
+        {
+            pool.setMinEvictableIdleTimeMillis(12345L);
+            assertEquals(12345L,pool.getMinEvictableIdleTimeMillis());
+        }
+        {
+            pool.setNumTestsPerEvictionRun(11);
+            assertEquals(11,pool.getNumTestsPerEvictionRun());
+        }
+        {
+            pool.setTestOnBorrow(true);
+            assertTrue(pool.getTestOnBorrow());
+            pool.setTestOnBorrow(false);
+            assertTrue(!pool.getTestOnBorrow());
+        }
+        {
+            pool.setTestOnReturn(true);
+            assertTrue(pool.getTestOnReturn());
+            pool.setTestOnReturn(false);
+            assertTrue(!pool.getTestOnReturn());
+        }
+        {
+            pool.setTestWhileIdle(true);
+            assertTrue(pool.getTestWhileIdle());
+            pool.setTestWhileIdle(false);
+            assertTrue(!pool.getTestWhileIdle());
+        }
+        {
+            pool.setTimeBetweenEvictionRunsMillis(11235L);
+            assertEquals(11235L,pool.getTimeBetweenEvictionRunsMillis());
+        }
+        {
+            pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK);
+            assertEquals(GenericObjectPool.WHEN_EXHAUSTED_BLOCK,pool.getWhenExhaustedAction());
+            pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_FAIL);
+            assertEquals(GenericObjectPool.WHEN_EXHAUSTED_FAIL,pool.getWhenExhaustedAction());
+            pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);
+            assertEquals(GenericObjectPool.WHEN_EXHAUSTED_GROW,pool.getWhenExhaustedAction());
+        }
+    }
+    
+    public void testDefaultConfiguration() throws Exception {
+        GenericObjectPool pool = new GenericObjectPool();
+        assertConfiguration(new GenericObjectPool.Config(),pool);
+    }
+
+    public void testConstructors() throws Exception {
+        {
+            GenericObjectPool pool = new GenericObjectPool();
+            assertConfiguration(new GenericObjectPool.Config(),pool);
+        }
+        {
+            GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
+            assertConfiguration(new GenericObjectPool.Config(),pool);
+        }
+        {
+            GenericObjectPool.Config expected = new GenericObjectPool.Config();
+            expected.maxActive = 2;
+            expected.maxIdle = 3;
+            expected.maxWait = 5L;
+            expected.minEvictableIdleTimeMillis = 7L;
+            expected.numTestsPerEvictionRun = 9;
+            expected.testOnBorrow = true;
+            expected.testOnReturn = true;
+            expected.testWhileIdle = true;
+            expected.timeBetweenEvictionRunsMillis = 11L;
+            expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
+            GenericObjectPool pool = new GenericObjectPool(null,expected);
+            assertConfiguration(expected,pool);
+        }
+        {
+            GenericObjectPool.Config expected = new GenericObjectPool.Config();
+            expected.maxActive = 2;
+            GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive);
+            assertConfiguration(expected,pool);
+        }
+        {
+            GenericObjectPool.Config expected = new GenericObjectPool.Config();
+            expected.maxActive = 2;
+            expected.maxWait = 5L;
+            expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
+            GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait);
+            assertConfiguration(expected,pool);
+        }
+        {
+            GenericObjectPool.Config expected = new GenericObjectPool.Config();
+            expected.maxActive = 2;
+            expected.maxWait = 5L;
+            expected.testOnBorrow = true;
+            expected.testOnReturn = true;
+            expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
+            GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait,expected.testOnBorrow,expected.testOnReturn);
+            assertConfiguration(expected,pool);
+        }
+        {
+            GenericObjectPool.Config expected = new GenericObjectPool.Config();
+            expected.maxActive = 2;
+            expected.maxIdle = 3;
+            expected.maxWait = 5L;
+            expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
+            GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait,expected.maxIdle);
+            assertConfiguration(expected,pool);
+        }
+        {
+            GenericObjectPool.Config expected = new GenericObjectPool.Config();
+            expected.maxActive = 2;
+            expected.maxIdle = 3;
+            expected.maxWait = 5L;
+            expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
+            expected.testOnBorrow = true;
+            expected.testOnReturn = true;
+            GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive,expected.whenExhaustedAction,expected.maxWait,expected.maxIdle,expected.testOnBorrow,expected.testOnReturn);
+            assertConfiguration(expected,pool);
+        }
+        {
+            GenericObjectPool.Config expected = new GenericObjectPool.Config();
+            expected.maxActive = 2;
+            expected.maxIdle = 3;
+            expected.maxWait = 5L;
+            expected.minEvictableIdleTimeMillis = 7L;
+            expected.numTestsPerEvictionRun = 9;
+            expected.testOnBorrow = true;
+            expected.testOnReturn = true;
+            expected.testWhileIdle = true;
+            expected.timeBetweenEvictionRunsMillis = 11L;
+            expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
+            GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive, expected.whenExhaustedAction, expected.maxWait, expected.maxIdle, expected.testOnBorrow, expected.testOnReturn, expected.timeBetweenEvictionRunsMillis, expected.numTestsPerEvictionRun, expected.minEvictableIdleTimeMillis, expected.testWhileIdle);
+            assertConfiguration(expected,pool);
+        }
+        {
+            GenericObjectPool.Config expected = new GenericObjectPool.Config();
+            expected.maxActive = 2;
+            expected.maxIdle = 3;
+            expected.minIdle = 1;
+            expected.maxWait = 5L;
+            expected.minEvictableIdleTimeMillis = 7L;
+            expected.numTestsPerEvictionRun = 9;
+            expected.testOnBorrow = true;
+            expected.testOnReturn = true;
+            expected.testWhileIdle = true;
+            expected.timeBetweenEvictionRunsMillis = 11L;
+            expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
+            GenericObjectPool pool = new GenericObjectPool(null,expected.maxActive, expected.whenExhaustedAction, expected.maxWait, expected.maxIdle, expected.minIdle, expected.testOnBorrow, expected.testOnReturn, expected.timeBetweenEvictionRunsMillis, expected.numTestsPerEvictionRun, expected.minEvictableIdleTimeMillis, expected.testWhileIdle);
+            assertConfiguration(expected,pool);
+        }
+    }
+
+    public void testSetConfig() throws Exception {
+        GenericObjectPool.Config expected = new GenericObjectPool.Config();
+        GenericObjectPool pool = new GenericObjectPool();
+        assertConfiguration(expected,pool);
+        expected.maxActive = 2;
+        expected.maxIdle = 3;
+        expected.maxWait = 5L;
+        expected.minEvictableIdleTimeMillis = 7L;
+        expected.numTestsPerEvictionRun = 9;
+        expected.testOnBorrow = true;
+        expected.testOnReturn = true;
+        expected.testWhileIdle = true;
+        expected.timeBetweenEvictionRunsMillis = 11L;
+        expected.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
+        pool.setConfig(expected);
+        assertConfiguration(expected,pool);
+    }
+
+    public void testDebugInfo() throws Exception {
+        GenericObjectPool pool = new GenericObjectPool(new SimpleFactory());
+        pool.setMaxIdle(3);
+        assertNotNull(pool.debugInfo());
+        Object obj = pool.borrowObject();
+        assertNotNull(pool.debugInfo());
+        pool.returnObject(obj);
+        assertNotNull(pool.debugInfo());
+    }
+
+    public void testStartAndStopEvictor() throws Exception {
+        // set up pool without evictor
+        pool.setMaxIdle(6);
+        pool.setMaxActive(6);
+        pool.setNumTestsPerEvictionRun(6);
+        pool.setMinEvictableIdleTimeMillis(100L);
+
+        for(int j=0;j<2;j++) {
+            // populate the pool
+            {
+                Object[] active = new Object[6];
+                for(int i=0;i<6;i++) {
+                    active[i] = pool.borrowObject();
+                }
+                for(int i=0;i<6;i++) {
+                    pool.returnObject(active[i]);
+                }
+            }
+    
+            // note that it stays populated
+            assertEquals("Should have 6 idle",6,pool.getNumIdle());
+    
+            // start the evictor
+            pool.setTimeBetweenEvictionRunsMillis(50L);
+            
+            // wait a second (well, .2 seconds)
+            try { Thread.sleep(200L); } catch(Exception e) { }
+            
+            // assert that the evictor has cleared out the pool
+            assertEquals("Should have 0 idle",0,pool.getNumIdle());
+    
+            // stop the evictor 
+            pool.startEvictor(0L);
+        }
+    }
+
+    public void testEvictionWithNegativeNumTests() throws Exception {
+        // when numTestsPerEvictionRun is negative, it represents a fraction of the idle objects to test
+        pool.setMaxIdle(6);
+        pool.setMaxActive(6);
+        pool.setNumTestsPerEvictionRun(-2);
+        pool.setMinEvictableIdleTimeMillis(50L);
+        pool.setTimeBetweenEvictionRunsMillis(100L);
+
+        Object[] active = new Object[6];
+        for(int i=0;i<6;i++) {
+            active[i] = pool.borrowObject();
+        }
+        for(int i=0;i<6;i++) {
+            pool.returnObject(active[i]);
+        }
+
+        try { Thread.sleep(100L); } catch(Exception e) { }
+        assertTrue("Should at most 6 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 6);
+        try { Thread.sleep(100L); } catch(Exception e) { }
+        assertTrue("Should at most 3 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 3);
+        try { Thread.sleep(100L); } catch(Exception e) { }
+        assertTrue("Should be at most 2 idle, found " + pool.getNumIdle(),pool.getNumIdle() <= 2);
+        try { Thread.sleep(100L); } catch(Exception e) { }
+        assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
+    }
+
+    public void testEviction() throws Exception {
+        pool.setMaxIdle(500);
+        pool.setMaxActive(500);
+        pool.setNumTestsPerEvictionRun(100);
+        pool.setMinEvictableIdleTimeMillis(250L);
+        pool.setTimeBetweenEvictionRunsMillis(500L);
+        pool.setTestWhileIdle(true);
+
+        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.sleep(1000L); } catch(Exception e) { }
+        assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
+
+        for(int i=0;i<500;i++) {
+            active[i] = pool.borrowObject();
+        }
+        for(int i=0;i<500;i++) {
+            pool.returnObject(active[i]);
+        }
+
+        try { Thread.sleep(1000L); } catch(Exception e) { }
+        assertTrue("Should be less than 500 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 500);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 400 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 400);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 300 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 300);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 200 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 200);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertTrue("Should be less than 100 idle, found " + pool.getNumIdle(),pool.getNumIdle() < 100);
+        try { Thread.sleep(600L); } catch(Exception e) { }
+        assertEquals("Should be zero idle, found " + pool.getNumIdle(),0,pool.getNumIdle());
+    }
+
+    public void testEvictionSoftMinIdle() throws Exception {
+        GenericObjectPool pool = null;
+        
+        class TimeTest extends BasePoolableObjectFactory {
+            private final long createTime;
+            public TimeTest() {
+                createTime = System.currentTimeMillis();
+            }
+            public Object makeObject() throws Exception {
+                return new TimeTest();
+            }
+            public long getCreateTime() {
+                return createTime;
+            }
+        }
+        
+        pool = new GenericObjectPool(new TimeTest());
+        
+        pool.setMaxIdle(5);
+        pool.setMaxActive(5);
+        pool.setNumTestsPerEvictionRun(5);
+        pool.setMinEvictableIdleTimeMillis(3000L);
+        pool.setSoftMinEvictableIdleTimeMillis(1000L);
+        pool.setMinIdle(2);
+
+        Object[] active = new Object[5];
+        Long[] creationTime = new Long[5] ;
+        for(int i=0;i<5;i++) {
+            active[i] = pool.borrowObject();
+            creationTime[i] = new Long(((TimeTest)active[i]).getCreateTime());
+        }
+        
+        for(int i=0;i<5;i++) {
+            pool.returnObject(active[i]);
+        }
+
+        // Soft evict all but minIdle(2)
+        Thread.sleep(1500L);
+        pool.evict();
+        assertEquals("Idle count different than expected.", 2, pool.getNumIdle());
+
+        // Hard evict the rest.
+        Thread.sleep(2000L);
+        pool.evict();
+        assertEquals("Idle count different than expected.", 0, pool.getNumIdle());
+    }
+
+    public void testMinIdle() throws Exception {
+        pool.setMaxIdle(500);
+        pool.setMinIdle(5);
+        pool.setMaxActive(10);
+        pool.setNumTestsPerEvictionRun(0);
+        pool.setMinEvictableIdleTimeMillis(50L);
+        pool.setTimeBetweenEvictionRunsMillis(100L);
+        pool.setTestWhileIdle(true);
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+
+        Object[] active = new Object[5];
+        active[0] = pool.borrowObject();
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+
+        for(int i=1 ; i<5 ; i++) {
+            active[i] = pool.borrowObject();
+        }
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+
+        for(int i=0 ; i<5 ; i++) {
+            pool.returnObject(active[i]);
+        }
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
+    }
+
+    public void testMinIdleMaxActive() throws Exception {
+        pool.setMaxIdle(500);
+        pool.setMinIdle(5);
+        pool.setMaxActive(10);
+        pool.setNumTestsPerEvictionRun(0);
+        pool.setMinEvictableIdleTimeMillis(50L);
+        pool.setTimeBetweenEvictionRunsMillis(100L);
+        pool.setTestWhileIdle(true);
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+
+        Object[] active = new Object[10];
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+
+        for(int i=0 ; i<5 ; i++) {
+            active[i] = pool.borrowObject();
+        }
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 5 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 5);
+
+        for(int i=0 ; i<5 ; i++) {
+            pool.returnObject(active[i]);
+        }
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
+
+        for(int i=0 ; i<10 ; i++) {
+            active[i] = pool.borrowObject();
+        }
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 0 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 0);
+
+        for(int i=0 ; i<10 ; i++) {
+            pool.returnObject(active[i]);
+        }
+
+        try { Thread.sleep(150L); } catch(Exception e) { }
+        assertTrue("Should be 10 idle, found " + pool.getNumIdle(),pool.getNumIdle() == 10);
+    }
+
+    public void testThreaded1() throws Exception {
+        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.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.sleep((long)_random.nextInt(_delay));
+                } catch(Exception e) {
+                    // ignored
+                }
+                Object obj = null;
+                try {
+                    obj = _pool.borrowObject();
+                } catch(Exception e) {
+                    _failed = true;
+                    _complete = true;
+                    break;
+                }
+
+                try {
+                    Thread.sleep((long)_random.nextInt(_delay));
+                } catch(Exception e) {
+                    // ignored
+                }
+                try {
+                    _pool.returnObject(obj);
+                } catch(Exception e) {
+                    _failed = true;
+                    _complete = true;
+                    break;
+                }
+            }
+            _complete = true;
+        }
+    }
+
+    public void testFIFO() throws Exception {
+        pool.addObject(); // "0"
+        pool.addObject(); // "1"
+        pool.addObject(); // "2"
+        assertEquals("Oldest", "0", pool.borrowObject());
+        assertEquals("Middle", "1", pool.borrowObject());
+        assertEquals("Youngest", "2", pool.borrowObject());
+        assertEquals("new-3", "3", pool.borrowObject());
+        pool.returnObject("r");
+        assertEquals("returned", "r", pool.borrowObject());
+        assertEquals("new-4", "4", pool.borrowObject());
+    }
+
+    public void testAddObject() throws Exception {
+        assertEquals("should be zero idle", 0, pool.getNumIdle());
+    	pool.addObject();
+		assertEquals("should be one idle", 1, pool.getNumIdle());
+		assertEquals("should be zero active", 0, pool.getNumActive());
+		Object obj = pool.borrowObject();
+		assertEquals("should be zero idle", 0, pool.getNumIdle());
+		assertEquals("should be one active", 1, pool.getNumActive());
+		pool.returnObject(obj);
+		assertEquals("should be one idle", 1, pool.getNumIdle());
+		assertEquals("should be zero active", 0, pool.getNumActive());
+    }
+    
+    private List testFactorySequenceStates = new ArrayList(5);
+    public void testFactorySequence() throws Exception {
+        // setup
+        // We need a factory that tracks method call sequence.
+        PoolableObjectFactory pof = new PoolableObjectFactory() {
+            public Object makeObject() throws Exception {
+                testFactorySequenceStates.add("makeObject");
+                return new Object();
+            }
+
+            public void activateObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("activateObject");
+            }
+
+            public boolean validateObject(Object obj) {
+                testFactorySequenceStates.add("validateObject");
+                return true;
+            }
+
+            public void passivateObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("passivateObject");
+            }
+
+            public void destroyObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("destroyObject");
+            }
+        };
+
+        GenericObjectPool pool = new GenericObjectPool(pof);
+        pool.setTestOnBorrow(true);
+        pool.setTestOnReturn(true);
+
+        // check the order in which the factory is called during borrow
+        testFactorySequenceStates.clear();
+        Object o = pool.borrowObject();
+        List desiredSequence = Arrays.asList(new String[] {
+                "makeObject",
+                "activateObject",
+                "validateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called when returning an object
+        testFactorySequenceStates.clear();
+        pool.returnObject(o);
+        desiredSequence = Arrays.asList(new String[] {
+                "validateObject",
+                "passivateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called during borrow again
+        testFactorySequenceStates.clear();
+        o = pool.borrowObject();
+        desiredSequence = Arrays.asList(new String[] {
+                "activateObject",
+                "validateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called when invalidating an object
+        testFactorySequenceStates.clear();
+        pool.invalidateObject(o);
+        desiredSequence = Arrays.asList(new String[] {
+                "destroyObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+    }
+
+    private GenericObjectPool pool = null;
+
+    private void assertConfiguration(GenericObjectPool.Config expected, GenericObjectPool actual) throws Exception {
+        assertEquals("testOnBorrow",expected.testOnBorrow,actual.getTestOnBorrow());
+        assertEquals("testOnReturn",expected.testOnReturn,actual.getTestOnReturn());
+        assertEquals("testWhileIdle",expected.testWhileIdle,actual.getTestWhileIdle());
+        assertEquals("whenExhaustedAction",expected.whenExhaustedAction,actual.getWhenExhaustedAction());
+        assertEquals("maxActive",expected.maxActive,actual.getMaxActive());
+        assertEquals("maxIdle",expected.maxIdle,actual.getMaxIdle());
+        assertEquals("maxWait",expected.maxWait,actual.getMaxWait());
+        assertEquals("minEvictableIdleTimeMillis",expected.minEvictableIdleTimeMillis,actual.getMinEvictableIdleTimeMillis());
+        assertEquals("numTestsPerEvictionRun",expected.numTestsPerEvictionRun,actual.getNumTestsPerEvictionRun());
+        assertEquals("timeBetweenEvictionRunsMillis",expected.timeBetweenEvictionRunsMillis,actual.getTimeBetweenEvictionRunsMillis());
+    }
+
+    public class SimpleFactory implements PoolableObjectFactory {
+        public SimpleFactory() {
+            this(true);
+        }
+        public SimpleFactory(boolean valid) {
+            this(valid,valid);
+        }
+        public SimpleFactory(boolean evalid, boolean ovalid) {
+            evenValid = evalid;
+            oddValid = ovalid;
+        }
+        void setValid(boolean valid) {
+            setEvenValid(valid);
+            setOddValid(valid);            
+        }
+        void setEvenValid(boolean valid) {
+            evenValid = valid;
+        }
+        void setOddValid(boolean valid) {
+            oddValid = valid;
+        }
+        public void setThrowExceptionOnPassivate(boolean bool) {
+            exceptionOnPassivate = bool;
+        }
+    
+        public Object makeObject() { return String.valueOf(makeCounter++); }
+        public void destroyObject(Object obj) { }
+        public boolean validateObject(Object obj) {
+            if (enableValidation) { 
+                return validateCounter++%2 == 0 ? evenValid : oddValid; 
+            }
+            else {
+                return true;
+            }
+        }
+        public void activateObject(Object obj) throws Exception {
+            if (exceptionOnActivate) {
+                if (!(validateCounter++%2 == 0 ? evenValid : oddValid)) {
+                    throw new Exception();
+                }
+            }
+        }
+        public void passivateObject(Object obj) throws Exception {
+            if(exceptionOnPassivate) {
+                throw new Exception();
+            }
+        }
+        int makeCounter = 0;
+        int validateCounter = 0;
+        boolean evenValid = true;
+        boolean oddValid = true;
+        boolean exceptionOnPassivate = false;
+        boolean exceptionOnActivate = false;
+        boolean enableValidation = true;
+
+        public boolean isThrowExceptionOnActivate() {
+            return exceptionOnActivate;
+        }
+
+        public void setThrowExceptionOnActivate(boolean b) {
+            exceptionOnActivate = b;
+        }
+
+        public boolean isValidationEnabled() {
+            return enableValidation;
+        }
+
+        public void setValidationEnabled(boolean b) {
+            enableValidation = b;
+        }
+    }
+
+    protected boolean isLifo() {
+ 
+        return false;
+    }
+
+    protected boolean isFifo() {
+        return true;
+    }
+}
+
+

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestSoftRefOutOfMemory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestSoftRefOutOfMemory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestSoftRefOutOfMemory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,198 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.commons.pool.PoolableObjectFactory;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+/**
+ * @author Dirk Verbeeck
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $
+ */
+public class TestSoftRefOutOfMemory extends TestCase {
+    private SoftReferenceObjectPool pool;
+
+    public TestSoftRefOutOfMemory(String testName) {
+        super(testName);
+    }
+
+    public static TestSuite suite() {
+        return new TestSuite(TestSoftRefOutOfMemory.class);
+    }
+
+    public void tearDown() throws Exception {
+        if (pool != null) {
+            pool.close();
+            pool = null;
+        }
+        System.gc();
+    }
+
+    public void testOutOfMemory() throws Exception {
+        pool = new SoftReferenceObjectPool(new SmallPoolableObjectFactory());
+
+        Object obj = pool.borrowObject();
+        assertEquals("1", obj);
+        pool.returnObject(obj);
+        obj = null;
+        
+        assertEquals(1, pool.getNumIdle());
+
+        try {
+            HashMap map = new HashMap();
+
+            for (int i = 0; i < 1000000; i++) {
+                map.put(new Integer(i), new String("Fred Flintstone" + i));
+            }
+        } catch (OutOfMemoryError ex) {
+            
+        }
+        obj = pool.borrowObject();
+        assertEquals("2", obj);
+        pool.returnObject(obj);
+        obj = null;
+            
+        assertEquals(1, pool.getNumIdle());
+    }
+
+    public void testOutOfMemory1000() throws Exception {
+        pool = new SoftReferenceObjectPool(new SmallPoolableObjectFactory());
+
+        for (int i = 0 ; i < 1000 ; i++) {
+            pool.addObject();
+        }
+
+        Object obj = pool.borrowObject();
+        assertEquals("1000", obj);
+        pool.returnObject(obj);
+        obj = null;
+        
+        assertEquals(1000, pool.getNumIdle());
+
+        try {
+            HashMap map = new HashMap();
+
+            for (int i = 0; i < 1000000; i++) {
+                map.put(new Integer(i), new String("Fred Flintstone" + i));
+            }
+        }
+        catch (OutOfMemoryError ex) { }
+        
+        obj = pool.borrowObject();
+        assertEquals("1001", obj);
+        pool.returnObject(obj);
+        obj = null;
+            
+        assertEquals(1, pool.getNumIdle());
+    }
+
+    public void testOutOfMemoryLarge() throws Exception {
+        pool = new SoftReferenceObjectPool(new LargePoolableObjectFactory(1000000));
+
+        Object obj = pool.borrowObject();
+        assertTrue(((String)obj).startsWith("1."));
+        pool.returnObject(obj);
+        obj = null;
+        
+        assertEquals(1, pool.getNumIdle());
+
+        try {
+            HashMap map = new HashMap();
+
+            for (int i = 0; i < 1000000; i++) {
+                map.put(new Integer(i), new String("Fred Flintstone" + i));
+            }
+        }
+        catch (OutOfMemoryError ex) { }
+        
+        obj = pool.borrowObject();
+        assertTrue(((String)obj).startsWith("2."));
+        pool.returnObject(obj);
+        obj = null;
+            
+        assertEquals(1, pool.getNumIdle());
+    }
+
+    public void testOutOfMemoryKeepMap() throws Exception {
+        pool = new SoftReferenceObjectPool(new LargePoolableObjectFactory(1000000));
+
+        Object obj = pool.borrowObject();
+        assertTrue(((String)obj).startsWith("1."));
+        pool.returnObject(obj);
+        obj = null;
+        
+        assertEquals(1, pool.getNumIdle());
+
+        // allocate map outside try/catch block
+        HashMap map = new HashMap();
+        try {
+            for (int i = 0; i < 1000000; i++) {
+                map.put(new Integer(i), new String("Fred Flintstone" + i));
+            }
+        }
+        catch (OutOfMemoryError ex) { }
+
+        try {
+            obj = pool.borrowObject();
+            fail("Expected out of memory");
+        }
+        catch (OutOfMemoryError ex) { }
+    }
+
+
+    public static class SmallPoolableObjectFactory implements PoolableObjectFactory {
+        private int counter = 0;
+        
+        public Object makeObject() {
+            counter++;
+            return String.valueOf(counter);
+        }
+        public boolean validateObject(Object obj) {
+            return true;
+        }
+        public void activateObject(Object obj) { }
+        public void passivateObject(Object obj) { }
+        public void destroyObject(Object obj) { }
+    }
+
+    public static class LargePoolableObjectFactory implements PoolableObjectFactory {
+        private String buffer;
+        private int counter = 0;
+        
+        public LargePoolableObjectFactory(int size) {
+            char[] data = new char[size];
+            Arrays.fill(data, '.');
+            buffer = new String(data);
+        }
+        
+        public Object makeObject() {
+            counter++;
+            return String.valueOf(counter) + buffer;
+        }
+        public boolean validateObject(Object obj) {
+            return true;
+        }
+        public void activateObject(Object obj) { }
+        public void passivateObject(Object obj) { }
+        public void destroyObject(Object obj) { }
+    }
+}
\ No newline at end of file

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestSoftReferenceObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestSoftReferenceObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestSoftReferenceObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,135 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.PoolableObjectFactory;
+import org.apache.commons.pool.TestObjectPool;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Revision: 383290 $ $Date: 2006-03-05 02:00:15 -0500 (Sun, 05 Mar 2006) $
+ */
+public class TestSoftReferenceObjectPool extends TestObjectPool {
+    public TestSoftReferenceObjectPool(String testName) {
+        super(testName);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestSoftReferenceObjectPool.class);
+    }
+
+    protected ObjectPool makeEmptyPool(int cap) {
+        return new SoftReferenceObjectPool(
+            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) { }
+            }
+            );
+    }
+
+    protected Object getNthObject(int n) {
+        return String.valueOf(n);
+    }
+
+    private List testFactorySequenceStates = new ArrayList(5);
+    public void testFactorySequence() throws Exception {
+        // setup
+        // We need a factory that tracks method call sequence.
+        PoolableObjectFactory pof = new PoolableObjectFactory() {
+            public Object makeObject() throws Exception {
+                testFactorySequenceStates.add("makeObject");
+                return new Object();
+            }
+
+            public void activateObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("activateObject");
+            }
+
+            public boolean validateObject(Object obj) {
+                testFactorySequenceStates.add("validateObject");
+                return true;
+            }
+
+            public void passivateObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("passivateObject");
+            }
+
+            public void destroyObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("destroyObject");
+            }
+        };
+
+        ObjectPool pool = new SoftReferenceObjectPool(pof);
+
+        // check the order in which the factory is called during borrow
+        testFactorySequenceStates.clear();
+        Object o = pool.borrowObject();
+        List desiredSequence = Arrays.asList(new String[] {
+                "makeObject",
+                "activateObject",
+                "validateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called when returning an object
+        testFactorySequenceStates.clear();
+        pool.returnObject(o);
+        desiredSequence = Arrays.asList(new String[] {
+                "validateObject",
+                "passivateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called during borrow again
+        testFactorySequenceStates.clear();
+        o = pool.borrowObject();
+        desiredSequence = Arrays.asList(new String[] {
+                "activateObject",
+                "validateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called when invalidating an object
+        testFactorySequenceStates.clear();
+        pool.invalidateObject(o);
+        desiredSequence = Arrays.asList(new String[] {
+                "destroyObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+    }
+
+    protected boolean isLifo() {
+        return false;
+    }
+
+    protected boolean isFifo() {
+        return false;
+    }
+
+}

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestStackKeyedObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,291 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.NoSuchElementException;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.commons.pool.KeyedObjectPool;
+import org.apache.commons.pool.KeyedPoolableObjectFactory;
+import org.apache.commons.pool.TestKeyedObjectPool;
+
+/**
+ * @author Rodney Waldhoff
+ * @version $Revision: 383290 $ $Date: 2006-03-05 02:00:15 -0500 (Sun, 05 Mar 2006) $
+ */
+public class TestStackKeyedObjectPool extends TestKeyedObjectPool {
+    public TestStackKeyedObjectPool(String testName) {
+        super(testName);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestStackKeyedObjectPool.class);
+    }
+
+    protected KeyedObjectPool makeEmptyPool(int mincapacity) {
+        StackKeyedObjectPool pool = new StackKeyedObjectPool(new SimpleFactory(),mincapacity);
+        return pool;
+    }
+    
+    protected Object getNthObject(Object key, int n) {
+        return String.valueOf(key) + String.valueOf(n);
+    }
+    
+    protected Object makeKey(int n) {
+        return String.valueOf(n);
+    }
+
+    private StackKeyedObjectPool pool = null;
+
+    public void setUp() throws Exception {
+        super.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 tearDown() throws Exception {
+        super.tearDown();
+        pool = null;
+    }
+
+    public void testCloseBug() throws Exception {
+        {
+            Object obj0 = pool.borrowObject("");
+            Object obj1 = pool.borrowObject("");
+            assertEquals(2,pool.getNumActive(""));
+            assertEquals(0,pool.getNumIdle(""));
+            pool.returnObject("",obj1);
+            pool.returnObject("",obj0);
+            assertEquals(0,pool.getNumActive(""));
+            assertEquals(2,pool.getNumIdle(""));
+        }
+        {
+            Object obj0 = pool.borrowObject("2");
+            Object obj1 = pool.borrowObject("2");
+            assertEquals(2,pool.getNumActive("2"));
+            assertEquals(0,pool.getNumIdle("2"));
+            pool.returnObject("2",obj1);
+            pool.returnObject("2",obj0);
+            assertEquals(0,pool.getNumActive("2"));
+            assertEquals(2,pool.getNumIdle("2"));
+        }
+        pool.close();
+    }
+
+    public void testIdleCap() throws Exception {
+        Object[] active = new Object[100];
+        for(int i=0;i<100;i++) {
+            active[i] = pool.borrowObject("");
+        }
+        assertEquals(100,pool.getNumActive(""));
+        assertEquals(0,pool.getNumIdle(""));
+        for(int i=0;i<100;i++) {
+            pool.returnObject("",active[i]);
+            assertEquals(99 - i,pool.getNumActive(""));
+            assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle(""));
+        }
+    }
+    
+    public void testPoolWithNullFactory() throws Exception {
+        KeyedObjectPool pool = new StackKeyedObjectPool(10);
+        for(int i=0;i<10;i++) {
+            pool.returnObject("X",new Integer(i));
+        }
+        for(int j=0;j<3;j++) {
+            Integer[] borrowed = new Integer[10];
+            BitSet found = new BitSet();
+            for(int i=0;i<10;i++) {
+                borrowed[i] = (Integer)(pool.borrowObject("X"));
+                assertNotNull(borrowed);
+                assertTrue(!found.get(borrowed[i].intValue()));
+                found.set(borrowed[i].intValue());
+            }
+            for(int i=0;i<10;i++) {
+                pool.returnObject("X",borrowed[i]);
+            }
+        }
+        pool.invalidateObject("X",pool.borrowObject("X"));
+        pool.invalidateObject("X",pool.borrowObject("X"));
+        pool.clear("X");        
+        pool.clear();        
+    }
+    
+    public void testVariousConstructors() throws Exception {
+        {
+            StackKeyedObjectPool pool = new StackKeyedObjectPool();
+            assertNotNull(pool);
+        }
+        {
+            StackKeyedObjectPool pool = new StackKeyedObjectPool(10);
+            assertNotNull(pool);
+        }
+        {
+            StackKeyedObjectPool pool = new StackKeyedObjectPool(10,5);
+            assertNotNull(pool);
+        }
+        {
+            StackKeyedObjectPool pool = new StackKeyedObjectPool(null);
+            assertNotNull(pool);
+        }
+        {
+            StackKeyedObjectPool pool = new StackKeyedObjectPool(null,10);
+            assertNotNull(pool);
+        }
+        {
+            StackKeyedObjectPool pool = new StackKeyedObjectPool(null,10,5);
+            assertNotNull(pool);
+        }
+    }
+    
+    public void testToString() throws Exception {
+        StackKeyedObjectPool pool = new StackKeyedObjectPool(new SimpleFactory());
+        assertNotNull(pool.toString());
+        Object obj = pool.borrowObject("key");
+        assertNotNull(pool.toString());
+        pool.returnObject("key",obj);
+        assertNotNull(pool.toString());
+    }
+        
+    public void testBorrowFromEmptyPoolWithNullFactory() throws Exception {
+        KeyedObjectPool pool = new StackKeyedObjectPool();
+        try {
+            pool.borrowObject("x");
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+    }
+    
+    public void testSetFactory() throws Exception {
+        KeyedObjectPool pool = new StackKeyedObjectPool();
+        try {
+            pool.borrowObject("x");
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+        pool.setFactory(new SimpleFactory());
+        Object obj = pool.borrowObject("x");
+        assertNotNull(obj);
+        pool.returnObject("x",obj);
+    }
+
+    public void testCantResetFactoryWithActiveObjects() throws Exception {
+        KeyedObjectPool pool = new StackKeyedObjectPool();
+        pool.setFactory(new SimpleFactory());
+        Object obj = pool.borrowObject("x");
+        assertNotNull(obj);
+
+        try {
+            pool.setFactory(new SimpleFactory());
+            fail("Expected IllegalStateException");
+        } catch(IllegalStateException e) {
+            // expected
+        }        
+    }
+    
+    public void testCanResetFactoryWithoutActiveObjects() throws Exception {
+        KeyedObjectPool pool = new StackKeyedObjectPool();
+        {
+            pool.setFactory(new SimpleFactory());
+            Object obj = pool.borrowObject("x");        
+            assertNotNull(obj);
+            pool.returnObject("x",obj);
+        }
+        {
+            pool.setFactory(new SimpleFactory());
+            Object obj = pool.borrowObject("x");        
+            assertNotNull(obj);
+            pool.returnObject("x",obj);
+        }
+    }
+
+    public void testBorrowReturnWithSometimesInvalidObjects() throws Exception {
+        KeyedObjectPool pool = new StackKeyedObjectPool();
+        pool.setFactory(
+            new KeyedPoolableObjectFactory() {
+                int counter = 0;
+                public Object makeObject(Object key) { return new Integer(counter++); }
+                public void destroyObject(Object key, Object obj) { }
+                public boolean validateObject(Object key, Object obj) {
+                    if(obj instanceof Integer) {
+                        return ((((Integer)obj).intValue() % 2) == 1);
+                    } else {
+                        return false;
+                    }
+                }
+                public void activateObject(Object key, Object obj) { }
+                public void passivateObject(Object key, Object obj) { 
+                    if(obj instanceof Integer) {
+                        if((((Integer)obj).intValue() % 3) == 0) {
+                            throw new RuntimeException("Couldn't passivate");
+                        }
+                    } else {
+                        throw new RuntimeException("Couldn't passivate");
+                    }
+                }
+            }
+        );
+
+        Object[] obj = new Object[10];
+        for(int i=0;i<10;i++) {
+            obj[i] = pool.borrowObject("key");
+        }
+        for(int i=0;i<10;i++) {
+            pool.returnObject("key",obj[i]);
+        }
+        assertEquals(3,pool.getNumIdle("key"));
+    }
+ 
+    class SimpleFactory implements KeyedPoolableObjectFactory {
+        HashMap map = new HashMap();
+        public Object makeObject(Object key) { 
+            int counter = 0;
+            Integer Counter = (Integer)(map.get(key));
+            if(null != Counter) {
+                counter = Counter.intValue();
+            }
+            map.put(key,new Integer(counter + 1));                       
+            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) { }
+    }
+
+    protected boolean isLifo() {
+        return true;
+    }
+
+    protected boolean isFifo() {
+        return false;
+    }
+}

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/impl/TestStackObjectPool.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,405 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.impl;
+
+import java.util.BitSet;
+import java.util.NoSuchElementException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.PoolableObjectFactory;
+import org.apache.commons.pool.TestObjectPool;
+
+/**
+ * @author Rodney Waldhoff
+ * @author Dirk Verbeeck
+ * @version $Revision: 383290 $ $Date: 2006-03-05 02:00:15 -0500 (Sun, 05 Mar 2006) $
+ */
+public class TestStackObjectPool extends TestObjectPool {
+    public TestStackObjectPool(String testName) {
+        super(testName);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestStackObjectPool.class);
+    }
+
+    protected ObjectPool makeEmptyPool(int mincap) {
+        return new StackObjectPool(new SimpleFactory());
+    }
+    
+    protected Object getNthObject(int n) {
+        return String.valueOf(n);
+    }
+
+    public void testIdleCap() throws Exception {
+        ObjectPool pool = makeEmptyPool(8);
+        Object[] active = new Object[100];
+        for(int i=0;i<100;i++) {
+            active[i] = pool.borrowObject();
+        }
+        assertEquals(100,pool.getNumActive());
+        assertEquals(0,pool.getNumIdle());
+        for(int i=0;i<100;i++) {
+            pool.returnObject(active[i]);
+            assertEquals(99 - i,pool.getNumActive());
+            assertEquals((i < 8 ? i+1 : 8),pool.getNumIdle());
+        }
+    }
+
+    public void testPoolWithNullFactory() throws Exception {
+        ObjectPool pool = new StackObjectPool(10);
+        for(int i=0;i<10;i++) {
+            pool.returnObject(new Integer(i));
+        }
+        for(int j=0;j<3;j++) {
+            Integer[] borrowed = new Integer[10];
+            BitSet found = new BitSet();
+            for(int i=0;i<10;i++) {
+                borrowed[i] = (Integer)(pool.borrowObject());
+                assertNotNull(borrowed);
+                assertTrue(!found.get(borrowed[i].intValue()));
+                found.set(borrowed[i].intValue());
+            }
+            for(int i=0;i<10;i++) {
+                pool.returnObject(borrowed[i]);
+            }
+        }
+        pool.invalidateObject(pool.borrowObject());
+        pool.invalidateObject(pool.borrowObject());
+        pool.clear();        
+    }
+    
+    public void testBorrowFromEmptyPoolWithNullFactory() throws Exception {
+        ObjectPool pool = new StackObjectPool();
+        try {
+            pool.borrowObject();
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+    }
+    
+    public void testSetFactory() throws Exception {
+        ObjectPool pool = new StackObjectPool();
+        try {
+            pool.borrowObject();
+            fail("Expected NoSuchElementException");
+        } catch(NoSuchElementException e) {
+            // expected
+        }
+        pool.setFactory(new SimpleFactory());
+        Object obj = pool.borrowObject();
+        assertNotNull(obj);
+        pool.returnObject(obj);
+    }
+
+    public void testCantResetFactoryWithActiveObjects() throws Exception {
+        ObjectPool pool = new StackObjectPool();
+        pool.setFactory(new SimpleFactory());
+        Object obj = pool.borrowObject();
+        assertNotNull(obj);
+
+        try {
+            pool.setFactory(new SimpleFactory());
+            fail("Expected IllegalStateException");
+        } catch(IllegalStateException e) {
+            // expected
+        }        
+    }
+    
+    public void testCanResetFactoryWithoutActiveObjects() throws Exception {
+        ObjectPool pool = new StackObjectPool();
+        {
+            pool.setFactory(new SimpleFactory());
+            Object obj = pool.borrowObject();        
+            assertNotNull(obj);
+            pool.returnObject(obj);
+        }
+        {
+            pool.setFactory(new SimpleFactory());
+            Object obj = pool.borrowObject();        
+            assertNotNull(obj);
+            pool.returnObject(obj);
+        }
+    }
+
+
+    public void testBorrowWithSometimesInvalidObjects() throws Exception {
+        ObjectPool pool = new StackObjectPool(20);
+        pool.setFactory(
+            new PoolableObjectFactory() {
+                // factory makes Integer objects
+                int counter = 0;
+                public Object makeObject() { return new Integer(counter++); }
+                public void destroyObject(Object obj) { }
+                public boolean validateObject(Object obj) {
+                    // only odd objects are valid
+                    if(obj instanceof Integer) {
+                        return ((((Integer)obj).intValue() % 2) == 1);
+                    } else {
+                        return false;
+                    }
+                }
+                public void activateObject(Object obj) { }
+                public void passivateObject(Object obj) { 
+                    if(obj instanceof Integer) {
+                        if((((Integer)obj).intValue() % 3) == 0) {
+                            throw new RuntimeException("Couldn't passivate");
+                        }
+                    } else {
+                        throw new RuntimeException("Couldn't passivate");
+                    }
+                }
+            }
+        );
+
+        Object[] obj = new Object[10];
+        for(int i=0;i<10;i++) {
+            obj[i] = pool.borrowObject();
+            assertEquals("Each time we borrow, get one more active.", i+1, pool.getNumActive());
+            
+        }
+        for(int i=0;i<10;i++) {
+            pool.returnObject(obj[i]);
+            assertEquals("Each time we borrow, get one less active.", 9-i, pool.getNumActive());
+        }
+        assertEquals(7,pool.getNumIdle());
+    }
+    
+    public void testBorrowReturnWithSometimesInvalidObjects() throws Exception {
+        ObjectPool pool = new StackObjectPool(20);
+
+        class TestingPoolableObjectFactory implements PoolableObjectFactory {
+            // factory makes Integer objects
+            int counter = 0;
+            boolean reject = false;
+            public Object makeObject() { return new Integer(counter++); }
+            public void destroyObject(Object obj) { }
+            public boolean validateObject(Object obj) {
+                if (reject) {
+                    // only odd objects are valid
+                    if(obj instanceof Integer) {
+                        return ((((Integer)obj).intValue() % 2) == 1);
+                    } else {
+                        return false;
+                    }
+                } else {
+                    return true;
+                }
+                    
+            }
+            public void activateObject(Object obj) { }
+            public void passivateObject(Object obj) { 
+                if(obj instanceof Integer) {
+                    if((((Integer)obj).intValue() % 3) == 0) {
+                        throw new RuntimeException("Couldn't passivate");
+                    }
+                } else {
+                    throw new RuntimeException("Couldn't passivate");
+                }
+            }
+        };
+        
+        TestingPoolableObjectFactory factory = new TestingPoolableObjectFactory();
+        
+        pool.setFactory(factory);
+
+        Object[] obj = new Object[10];
+        for(int i=0;i<10;i++) {
+            obj[i] = pool.borrowObject();
+            assertEquals("Each time we borrow, get one more active.", i+1, pool.getNumActive());
+            
+        }
+        
+        // now reject even numbers
+        factory.reject = true;
+        
+        for(int i=0;i<10;i++) {
+            pool.returnObject(obj[i]);
+            assertEquals("Each time we borrow, get one less active.", 9-i, pool.getNumActive());
+        }
+        assertEquals(3,pool.getNumIdle());
+    }
+    
+    public void testVariousConstructors() throws Exception {
+        {
+            StackObjectPool pool = new StackObjectPool();
+            assertNotNull(pool);
+        }
+        {
+            StackObjectPool pool = new StackObjectPool(10);
+            assertNotNull(pool);
+        }
+        {
+            StackObjectPool pool = new StackObjectPool(10,5);
+            assertNotNull(pool);
+        }
+        {
+            StackObjectPool pool = new StackObjectPool(null);
+            assertNotNull(pool);
+        }
+        {
+            StackObjectPool pool = new StackObjectPool(null,10);
+            assertNotNull(pool);
+        }
+        {
+            StackObjectPool pool = new StackObjectPool(null,10,5);
+            assertNotNull(pool);
+        }
+    }
+
+    private final List destroyed = new ArrayList();
+    public void testReturnObjectDiscardOrder() throws Exception {
+        // setup
+        // We need a factory that tracks what was discarded.
+        PoolableObjectFactory pof = new PoolableObjectFactory() {
+            int i = 0;
+            public Object makeObject() throws Exception {
+                return new Integer(i++);
+            }
+
+            public void destroyObject(Object obj) throws Exception {
+                destroyed.add(obj);
+            }
+
+            public boolean validateObject(Object obj) {
+                return obj instanceof Integer;
+            }
+
+            public void activateObject(Object obj) throws Exception {
+            }
+
+            public void passivateObject(Object obj) throws Exception {
+            }
+        };
+        ObjectPool pool = new StackObjectPool(pof, 3);
+
+        // borrow more objects than the pool can hold
+        Integer i0 = (Integer)pool.borrowObject();
+        Integer i1 = (Integer)pool.borrowObject();
+        Integer i2 = (Integer)pool.borrowObject();
+        Integer i3 = (Integer)pool.borrowObject();
+
+        // tests
+        // return as many as the pool will hold.
+        pool.returnObject(i0);
+        pool.returnObject(i1);
+        pool.returnObject(i2);
+
+        // the pool should now be full.
+        assertEquals("No returned objects should have been destroyed yet.",0, destroyed.size());
+
+        // cause the pool to discard a returned object.
+        pool.returnObject(i3);
+        assertEquals("One object should have been destroyed.", 1, destroyed.size());
+
+        // check to see what object was destroyed
+        Integer d = (Integer)destroyed.get(0);
+        assertEquals("Destoryed objects should have the stalest object.", i0, d);
+    }
+
+    private List testFactorySequenceStates = new ArrayList(5);
+    public void testFactorySequence() throws Exception {
+        // setup
+        // We need a factory that tracks method call sequence.
+        PoolableObjectFactory pof = new PoolableObjectFactory() {
+            public Object makeObject() throws Exception {
+                testFactorySequenceStates.add("makeObject");
+                return new Object();
+            }
+
+            public void activateObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("activateObject");
+            }
+
+            public boolean validateObject(Object obj) {
+                testFactorySequenceStates.add("validateObject");
+                return true;
+            }
+
+            public void passivateObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("passivateObject");
+            }
+
+            public void destroyObject(Object obj) throws Exception {
+                testFactorySequenceStates.add("destroyObject");
+            }
+        };
+
+        ObjectPool pool = new StackObjectPool(pof, 1);
+
+        // check the order in which the factory is called during borrow
+        testFactorySequenceStates.clear();
+        Object o = pool.borrowObject();
+        List desiredSequence = Arrays.asList(new String[] {
+                "makeObject",
+                "activateObject",
+                "validateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called when returning an object
+        testFactorySequenceStates.clear();
+        pool.returnObject(o);
+        desiredSequence = Arrays.asList(new String[] {
+                "validateObject",
+                "passivateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called during borrow again
+        testFactorySequenceStates.clear();
+        o = pool.borrowObject();
+        desiredSequence = Arrays.asList(new String[] {
+                "activateObject",
+                "validateObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+
+        // check the order in which the factory is called when invalidating an object
+        testFactorySequenceStates.clear();
+        pool.invalidateObject(o);
+        desiredSequence = Arrays.asList(new String[] {
+                "destroyObject"
+        });
+        assertEquals("Wrong sequence", desiredSequence, testFactorySequenceStates);
+    }
+
+    static class SimpleFactory implements 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) { }
+    }
+
+    protected boolean isLifo() {
+        return true;
+    }
+
+    protected boolean isFifo() {
+        return false;
+    }
+}
+

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/performance/PerformanceTest.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/performance/PerformanceTest.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/performance/PerformanceTest.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,184 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.performance;
+
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+/**
+ * Multi-thread performance test
+ * 
+ * @author Dirk Verbeeck
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ */
+public class PerformanceTest {
+    private int logLevel = 0;
+    private int nrIterations = 5;
+    private int nrThreads = 100;
+
+    private GenericObjectPool pool;
+    private boolean start = false;
+    private volatile int waiting = 0;
+    private volatile int complete = 0;
+    private volatile long totalBorrowTime = 0;
+    private volatile long totalReturnTime = 0;
+    private volatile int nrSamples = 0; 
+
+    public void setLogLevel(int i) {
+        logLevel = i;
+    }
+    
+    private void init() {
+        start = false;
+        waiting = 0;
+        complete = 0;
+        totalBorrowTime = 0;
+        totalReturnTime = 0;
+        nrSamples = 0;     
+    }
+
+    class MyThread implements Runnable {
+        long borrowTime;
+        long returnTime;
+
+        public void runOnce() {
+            try {
+                waiting++;
+                if (logLevel >= 5) {
+                    String name = "thread" + Thread.currentThread().getName();
+                    System.out.println(name + "   waiting: " + waiting + "   complete: " + complete);
+                }
+                long bbegin = System.currentTimeMillis();
+                Object o = pool.borrowObject();
+                long bend = System.currentTimeMillis();
+                waiting--;
+                do {
+                    Thread.yield();
+                }
+                while (!start);
+
+                if (logLevel >= 3) {
+                    String name = "thread" + Thread.currentThread().getName();
+                    System.out.println(name + "    waiting: " + waiting + "   complete: " + complete);
+                }
+                                 
+                long rbegin = System.currentTimeMillis();
+                pool.returnObject(o);
+                long rend = System.currentTimeMillis();
+                Thread.yield();
+                complete++;
+                borrowTime = (bend-bbegin);
+                returnTime = (rend-rbegin);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        public void run() {
+            runOnce(); // warmup
+            for (int i = 0; i<nrIterations; i++) {
+                runOnce();
+                totalBorrowTime += borrowTime;
+                totalReturnTime += returnTime;
+                nrSamples++;
+                if (logLevel >= 2) {
+                    String name = "thread" + Thread.currentThread().getName();
+                    System.out.println(
+                        "result " + nrSamples + "\t" + name 
+                        + "\t" + "borrow time: " + borrowTime + "\t" + "return time: " + returnTime
+                        + "\t" + "waiting: " + waiting + "\t" + "complete: " + complete);
+                }
+            }
+        }
+    }
+
+    private void run(int nrIterations, int nrThreads, int maxActive, int maxIdle) {
+        this.nrIterations = nrIterations;
+        this.nrThreads = nrThreads;
+        init();
+        
+        SleepingObjectFactory factory = new SleepingObjectFactory();
+        if (logLevel >= 4) { factory.setDebug(true); } 
+        pool = new GenericObjectPool(factory);
+        pool.setMaxActive(maxActive);
+        pool.setMaxIdle(maxIdle);
+        pool.setTestOnBorrow(true);
+
+        Thread[] threads = new Thread[nrThreads];
+        for (int i = 0; i < threads.length; i++) {
+            threads[i]= new Thread(new MyThread(), Integer.toString(i));
+            Thread.yield();
+        }
+        if (logLevel >= 1) { System.out.println("created"); } 
+        Thread.yield();
+
+        for (int i = 0; i < threads.length; i++) {
+            threads[i].start();
+            Thread.yield();
+        }
+        if (logLevel >= 1) { System.out.println("started"); }
+        Thread.yield();
+
+        start = true;
+        if (logLevel >= 1) { System.out.println("go"); }
+        Thread.yield();
+
+        for (int i = 0; i < threads.length; i++) {
+            try {
+                threads[i].join();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+        if (logLevel >= 1) { System.out.println("finish"); }
+        System.out.println("-----------------------------------------");
+        System.out.println("nrIterations: " + nrIterations);
+        System.out.println("nrThreads: " + nrThreads);
+        System.out.println("maxActive: " + maxActive);
+        System.out.println("maxIdle: " + maxIdle);
+        System.out.println("nrSamples: " + nrSamples);
+        System.out.println("totalBorrowTime: " + totalBorrowTime);
+        System.out.println("totalReturnTime: " + totalReturnTime);
+        System.out.println("avg BorrowTime: " + totalBorrowTime/nrSamples);
+        System.out.println("avg ReturnTime: " + totalReturnTime/nrSamples);
+    }
+
+    public static void main(String[] args) {
+        PerformanceTest test = new PerformanceTest();
+        test.setLogLevel(0);
+        System.out.println("Increase threads");
+        test.run(1,  50,  5,  5);
+        test.run(1, 100,  5,  5);
+        test.run(1, 200,  5,  5);
+        test.run(1, 400,  5,  5);
+
+        System.out.println("Increase threads & poolsize");
+        test.run(1,  50,  5,  5);
+        test.run(1, 100, 10, 10);
+        test.run(1, 200, 20, 20);
+        test.run(1, 400, 40, 40);
+
+        System.out.println("Increase maxIdle");
+        test.run(1, 400, 40,  5);
+        test.run(1, 400, 40, 40);
+
+
+//      System.out.println("Show creation/destruction of objects");
+//      test.setLogLevel(4);
+//      test.run(1, 400, 40,  5);
+    }
+
+}

Added: branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/performance/SleepingObjectFactory.java
===================================================================
--- branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/performance/SleepingObjectFactory.java	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/src/test/org/apache/commons/pool/performance/SleepingObjectFactory.java	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,82 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.pool.performance;
+
+import org.apache.commons.pool.PoolableObjectFactory;
+
+/**
+ * Sleepy ObjectFactory (everything takes a while longer)
+ * 
+ * @author Dirk Verbeeck
+ * @version $Revision: 155430 $ $Date: 2005-02-26 08:13:28 -0500 (Sat, 26 Feb 2005) $ 
+ */
+public class SleepingObjectFactory implements PoolableObjectFactory {
+
+    private int counter = 0;
+    private boolean debug = false;
+
+	public Object makeObject() throws Exception {
+        Object obj = new Integer(counter++);
+        debug("makeObject", obj);
+        sleep(500);
+		return obj;
+	}
+
+	public void destroyObject(Object obj) throws Exception {
+        debug("destroyObject", obj);
+        sleep(250);
+	}
+
+	public boolean validateObject(Object obj) {
+        debug("validateObject", obj);
+        sleep(30);
+		return true;
+	}
+
+	public void activateObject(Object obj) throws Exception {
+        debug("activateObject", obj);
+        sleep(10);
+	}
+
+	public void passivateObject(Object obj) throws Exception {
+        debug("passivateObject", obj);
+        sleep(10);
+	}
+    
+    private void debug(String method, Object obj) {
+        if (debug) {
+            String thread = "thread" + Thread.currentThread().getName();
+            System.out.println(thread + ": " + method + " " + obj);
+        }
+    }
+    
+    private void sleep(long millis) {
+        try {
+            Thread.sleep(millis);
+        }
+        catch (InterruptedException e) {
+        }
+    }
+
+    public boolean isDebug() {
+        return debug;
+    }
+
+    public void setDebug(boolean b) {
+        debug = b;
+    }
+}

Added: branches/commons-pool/upstream/1.3/xdocs/cvs-usage.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/cvs-usage.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/cvs-usage.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!--
+Copyright 2006 The Apache Software Foundation.
+ 
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<document>
+
+  <properties>
+    <title>Source repository</title>
+    <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+  </properties>
+  
+  <body>
+    <!-- ================================================== -->
+    <section name="Source repository">
+      <p>
+        Jakarta Commons Pool is hosted on the Apache
+        <a href="http://subversion.tigris.org/">subversion</a> repository.
+      </p>
+      <p>
+        The project URL is:<br />
+        <code>http://svn.apache.org/repos/asf/jakarta/commons/proper/pool/trunk</code>
+      </p>
+      <p>
+        The best way to view the repository is via the
+        <a href="http://svn.apache.org/viewcvs.cgi/jakarta/commons/proper/pool/trunk/">subversion viewer</a>.
+      </p>
+      <p>
+        The alternative is to use the
+        <a href="http://svn.apache.org/repos/asf/jakarta/commons/proper/pool/trunk/">native subversion</a> display.
+      </p>
+    </section>
+    <!-- ================================================== -->
+  </body>
+</document>

Added: branches/commons-pool/upstream/1.3/xdocs/downloads.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/downloads.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/downloads.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,65 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2003-2004,2006 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<document>
+   <properties>
+      <title>Downloads</title>
+      <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+      <revision>$Id: downloads.xml 390933 2006-04-03 00:46:35Z sandymac $</revision>
+   </properties>
+
+   <body>
+     <section name="Releases">
+         <p>The following releases are available:</p>
+         <ul>
+           <li>Release 1.3 - 3 April 2006 - <a href="release-notes-1.3.html">(release notes)</a></li>
+           <li>Release 1.2 - 7 June 2004 - <a href="release-notes-1.2.html">(release notes)</a></li>
+           <li>Release 1.1 - 20 October 2003 - <a href="release-notes-1.1.html">(release notes)</a></li>
+           <li>Release 1.0.1 - 12 August 2002</li>
+           <li>Release 1.0 - 4 May 2002</li>
+         </ul>
+         <br/>
+         <p>
+            The latest release binary and source releases are always available on the
+            <a href="http://jakarta.apache.org/site/downloads/downloads_commons-pool.cgi">
+            Jakarta Commons Pool Downloads page</a>.
+         </p>
+         <p>
+            Commons-pool 1.3 only depends at runtime on a Java 1.3 or better JVM.
+         </p>
+         <p>
+            Commons-pool 1.2 depends at runtime on 
+            <a href="http://jakarta.apache.org/commons/collections/">commons-collections</a>.
+         </p>
+         <p>
+            Older releases are retained by the Apache Software Foundation but are 
+            moved into a
+            <a href="http://archive.apache.org/dist/jakarta/commons/pool/">
+            special archive area</a>.
+         </p>
+         <p>
+           <a href="http://cvs.apache.org/builds/jakarta-commons/nightly/commons-pool/">
+           Nightly source and binary drops</a> are also available.
+         </p>
+         <p>
+            Access to the source tree to see the latest and greatest code is possible
+            through <a href="cvs-usage.html">anonymous SVN access</a>.
+         </p>
+      </section>
+
+   </body>
+</document>
+

Added: branches/commons-pool/upstream/1.3/xdocs/examples.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/examples.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/examples.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,175 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2003-2004 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<document>
+   <properties>
+      <title>Examples</title>
+      <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+      <author email="rwaldhoff at apache.org">Rodney Waldhoff</author>
+      <revision>$Id: examples.xml 155430 2005-02-26 13:13:28Z dirkv $</revision>
+   </properties>
+
+   <body>
+      <section name="A Simple Pool Client">
+       <p>
+        Suppose you're writing a set of <code>java.io.Reader</code> utilities, and would like to
+        provide a method for dumping the contents of a <code>Reader</code> to a <code>String</code>.
+        Here's the code for the <code>ReaderUtil</code>, implemented without an <code>ObjectPool</code>:
+       </p>
+<source>
+import java.io.Reader; 
+import java.io.IOException; 
+ 
+public class ReaderUtil { 
+    public ReaderUtil() { 
+    } 
+ 
+    /** 
+     * Dumps the contents of the {@link Reader} to a 
+     * String, closing the {@link Reader} when done. 
+     */ 
+    public String readToString(Reader in) throws IOException { 
+        StringBuffer buf = new StringBuffer(); 
+        try { 
+            for(int c = in.read(); c != -1; c = in.read()) { 
+                buf.append((char)c); 
+            } 
+            return buf.toString(); 
+        } catch(IOException e) { 
+            throw e; 
+        } finally { 
+            try { 
+                in.close(); 
+            } catch(Exception e) { 
+                // ignored 
+            } 
+        } 
+    } 
+}
+</source>
+       <p>
+        For the sake of this example, let's assume we want to to pool the <code>StringBuffer</code>s 
+        used to buffer the <code>Reader</code>'s contents. (A pool of <code>StringBuffer</code>s 
+        may or may not be useful in practice. We're just using it as a simple example here.)
+       </p>
+       <p>
+        Let's further assume that a complete pool implementation will be provided via 
+        a constructor. (We'll show you how to create such an implementation in just a moment.)  
+        Then to use the pool we simply call <code>borrowObject</code> to obtain the buffer, and
+        then call <code>returnObject</code> when we're done with it.
+        Then a <code>ReaderUtil</code> implementation using a pool of <code>StringBuffer</code>s might look 
+        like this:
+       </p>
+<source>
+import org.apache.commons.pool.ObjectPool;
+import java.io.Reader; 
+import java.io.IOException; 
+ 
+public class ReaderUtil { 
+    private ObjectPool pool;
+ 
+    public ReaderUtil(ObjectPool pool) { 
+        this.pool = pool;
+    } 
+ 
+    /** 
+     * Dumps the contents of the {@link Reader} to a 
+     * String, closing the {@link Reader} when done. 
+     */ 
+    public String readToString(Reader in) throws IOException { 
+        StringBuffer buf = null;
+        try { 
+            buf = (StringBuffer)(pool.borrowObject());
+            for(int c = in.read(); c != -1; c = in.read()) { 
+                buf.append((char)c); 
+            } 
+            return buf.toString(); 
+        } catch(IOException e) { 
+            throw e; 
+        } catch(Exception e) {
+            throw new RuntimeException("Unable to borrow buffer from pool" + 
+                    e.toString());
+        } finally { 
+            try { 
+                in.close(); 
+            } catch(Exception e) { 
+                // ignored 
+            } 
+            try {
+                if(null != buf) {
+                    pool.returnObject(buf);
+                }
+            } catch(Exception e) {
+                // ignored
+            }
+        } 
+    } 
+}
+</source>
+      <p>
+       Since we've constrained ourselves to the <code>ObjectPool</code> interface, an arbitrary pool 
+       implementation (returning, in our case, <code>StringBuffer</code>s) can be used.  When a different
+       or "better" pool implemenatation comes along, we can simply drop it into our <code>ReaderUtil</code>
+       without changing a line of code.  
+      </p>
+      </section>
+      <section name="A PoolableObjectFactory">
+       <p>
+        Recall that Pool provides a simple toolkit for creating object pools.  The 
+        <code>PoolableObjectFactory</code> interface is an important part of this toolkit.
+        <code>PoolableObjectFactory</code> defines lifecycle methods for pooled objects. 
+        We can use it to separate the kinds of objects that are pooled and how they are 
+        created, persisted, or destroyed, from the pooling algorithm itself.
+       </p>
+       <p>
+        Suppose we have an <code>ObjectPool</code> implementation that accepts a 
+        <code>PoolableObjectFactory</code> (for example, any of the implementations in the
+        <code>org.apache.commons.pool.impl</code> package).  Then we need only provide 
+        the factory implemenation in order to pool a new kind of object.  
+       </p>
+       <p>
+        Here's a <code>PoolableObjectFactory</code> implementation that creates
+        <code>StringBuffer</code>s as used above.
+       </p>
+<source>
+import org.apache.commons.pool.BasePoolableObjectFactory; 
+ 
+public class StringBufferFactory extends BasePoolableObjectFactory { 
+    // for makeObject we'll simply return a new buffer 
+    public Object makeObject() { 
+        return new StringBuffer(); 
+    } 
+     
+    // when an object is returned to the pool,  
+    // we'll clear it out 
+    public void passivateObject(Object obj) { 
+        StringBuffer buf = (StringBuffer)obj; 
+        buf.setLength(0); 
+    } 
+     
+    // for all other methods, the no-op  
+    // implementation in BasePoolableObjectFactory 
+    // will suffice 
+}
+</source>
+      <p>
+       We can, for example, use this factory with the <code>StackObjectPool</code> to instantiate our
+       <code>ReaderUtil</code> as follows:
+      </p>
+<source>new ReaderUtil(new StackObjectPool(new StringBufferFactory()))</source>
+      </section>
+   </body>
+</document>

Added: branches/commons-pool/upstream/1.3/xdocs/guide/classdiagrams.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/guide/classdiagrams.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/guide/classdiagrams.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2003-2004 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+
+<document>
+
+ <properties>
+  <title>Class Diagrams</title>
+  <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+ </properties>
+
+ <body>
+
+<section name="GenericObjectPool">
+<center><img src="../images/uml/GenericObjectPool.gif"/></center>
+</section>
+
+<section name="GenericKeyedObjectPool">
+<center><img src="../images/uml/GenericKeyedObjectPool.gif"/></center>
+</section>
+
+
+</body>
+</document>

Added: branches/commons-pool/upstream/1.3/xdocs/guide/index.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/guide/index.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/guide/index.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2003-2004 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+
+<document>
+
+ <properties>
+  <title>Developers Guide</title>
+  <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+ </properties>
+
+ <body>
+
+<section name="ObjectPool">
+<center><img src="../images/uml/ObjectPool.gif"/></center>
+<br/>
+<p>
+<a href="../apidocs/org/apache/commons/pool/ObjectPool.html">ObjectPool</a> defines a simple pooling interface.
+<ul>
+   <li>
+       <a href="../apidocs/org/apache/commons/pool/impl/GenericObjectPool.html">GenericObjectPool</a>:
+       ObjectPool implementation with a FIFO (First In First Out) behavior. This queue like behavior 
+       makes sure each object is regularly used. (helps preventing time-outs)
+   </li>
+   <li>
+       <a href="../apidocs/org/apache/commons/pool/impl/StackObjectPool.html">StackObjectPool</a>:
+       ObjectPool implementation with a LIFO (Last In First Out) behavior.
+   </li>
+   <li>
+       <a href="../apidocs/org/apache/commons/pool/impl/SoftReferenceObjectPool.html">SoftReferenceObjectPool</a>: 
+       ObjectPool implementation with a LIFO (Last In First Out) behavior. Additionally this pool wraps 
+       each object in a SoftReference allowing the garbage collector to remove them in response to 
+       memory demand.
+   </li>
+</ul>
+</p>
+</section>
+
+<section name="KeyedObjectPool">
+<center><img src="../images/uml/KeyedObjectPool.gif"/></center>
+<br/>
+<p>
+A <a href="../apidocs/org/apache/commons/pool/KeyedObjectPool.html">KeyedObjectPool</a>
+pools instances of multiple types. Each type may be accessed using an arbitrary key.
+<ul>
+   <li>
+       <a href="../apidocs/org/apache/commons/pool/impl/GenericKeyedObjectPool.html">GenericKeyedObjectPool</a>:
+       ObjectPool implementation with a FIFO (First In First Out) behavior.
+   </li>
+   <li>
+       <a href="../apidocs/org/apache/commons/pool/impl/StackKeyedObjectPool.html">StackKeyedObjectPool</a>:
+       ObjectPool implementation with a LIFO (Last In First Out) behavior.
+   </li>
+</ul>
+</p>
+</section>
+
+</body>
+</document>

Added: branches/commons-pool/upstream/1.3/xdocs/guide/sequencediagrams.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/guide/sequencediagrams.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/guide/sequencediagrams.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2003-2004 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+
+<document>
+
+ <properties>
+  <title>Sequence Diagrams</title>
+  <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+ </properties>
+
+ <body>
+
+<section name="borrowObject">
+<center><img src="../images/uml/borrowObject.gif"/></center>
+</section>
+
+<section name="returnObject">
+<center><img src="../images/uml/returnObject.gif"/></center>
+</section>
+
+<section name="invalidateObject">
+<center><img src="../images/uml/invalidateObject.gif"/></center>
+</section>
+
+</body>
+</document>

Added: branches/commons-pool/upstream/1.3/xdocs/images/pool-logo-blue.jpg
===================================================================
(Binary files differ)


Property changes on: branches/commons-pool/upstream/1.3/xdocs/images/pool-logo-blue.jpg
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/commons-pool/upstream/1.3/xdocs/images/pool-logo-white.png
===================================================================
(Binary files differ)


Property changes on: branches/commons-pool/upstream/1.3/xdocs/images/pool-logo-white.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/commons-pool/upstream/1.3/xdocs/images/pool-logo-white.xcf
===================================================================
(Binary files differ)


Property changes on: branches/commons-pool/upstream/1.3/xdocs/images/pool-logo-white.xcf
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/commons-pool/upstream/1.3/xdocs/images/uml/GenericKeyedObjectPool.gif
===================================================================
(Binary files differ)


Property changes on: branches/commons-pool/upstream/1.3/xdocs/images/uml/GenericKeyedObjectPool.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/commons-pool/upstream/1.3/xdocs/images/uml/GenericObjectPool.gif
===================================================================
(Binary files differ)


Property changes on: branches/commons-pool/upstream/1.3/xdocs/images/uml/GenericObjectPool.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/commons-pool/upstream/1.3/xdocs/images/uml/KeyedObjectPool.gif
===================================================================
(Binary files differ)


Property changes on: branches/commons-pool/upstream/1.3/xdocs/images/uml/KeyedObjectPool.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/commons-pool/upstream/1.3/xdocs/images/uml/ObjectPool.gif
===================================================================
(Binary files differ)


Property changes on: branches/commons-pool/upstream/1.3/xdocs/images/uml/ObjectPool.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/commons-pool/upstream/1.3/xdocs/images/uml/borrowObject.gif
===================================================================
(Binary files differ)


Property changes on: branches/commons-pool/upstream/1.3/xdocs/images/uml/borrowObject.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/commons-pool/upstream/1.3/xdocs/images/uml/invalidateObject.gif
===================================================================
(Binary files differ)


Property changes on: branches/commons-pool/upstream/1.3/xdocs/images/uml/invalidateObject.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/commons-pool/upstream/1.3/xdocs/images/uml/returnObject.gif
===================================================================
(Binary files differ)


Property changes on: branches/commons-pool/upstream/1.3/xdocs/images/uml/returnObject.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/commons-pool/upstream/1.3/xdocs/index.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/index.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/index.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,173 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2003-2004,2006 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<document>
+   <properties>
+      <title>Overview</title>
+      <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+      <author email="rwaldhoff at apache.org">Rodney Waldhoff</author>
+      <author email="sandymac at apache.org">Sandy McArthur</author>
+      <revision>$Id: index.xml 387718 2006-03-22 04:54:59Z sandymac $</revision>
+   </properties>
+
+   <body>
+      <section name="The Pool Component">
+         <p>
+          Pool provides an Object-pooling API, with three major aspects:
+          <ol>
+           <li>
+            A generic object pool interface that clients and implementors can use to provide easily 
+            interchangable pooling implementations.
+           </li>
+           <li>
+            A toolkit for creating modular object pools.
+           </li>
+           <li>
+            Several general purpose pool implementations.
+           </li>
+          </ol>
+         </p>
+      </section>
+
+      <section name="Releases">
+         <p>
+            See the <a href="downloads.html">downloads</a> page for information on obtaining releases.
+            The <a href="release-notes-1.3.html">commons pool 1.3 release</a> is the most recent stable release. 
+         </p>
+      </section>
+
+      <section name="Features">
+        <p>
+            The 
+            <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/package-summary.html">org.apache.commons.pool</a> 
+            package defines a handful of pooling interfaces and some base classes 
+            that may be useful when creating new pool implementations.
+        </p>
+        <subsection name="ObjectPool">
+          <p>
+             <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/ObjectPool.html"><code>ObjectPool</code></a>
+             defines a trivially simple pooling interface:
+          </p>
+<source>
+public interface ObjectPool {
+    Object borrowObject();
+    void returnObject(Object borrowed);
+}
+</source>           
+          <p>
+            Some client classes won't integrate with <i>Pool</i> any more than this.
+            Clients written to this interface can use arbitrary <code>ObjectPool</code> 
+            implementations interchangeably. 
+          </p>           
+          <p>
+             <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/BaseObjectPool.html"><code>BaseObjectPool</code></a>
+             provides an abstract base implementation of <code>ObjectPool</code>. Clients are
+             encouraged but not required to extend <code>BaseObjectPool</code> for new 
+             <code>ObjectPool</code> implementations.
+          </p>
+          <p>
+             <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/KeyedObjectPool.html"><code>KeyedObjectPool</code></a>
+             defines a similiar interface for pools composed of heterogenous objects:
+          </p>
+<source>
+public interface KeyedObjectPool {
+    Object borrowObject(Object key);
+    void returnObject(Object key, Object borrowed);
+}
+</source>           
+        </subsection>
+        <subsection name="PoolableObjectFactory">
+          <p>
+             The <i>Pool</i> package makes it possible separate the way in which instances
+             are pooled from the way in which instances are created and destroyed. 
+             <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/PoolableObjectFactory.html"><code>PoolableObjectFactory</code></a>
+             supports this by providing a generic inteface for the lifecycle of a pooled object:
+          </p>
+<source>
+public interface PoolableObjectFactory {
+    Object makeObject();
+    void activateObject(Object obj);
+    void passivateObject(Object obj);
+    boolean validateObject(Object obj);
+    void destroyObject(Object obj);
+}
+</source>           
+          <p>
+             <code>ObjectPool</code> implementations may be written to accept arbitrary
+             <code>PoolableObjectFactory</code>s.
+             This makes is possible for clients to select pooling-behavior distinct 
+             from the kinds of objects that are pooled.  
+          </p>           
+          <p>
+             <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/BasePoolableObjectFactory.html"><code>BasePoolableObjectFactory</code></a>
+             provides an abstract base implementation of <code>PoolableObjectFactory</code> that
+             makes implementations a snap.
+          </p>
+          <p>
+             <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/KeyedPoolableObjectFactory.html"><code>KeyedPoolableObjectFactory</code></a>
+             defines a similiar interface for <code>KeyedObjectPool</code>s:
+          </p>
+<source>
+public interface KeyedPoolableObjectFactory {
+    Object makeObject(Object key);
+    void activateObject(Object key, Object obj);
+    void passivateObject(Object key, Object obj);
+    boolean validateObject(Object key, Object obj);
+    void destroyObject(Object key, Object obj);
+}
+</source>           
+          <p>
+             <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/BaseKeyedPoolableObjectFactory.html"><code>BaseKeyedPoolableObjectFactory</code></a>
+             provides an abstract base implementation of <code>KeyedPoolableObjectFactory</code> that
+             makes implementations a snap.
+          </p>
+        </subsection>
+        <p>
+            The 
+            <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/impl/package-summary.html">org.apache.commons.pool.impl</a> 
+            package provides some <i>Pool</i> implementations.
+        </p>
+        <subsection name="StackObjectPool">
+          <p>
+             <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/impl/StackObjectPool.html"><code>StackObjectPool</code></a>
+             will pool a finite number of "idle" instances, but will create new instances a needed in 
+             order to support high demand.
+          </p>
+          <p>
+             <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/impl/StackKeyedObjectPool.html"><code>StackKeyedObjectPool</code></a>
+             offers the same behavior for keyed pools.
+          </p>
+        </subsection>
+        <subsection name="GenericObjectPool">
+          <p>
+             <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/impl/GenericObjectPool.html"><code>GenericObjectPool</code></a>
+             provides a wide variety of configuration options, including the ablity to cap the number of idle or
+             active instances, to evict instances as they sit idle in the pool, etc.
+          </p>
+          <p>
+             <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/impl/GenericKeyedObjectPool.html"><code>GenericKeyedObjectPool</code></a>
+             offers the same behavior for keyed pools.
+          </p>
+        </subsection>
+        <subsection name="SoftReferenceObjectPool">
+          <p>
+             <a href="http://jakarta.apache.org/commons/pool/apidocs/org/apache/commons/pool/impl/SoftReferenceObjectPool.html"><code>SoftReferenceObjectPool</code></a>
+             can grow as needed, but allows the garbage collector to evict idle instances from the pool as needed. 
+          </p>
+        </subsection>
+      </section>
+   </body>
+</document>

Added: branches/commons-pool/upstream/1.3/xdocs/issue-tracking.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/issue-tracking.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/issue-tracking.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<!--
+Copyright 2006 The Apache Software Foundation.
+ 
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<document>
+
+  <properties>
+    <title>Issue tracking</title>
+    <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+  </properties>
+
+  <body>
+    <!-- ================================================== -->
+    <section name="Issue tracking">
+      <p>
+        Commons Pool uses <a href="http://issues.apache.org/bugzilla/">ASF Bugzilla</a> for tracking issues.
+        To use Bugzilla you may need to <a href="http://issues.apache.org/bugzilla/createaccount.cgi">create an account</a>.
+      </p>
+      <p>
+        If you would like to report a bug, or raise an enhancement request with
+        Commons Pool please do the following:
+        <ol>
+        <li><a href="http://issues.apache.org/bugzilla/buglist.cgi?bug_status=UNCONFIRMED&amp;bug_status=NEW&amp;bug_status=ASSIGNED&amp;bug_status=REOPENED&amp;bug_status=NEEDINFO&amp;product=Commons&amp;component=Pool">Search existing open bugs</a>.
+        If you find your issue listed then please add a comment with your details.</li>
+        <li><a href="http://mail-archives.apache.org/mod_mbox/jakarta-commons-dev/">Search the mailing list archive</a>.
+        You may find your issue or idea has already been discussed.</li>
+        <li><a href="http://issues.apache.org/bugzilla/enter_bug.cgi?product=Commons&amp;component=Pool&amp;version=1.1%20Final&amp;short_desc=%5Bpool%5D%20%22Your%20subject%20heading%20here%22&amp;comment=Please%20provide%20details%20here.%20Its%20best%20to%20submit%20patches%20that%20alter%0D%0Aexisting%20file%20content%20in%20%22unified%20diff%22%20format.%20%0D%0A%0D%0ASubmissions%20that%20provide%20new%20files%20can%20be%20supplied%20as%20direct%20file%0D%0Aattachments%20or%20archives%20in%20zip%20or%20tar.gz%20format.%20Please%20be%20kind%20%0D%0Aenough%20to%20identify%20the%20format%20of%20the%20attached%20archive%20as%20Bugzilla%0D%0Atends%20to%20strip%20these%20characterstics%20by%20removing%20the%20files%20extension.">Submit a bug report or enhancement request</a>.
+        Please prefix all new issues with [pool] in the summary line.
+        </li>
+        </ol>
+      </p>
+      <p>
+        Please also remember these points:
+        <ul>
+          <li>the more information you provide, the better we can help you</li>
+          <li>test cases are vital, particularly for any proposed enhancements</li>
+          <li>the developers of Commons Pool are all unpaid volunteers</li>
+        </ul>
+      </p>
+      <p>
+        You may also find these links useful:
+        <ul>
+          <li><a href="http://issues.apache.org/bugzilla/buglist.cgi?bug_status=UNCONFIRMED&amp;bug_status=NEW&amp;bug_status=ASSIGNED&amp;bug_status=REOPENED&amp;bug_status=NEEDINFO&amp;product=Commons&amp;component=Pool">All Open Pool bugs</a></li>
+          <li><a href="http://issues.apache.org/bugzilla/buglist.cgi?bug_status=RESOLVED&amp;bug_status=VERIFIED&amp;bug_status=CLOSED&amp;product=Commons&amp;component=Pool">All Closed Pool bugs</a></li>
+          <li><a href="http://issues.apache.org/bugzilla/buglist.cgi?bug_status=UNCONFIRMED&amp;bug_status=NEW&amp;bug_status=ASSIGNED&amp;bug_status=REOPENED&amp;bug_status=NEEDINFO&amp;bug_status=RESOLVED&amp;bug_status=VERIFIED&amp;bug_status=CLOSED&amp;product=Commons&amp;component=Pool">All Pool bugs</a></li>
+        </ul>
+      </p>
+    </section>
+    <!-- ================================================== -->
+  </body>
+</document>

Added: branches/commons-pool/upstream/1.3/xdocs/navigation.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/navigation.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/navigation.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+   Copyright 2003-2004 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<!DOCTYPE org.apache.commons.menus SYSTEM 'http://jakarta.apache.org/commons/build/maven-build.dtd'>
+<project name="Commons Pool">
+    <title>Commons Pool</title>
+    <organizationLogo href="/images/jakarta-logo-blue.gif">
+   		Jakarta
+  	</organizationLogo>
+    <body>
+	    <links>
+	      <item name="Jakarta Commons"                   
+	            href="http://jakarta.apache.org/commons/"/>
+	    </links>
+    
+        <menu name="Commons&#xA0;Pool">
+            <item name="Overview"                      href="/index.html" />
+            <item name="Javadoc"                       href="/apidocs/index.html"/>
+            <item name="Developers&#xA0;Guide"         href="/guide/index.html" collapse="true">
+                <item name="Class&#xA0;Diagrams"       href="/guide/classdiagrams.html"/>
+                <item name="Sequence&#xA0;Diagrams"    href="/guide/sequencediagrams.html"/>
+            </item>
+            <item name="Examples"                      href="/examples.html"/>
+            <item name="Downloads"                     href="/downloads.html"/>
+            <item name="Wiki"                          href="http://wiki.apache.org/jakarta-commons/Pool"/>
+        </menu>
+        
+        &commons;
+    </body>
+</project>

Added: branches/commons-pool/upstream/1.3/xdocs/release-notes-1.1.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/release-notes-1.1.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/release-notes-1.1.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,76 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2003-2004 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<document>
+   <properties>
+      <title>Release notes for Commons-Pool 1.1</title>
+      <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+      <revision>$Id: release-notes-1.1.xml 155430 2005-02-26 13:13:28Z dirkv $</revision>
+   </properties>
+
+   <body>
+     <section name="Release notes for Commons-Pool 1.1">
+<p>
+There were a lot changes since the 1.0.1 release on 12 Aug 2002.
+<ul>
+<li>A lot of corner cases were fixed</li>
+<br/>
+<li>Performance improvement by optimizing pool synchronization,
+  the critical code paths were optimized by reducing pool synchronization
+  but we also added more synchronization where needed</li>
+<br/>
+<li>New minIdle feature: the minimum number of objects allowed in the pool
+  before the evictor thread (if active) spawns new objects.
+  (Note no objects are created when: numActive + numIdle >= maxActive)</li>
+<br/>
+<li>New maxTotal feature: a cap on the total number of instances controlled by a pool.
+  Only for GenericKeyedObjectPool where maxActive is a cap on the number of active 
+  instances from the pool (per key).</li>
+<br/>
+<li>UML Class and sequence diagrams</li>
+<br/>
+<li>The following issues were resolved since v1.0.1: (see Bugzilla for complete description)
+<table>
+<tr><th>ID</th><th>Date</th><th>Sev</th><th>State</th><th>Summary</th></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=12840">12840</a></td><td>2002-10-31</td><td>Enh</td><td>FIXE</td><td>Factor out syncronized block Evictor code to method</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=12841">12841</a></td><td>2002-10-30</td><td>Nor</td><td>FIXE</td><td>GenericObjectPool unused variable and unused synchronized block</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=13128">13128</a></td><td>2002-10-30</td><td>Maj</td><td>DUPL</td><td>GenericKeyedObjectPool: _activeMap.get(key) increment is not balanced with decrements</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=13649">13649</a></td><td>2002-10-29</td><td>Nor</td><td>FIXE</td><td>GenericObjectPool: Negative _maxActive doesn't allow growth</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=13705">13705</a></td><td>2002-10-30</td><td>Nor</td><td>FIXE</td><td>Add invalidateObject() method to ObjectPool</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=14970">14970</a></td><td>2002-11-30</td><td>Nor</td><td>FIXE</td><td>Passing null for Stack[Keyed]ObjectPool factory causes NullPointerException</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=14981">14981</a></td><td>2003-04-24</td><td>Nor</td><td>FIXE</td><td>getNumActive() count is wrong when returnObject()  is used to pre-populate StackObjectPool</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=14982">14982</a></td><td>2003-03-05</td><td>Enh</td><td>FIXE</td><td>GenericObjectPool does not work with null factory.</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=14983">14983</a></td><td>2003-03-14</td><td>Enh</td><td>FIXE</td><td>GenericObjectPool should allow for manual population of the pool</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=17931">17931</a></td><td>2003-03-13</td><td>Min</td><td>FIXE</td><td>Patch to update the javadocs for StackObjectPool</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=17962">17962</a></td><td>2003-03-13</td><td>Nor</td><td>FIXE</td><td>Misc javadoc updates and clean up for GenericKeyedObjectPool</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=17963">17963</a></td><td>2003-03-13</td><td>Enh</td><td>FIXE</td><td>General cleanup in GenericObjectPool</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=17968">17968</a></td><td>2003-03-13</td><td>Enh</td><td>FIXE</td><td>Allow zero idle objects in GenericObjectPool</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=17969">17969</a></td><td>2003-03-13</td><td>Nor</td><td>FIXE</td><td>Additional javadocs for StackKeyedObjectPool</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=17990">17990</a></td><td>2003-04-18</td><td>Maj</td><td>FIXE</td><td>Leaking DB connections - synch problem in GenericKeyedObject</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=18062">18062</a></td><td>2003-04-18</td><td>Cri</td><td>FIXE</td><td>borrowObject/validation infinite loop and deadlock issue in</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=18617">18617</a></td><td>2003-04-07</td><td>Min</td><td>FIXE</td><td>DelegatingPreparedStatement throws misleading exception</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=19192">19192</a></td><td>2003-04-22</td><td>Enh</td><td>FIXE</td><td>over agressive synchronize causing performance problem</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=21838">21838</a></td><td>2003-08-11</td><td>Enh</td><td>FIXE</td><td>Weird HTML makes the pool example doc hard to read</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=22597">22597</a></td><td>2003-08-21</td><td>Enh</td><td>FIXE</td><td>minIdle Functionality</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=23060">23060</a></td><td>2003-09-20</td><td>Cri</td><td>FIXE</td><td>Pool not available for download</td></tr>
+</table>
+</li>
+</ul>
+</p>
+</section>
+</body>
+</document>
+

Added: branches/commons-pool/upstream/1.3/xdocs/release-notes-1.2.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/release-notes-1.2.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/release-notes-1.2.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2003-2004 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<document>
+   <properties>
+      <title>Release notes for Commons-Pool 1.2</title>
+      <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+      <revision>$Id: release-notes-1.2.xml 155430 2005-02-26 13:13:28Z dirkv $</revision>
+   </properties>
+
+   <body>
+     <section name="Release notes for Commons-Pool 1.2">
+<p>
+There were no mayor changes since the 1.1 release on 20 October 2003.
+<ul>
+<li>The following issues were resolved since v1.1: (see Bugzilla for complete description)
+<table>
+<tr><th>ID</th><th>Date</th><th>Sev</th><th>State</th><th>Summary</th></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=24864">24864</a></td><td>2004-01-19</td><td>Nor</td><td>FIXE</td><td>GenericKeyedObjectPoolFactory Config Constructor is incorrect</td></tr>
+<tr><td><a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=28638">28638</a></td><td>2004-04-27</td><td>Min</td><td>FIXE</td><td>Not possible to extend GenericObjectPool.returnObject() without affecting addObject()</td></tr>
+</table>
+</li>
+</ul>
+</p>
+</section>
+</body>
+</document>
+

Added: branches/commons-pool/upstream/1.3/xdocs/release-notes-1.3.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/release-notes-1.3.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/release-notes-1.3.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,639 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2003-2006 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<document>
+   <properties>
+      <title>Release notes for Commons-Pool 1.3</title>
+      <author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+      <revision>$Id: release-notes-1.3.xml 387892 2006-03-22 17:13:02Z sandymac $</revision>
+   </properties>
+
+   <body>
+     <section name="Release notes for Commons-Pool 1.3">
+         <p>
+             This is a long overdue maintence release of the Pool 1.x branch.
+             This should be a drop in upgrade for anyone using Pool 1.2.
+         </p>
+<ul>
+    <li>
+        <p>
+            Dependency on Commons Collections has been removed. Pool 1.3 has no requirements other than
+            a 1.3 JVM.
+        </p>
+    </li>
+    <li>
+        <p>
+            Thanks to an audit by Mayur Naik many potential synchronizations issues have been fixed.
+        </p>
+    </li>
+    <li>
+        <p>
+            GenericObjectPool and GenericKeyedObjectPool were incorrectly implemented as a LIFO (stack)
+            as opposed to a FIFO as documented. This has been fixed.
+        </p>
+    </li>
+    <li>
+        <p>
+            The PoolUtils class with a number static decorator methods has been added. 
+        </p>
+    </li>
+    <li>
+        <p>
+            The following issues were resolved since v1.2: (see Bugzilla for complete description)
+        </p>
+<table>
+        <tr>
+            <th>ID</th>
+            <th>Date</th>
+            <th>Sev</th>
+            <th>State</th>
+            <th>Summary</th>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=27493">27493</a>
+            </td>
+
+            <td>2004-11-17</td>
+            <td>enh</td>
+            <td>FIXE</td>
+            <td>GenericKeyedObjectPool: maxTotal limit enhancement</td>
+
+        </tr>
+
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=28619">28619</a>
+            </td>
+
+            <td>2004-11-17
+            </td>
+            <td>enh
+            </td>
+            <td>FIXE
+            </td>
+            <td>GenericObjectPool: Swallowed Exception
+            </td>
+
+        </tr>
+
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=29863">29863</a>
+            </td>
+
+            <td>2004-11-17
+            </td>
+            <td>nor
+            </td>
+            <td>FIXE
+            </td>
+            <td>GenericObjectPool.setMaxActive(0) allows an infinite numb...
+            </td>
+
+        </tr>
+
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=29912">29912</a>
+            </td>
+
+            <td>2004-11-17
+            </td>
+            <td>nor
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] Compilation under 1.5: enum keyword
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=30426">30426</a>
+            </td>
+
+            <td>2004-11-17
+            </td>
+            <td>enh
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] need property for removing objects above min
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=31298">31298</a>
+            </td>
+
+            <td>2004-11-17
+            </td>
+            <td>nor
+            </td>
+            <td>FIXE
+            </td>
+            <td>setMinIdle feature implemented for GenericKeyedObjectPool
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=34902">34902</a>
+            </td>
+
+            <td>2005-05-16
+            </td>
+            <td>nor
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] StackObjectPool.releaseObject(...) has silly behav...
+            </td>
+        </tr>
+
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=34934">34934</a>
+            </td>
+
+            <td>2005-05-16
+            </td>
+            <td>tri
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] clean up some JavaDoc warnings
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=34935">34935</a>
+            </td>
+
+            <td>2005-05-16
+            </td>
+            <td>enh
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] changes the borrowObject method so it advoids catc...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=34296">34296</a>
+            </td>
+
+            <td>2005-05-16
+            </td>
+            <td>maj
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] Potential pool leak if _factory.makeObject() throw...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=37226">37226</a>
+            </td>
+
+            <td>2005-10-26
+            </td>
+            <td>maj
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] synchronization issues in StackObjectPool
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=37227">37227</a>
+            </td>
+
+            <td>2005-10-26
+            </td>
+            <td>maj
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] synchronization issues in GenericObjectPool
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=37228">37228</a>
+            </td>
+
+            <td>2005-10-27
+            </td>
+            <td>maj
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] synchronization issues in SoftReferenceObjectPool
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=37234">37234</a>
+            </td>
+
+            <td>2005-10-27
+            </td>
+            <td>maj
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] synchronization issues in GenericKeyedObjectPool
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=37235">37235</a>
+            </td>
+
+            <td>2005-10-27
+            </td>
+            <td>maj
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] synchronization issues in StackKeyedObjectPool
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=36719">36719</a>
+            </td>
+
+            <td>2005-10-29
+            </td>
+            <td>maj
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] Some ObjectPool.borrowObject() implementations do ...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=33264">33264</a>
+            </td>
+
+            <td>2005-10-29
+            </td>
+            <td>nor
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] GenericObjectPool is a LIFO, not a FIFO implementa...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=36904">36904</a>
+            </td>
+
+            <td>2005-10-29
+            </td>
+            <td>nor
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] GenericKeyedObjectPool is a LIFO, not a FIFO imple...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=37428">37428</a>
+            </td>
+
+            <td>2005-11-10
+            </td>
+            <td>enh
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] patch to remove GenericObjectPool's dep on Cursora...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=37431">37431</a>
+            </td>
+
+            <td>2005-11-10
+            </td>
+            <td>enh
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] patch to remove GenericKeyedObjectPool's dep on Cu...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=37321">37321</a>
+            </td>
+
+            <td>2005-11-16
+            </td>
+            <td>min
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] GenericObjectPool.Evictor._cancelled should to be ...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=37153">37153</a>
+            </td>
+
+            <td>2006-02-06
+            </td>
+            <td>enh
+            </td>
+            <td>WORK
+            </td>
+            <td>[pool] patch to use non-deprecated CursorableLinkedList f...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=38540">38540</a>
+            </td>
+
+            <td>2006-02-06
+            </td>
+            <td>nor
+            </td>
+            <td>DUPL
+            </td>
+            <td>[pool] Remove the use of the deprecated collections class...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=38541">38541</a>
+            </td>
+
+            <td>2006-02-07
+            </td>
+            <td>enh
+            </td>
+            <td>WORK
+            </td>
+            <td>[pool] Take into account the minIdle in the GenericObject...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=37109">37109</a>
+            </td>
+
+            <td>2006-02-10
+            </td>
+            <td>enh
+            </td>
+            <td>FIXE
+            </td>
+            <td>[Pool] Improvements to maven build
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=30305">30305</a>
+            </td>
+
+            <td>2006-02-11
+            </td>
+            <td>enh
+            </td>
+            <td>LATE
+            </td>
+            <td>[pool] GenericKeyedObjectPool raises exception while dest...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=33949">33949</a>
+            </td>
+
+            <td>2006-02-11
+            </td>
+            <td>enh
+            </td>
+            <td>WONT
+            </td>
+            <td>[pool] genericKeyedObjectPool.borrowObject() calls activa...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=31900">31900</a>
+            </td>
+
+            <td>2006-02-11
+            </td>
+            <td>nor
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] GenericObjectPool: TestWhileIdle is mutually exclu...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=37337">37337</a>
+            </td>
+
+            <td>2006-02-12
+            </td>
+            <td>min
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] GenericObjectPool WHEN_EXHAUSTED_BLOCK behvior cou...
+            </td>
+        </tr>
+
+        <tr>
+           <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=35617">35617</a>
+            </td>
+
+            <td>2006-02-12
+            </td>
+            <td>maj
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool]NumActive goes to negative when the pool can't crea...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=38625">38625</a>
+            </td>
+
+            <td>2006-02-14
+            </td>
+            <td>enh
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] GenericObjectPool currently in SVN isn't Java 1.3 ...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=33265">33265</a>
+            </td>
+
+            <td>2006-02-14
+            </td>
+            <td>min
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] Number of tested objects in eviction runs of Gener...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=36581">36581</a>
+            </td>
+
+            <td>2006-02-14
+            </td>
+            <td>enh
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] GenericObjectPool Evictor should be a TimerTask, n...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=35543">35543</a>
+            </td>
+
+            <td>2006-02-14
+            </td>
+            <td>min
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool][patch] Docs lie: not maxTotal negative for no limi...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=38649">38649</a>
+            </td>
+
+            <td>2006-02-18
+            </td>
+            <td>enh
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] Generic[Keyed]ObjectPool.ObjectTimestampPair can b...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=38690">38690</a>
+            </td>
+
+            <td>2006-02-18
+            </td>
+            <td>min
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] BaseObjectPool closed boolean field needs to be vo...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=38746">38746</a>
+            </td>
+
+            <td>2006-02-22
+            </td>
+            <td>enh
+            </td>
+            <td>FIXE
+            </td>
+            <td>[pool] indicate that ObjectPools.addObject may throw an U...
+            </td>
+        </tr>
+
+        <tr>
+            <td>
+                <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=38856">38856</a>
+            </td>
+            <td>2006-03-06</td>
+            <td>maj</td>
+            <td>DUPL</td>
+            <td>[pool] Killed user connection causes the setautocomit to ...</td>
+        </tr>
+    </table>
+</li>
+</ul>
+</section>
+</body>
+</document>
+

Added: branches/commons-pool/upstream/1.3/xdocs/release-plan.xml
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/release-plan.xml	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/release-plan.xml	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1,135 @@
+<?xml version="1.0"?>
+<!--
+   Copyright 2003-2004 The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<document>
+	<properties>
+		<title>Release Plan</title>
+		<author email="commons-dev at jakarta.apache.org">Commons Documentation Team</author>
+		<revision>$Id: release-plan.xml 155430 2005-02-26 13:13:28Z dirkv $</revision>
+	</properties>
+	<body>
+		<section name="Release Plan for Pool 1.2">
+<subsection name="Administrivia">
+<p>
+This document describes a plan for a 1.2 release of the
+Jakarta-Commons Pool component (for the remainder
+of this document, simply "Pool").  Per the
+<a href="http://jakarta.apache.org/site/decisions.html">
+Jakarta/ASF guidelines</a>, this
+document doesn't mean anything until accepted by the
+relevant committer community via a lazy majority vote
+(hereafter, simply "lazy majority").  Once accepted, it may
+be replaced by an alternative plan, again subject to lazy
+majority approval.
+</p>
+<p>
+Non-binding votes (votes cast by those outside the relevant
+committer community) are welcome, but only binding votes
+are significant for decision making purposes.
+</p>
+</subsection>
+
+<subsection name="Objective">
+<p>The objective of the 1.2 release of Pool is to
+provide a stable and robust release with the intention of 
+providing a stable foundation for the further evolution of 
+the Pool component.</p>
+</subsection>
+
+<subsection name="Release Manager">
+<p><ul><li>Dirk Verbeeck</li></ul></p>
+</subsection>
+
+<subsection name="Release Process">
+<p>The <a href="http://jakarta.apache.org/commons/releases/index.html">
+Jakarta Commons release process</a> will be followed.</p>
+</subsection>
+
+<subsection name="Timeline:">
+<p>
+(All days ending at 23:59:59 GMT in case of dispute.)
+<ul>
+<li><b>Preparation Period</b>:
+  17 May 2004 - 20 May 2004
+  <br/>
+  During this period, all issues preventing building a
+  release candidate should be a addressed. All other 
+  updates (documentation and website) are not blocking.
+</li>
+<br/>
+<li><b>Review Period</b>:
+  21 May 2004 - 28 May 2004
+  <br/>
+  During the Review Period specific design, functional and
+  contract changes to Pool will be considered on the
+  Jakarta-Commons mailing list, using the following
+  process:
+  <ol>
+  <li>Any developer or committer that would like to see
+      a specific change (or group of changes) enacted or
+      rolled back will suggest it on the Jakarta-Commons
+      mailing list (jakarta-commons at jakarta.apache.org).
+  </li>
+  <li>Any interested committer that opposes a given change
+      (or group of changes) is obligated to indicate this
+      disapproval on the list during the Review Period.
+  </li>
+  <li>We will seek, but not strictly require consensus on
+      each decision point.  If consensus cannot be reached,
+      any committer may call for a vote to resolve the
+      issue via a lazy majority vote.
+  </li>
+  </ol>
+  The Review Period may be extended by one week (at a time)
+  given lazy majority approval, in case issues still need
+  to be resolved.
+  <br/><br/>
+  To facilitate the review process Release Candidates 
+  (RC1, RC2, ...) will be provided at the start of the 
+  review period and when mayor issues are resolved.
+</li>
+<br/>
+<li><b>Implementation Period</b>:
+  29 May 2004 - 30 May 2004
+  <br/>
+  (assuming the Review Period is not extended)
+  <br/><br/>
+  During this period, any remaining implementation, testing
+  and documentation will be completed.  No new features
+  or "public" interface changes will be considered
+  in-scope at this time (short of a lazy-majority
+  approved revised release plan or any "showstopper"
+  defects).
+  <br/><br/>
+  At the end of the Implementation Period, a formal
+  release vote will be called, subject to lazy
+  approval.
+  <br/><br/>
+  A formal release vote may be called before the end 
+  of the implementation period, but after the end of 
+  the Review Period, if appropriate.
+  (As soon as all remaining issues are resolved)
+</li>
+<br/>
+<li><b>Release</b>:
+  31 May 2004
+</li>
+</ul>
+</p>
+</subsection>
+</section>
+</body>
+</document>

Added: branches/commons-pool/upstream/1.3/xdocs/style/project.css
===================================================================
--- branches/commons-pool/upstream/1.3/xdocs/style/project.css	                        (rev 0)
+++ branches/commons-pool/upstream/1.3/xdocs/style/project.css	2006-10-26 09:27:52 UTC (rev 2656)
@@ -0,0 +1 @@
+ at import url("http://jakarta.apache.org/style/jakarta-maven.css");




More information about the pkg-java-commits mailing list