Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/commons/pool/impl/GenericKeyedObjectPool.java


1   /*
2    * Copyright 1999-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.pool.impl;
18  
19  import java.util.HashMap;
20  import java.util.Iterator;
21  import java.util.NoSuchElementException;
22  
23  import org.apache.commons.collections.CursorableLinkedList;
24  import org.apache.commons.pool.BaseKeyedObjectPool;
25  import org.apache.commons.pool.KeyedObjectPool;
26  import org.apache.commons.pool.KeyedPoolableObjectFactory;
27  
28  /**
29   * A configurable {@link KeyedObjectPool} implementation.
30   * <p>
31   * When coupled with the appropriate {@link KeyedPoolableObjectFactory},
32   * <tt>GenericKeyedObjectPool</tt> provides robust pooling functionality for
33   * arbitrary objects.
34   * <p>
35   * A <tt>GenericKeyedObjectPool</tt> provides a number of configurable parameters:
36   * <ul>
37   *  <li>
38   *    {@link #setMaxActive <i>maxActive</i>} controls the maximum number of objects (per key)
39   *    that can be borrowed from the pool at one time.  When non-positive, there
40   *    is no limit to the number of objects that may be active at one time.
41   *    When {@link #setMaxActive <i>maxActive</i>} is exceeded, the pool is said to be exhausted.
42   *  </li>
43   *  <li>
44   *    {@link #setMaxIdle <i>maxIdle</i>} controls the maximum number of objects that can
45   *    sit idle in the pool (per key) at any time.  When negative, there
46   *    is no limit to the number of objects that may be idle at one time.
47   *  </li>
48   *  <li>
49   *    {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} specifies the
50   *    behaviour of the {@link #borrowObject} method when the pool is exhausted:
51   *    <ul>
52   *    <li>
53   *      When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
54   *      {@link #WHEN_EXHAUSTED_FAIL}, {@link #borrowObject} will throw
55   *      a {@link NoSuchElementException}
56   *    </li>
57   *    <li>
58   *      When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
59   *      {@link #WHEN_EXHAUSTED_GROW}, {@link #borrowObject} will create a new
60   *      object and return it(essentially making {@link #setMaxActive <i>maxActive</i>}
61   *      meaningless.)
62   *    </li>
63   *    <li>
64   *      When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>}
65   *      is {@link #WHEN_EXHAUSTED_BLOCK}, {@link #borrowObject} will block
66   *      (invoke {@link Object#wait} until a new or idle object is available.
67   *      If a positive {@link #setMaxWait <i>maxWait</i>}
68   *      value is supplied, the {@link #borrowObject} will block for at
69   *      most that many milliseconds, after which a {@link NoSuchElementException}
70   *      will be thrown.  If {@link #setMaxWait <i>maxWait</i>} is non-positive,
71   *      the {@link #borrowObject} method will block indefinitely.
72   *    </li>
73   *    </ul>
74   *  </li>
75   *  <li>
76   *    When {@link #setTestOnBorrow <i>testOnBorrow</i>} is set, the pool will
77   *    attempt to validate each object before it is returned from the
78   *    {@link #borrowObject} method. (Using the provided factory's
79   *    {@link org.apache.commons.pool.PoolableObjectFactory#validateObject} method.)  Objects that fail
80   *    to validate will be dropped from the pool, and a different object will
81   *    be borrowed.
82   *  </li>
83   *  <li>
84   *    When {@link #setTestOnReturn <i>testOnReturn</i>} is set, the pool will
85   *    attempt to validate each object before it is returned to the pool in the
86   *    {@link #returnObject} method. (Using the provided factory's
87   *    {@link org.apache.commons.pool.PoolableObjectFactory#validateObject}
88   *    method.)  Objects that fail to validate will be dropped from the pool.
89   *  </li>
90   * </ul>
91   * <p>
92   * Optionally, one may configure the pool to examine and possibly evict objects as they
93   * sit idle in the pool.  This is performed by an "idle object eviction" thread, which
94   * runs asychronously.  The idle object eviction thread may be configured using the
95   * following attributes:
96   * <ul>
97   *  <li>
98   *   {@link #setTimeBetweenEvictionRunsMillis <i>timeBetweenEvictionRunsMillis</i>}
99   *   indicates how long the eviction thread should sleep before "runs" of examining
100  *   idle objects.  When non-positive, no eviction thread will be launched.
101  *  </li>
102  *  <li>
103  *   {@link #setMinEvictableIdleTimeMillis <i>minEvictableIdleTimeMillis</i>}
104  *   specifies the minimum amount of time that an object may sit idle in the pool
105  *   before it is eligable for eviction due to idle time.  When non-positive, no object
106  *   will be dropped from the pool due to idle time alone.
107  *  </li>
108  *  <li>
109  *   {@link #setTestWhileIdle <i>testWhileIdle</i>} indicates whether or not idle
110  *   objects should be validated using the factory's
111  *   {@link org.apache.commons.pool.PoolableObjectFactory#validateObject} method.  Objects
112  *   that fail to validate will be dropped from the pool.
113  *  </li>
114  * </ul>
115  * <p>
116  * GenericKeyedObjectPool is not usable without a {@link KeyedPoolableObjectFactory}.  A
117  * non-<code>null</code> factory must be provided either as a constructor argument
118  * or via a call to {@link #setFactory} before the pool is used.
119  * </p>
120  * @see GenericObjectPool
121  * @author Rodney Waldhoff
122  * @author Dirk Verbeeck
123  * @version $Revision: 1.26 $ $Date: 2004/02/28 11:46:33 $
124  */
125 public class GenericKeyedObjectPool extends BaseKeyedObjectPool implements KeyedObjectPool {
126 
127     //--- public constants -------------------------------------------
128 
129     /**
130      * A "when exhausted action" type indicating that when the pool is
131      * exhausted (i.e., the maximum number of active objects has
132      * been reached), the {@link #borrowObject}
133      * method should fail, throwing a {@link NoSuchElementException}.
134      * @see #WHEN_EXHAUSTED_BLOCK
135      * @see #WHEN_EXHAUSTED_GROW
136      * @see #setWhenExhaustedAction
137      */
138     public static final byte WHEN_EXHAUSTED_FAIL   = 0;
139 
140     /**
141      * A "when exhausted action" type indicating that when the pool
142      * is exhausted (i.e., the maximum number
143      * of active objects has been reached), the {@link #borrowObject}
144      * method should block until a new object is available, or the
145      * {@link #getMaxWait maximum wait time} has been reached.
146      * @see #WHEN_EXHAUSTED_FAIL
147      * @see #WHEN_EXHAUSTED_GROW
148      * @see #setMaxWait
149      * @see #getMaxWait
150      * @see #setWhenExhaustedAction
151      */
152     public static final byte WHEN_EXHAUSTED_BLOCK  = 1;
153 
154     /**
155      * A "when exhausted action" type indicating that when the pool is
156      * exhausted (i.e., the maximum number
157      * of active objects has been reached), the {@link #borrowObject}
158      * method should simply create a new object anyway.
159      * @see #WHEN_EXHAUSTED_FAIL
160      * @see #WHEN_EXHAUSTED_GROW
161      * @see #setWhenExhaustedAction
162      */
163     public static final byte WHEN_EXHAUSTED_GROW   = 2;
164 
165     /**
166      * The default cap on the number of idle instances in the pool
167      * (per key).
168      * @see #getMaxIdle
169      * @see #setMaxIdle
170      */
171     public static final int DEFAULT_MAX_IDLE  = 8;
172 
173     /**
174      * The default cap on the total number of active instances from the pool
175      * (per key).
176      * @see #getMaxActive
177      * @see #setMaxActive
178      */
179     public static final int DEFAULT_MAX_ACTIVE  = 8;
180 
181     /**
182      * The default cap on the the maximum number of objects that can exists at one time.
183      * @see #getMaxTotal
184      * @see #setMaxTotal
185      */
186     public static final int DEFAULT_MAX_TOTAL  = -1;
187 
188     /**
189      * The default "when exhausted action" for the pool.
190      * @see #WHEN_EXHAUSTED_BLOCK
191      * @see #WHEN_EXHAUSTED_FAIL
192      * @see #WHEN_EXHAUSTED_GROW
193      * @see #setWhenExhaustedAction
194      */
195     public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK;
196 
197     /**
198      * The default maximum amount of time (in millis) the
199      * {@link #borrowObject} method should block before throwing
200      * an exception when the pool is exhausted and the
201      * {@link #getWhenExhaustedAction "when exhausted" action} is
202      * {@link #WHEN_EXHAUSTED_BLOCK}.
203      * @see #getMaxWait
204      * @see #setMaxWait
205      */
206     public static final long DEFAULT_MAX_WAIT = -1L;
207 
208     /**
209      * The default "test on borrow" value.
210      * @see #getTestOnBorrow
211      * @see #setTestOnBorrow
212      */
213     public static final boolean DEFAULT_TEST_ON_BORROW = false;
214 
215     /**
216      * The default "test on return" value.
217      * @see #getTestOnReturn
218      * @see #setTestOnReturn
219      */
220     public static final boolean DEFAULT_TEST_ON_RETURN = false;
221 
222     /**
223      * The default "test while idle" value.
224      * @see #getTestWhileIdle
225      * @see #setTestWhileIdle
226      * @see #getTimeBetweenEvictionRunsMillis
227      * @see #setTimeBetweenEvictionRunsMillis
228      */
229     public static final boolean DEFAULT_TEST_WHILE_IDLE = false;
230 
231     /**
232      * The default "time between eviction runs" value.
233      * @see #getTimeBetweenEvictionRunsMillis
234      * @see #setTimeBetweenEvictionRunsMillis
235      */
236     public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;
237 
238     /**
239      * The default number of objects to examine per run in the
240      * idle object evictor.
241      * @see #getNumTestsPerEvictionRun
242      * @see #setNumTestsPerEvictionRun
243      * @see #getTimeBetweenEvictionRunsMillis
244      * @see #setTimeBetweenEvictionRunsMillis
245      */
246     public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;
247 
248     /**
249      * The default value for {@link #getMinEvictableIdleTimeMillis}.
250      * @see #getMinEvictableIdleTimeMillis
251      * @see #setMinEvictableIdleTimeMillis
252      */
253     public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;
254 
255     //--- constructors -----------------------------------------------
256 
257     /**
258      * Create a new <tt>GenericKeyedObjectPool</tt>..
259      */
260     public GenericKeyedObjectPool() {
261         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);
262     }
263 
264     /**
265      * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
266      * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
267      */
268     public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory) {
269         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);
270     }
271 
272     /**
273      * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
274      * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
275      * @param config a non-<tt>null</tt> {@link GenericKeyedObjectPool.Config} describing my configuration
276      */
277     public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, GenericKeyedObjectPool.Config config) {
278         this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.maxTotal,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle);
279     }
280 
281     /**
282      * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
283      * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
284      * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
285      */
286     public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive) {
287         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);
288     }
289 
290     /**
291      * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
292      * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
293      * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
294      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
295      * @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})
296      */
297     public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) {
298         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);
299     }
300 
301     /**
302      * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
303      * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
304      * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
305      * @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})
306      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
307      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
308      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
309      */
310     public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) {
311         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);
312     }
313 
314     /**
315      * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
316      * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
317      * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
318      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
319      * @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})
320      * @param maxIdle the maximum number of idle objects in my pool (per key) (see {@link #setMaxIdle})
321      */
322     public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
323         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);
324     }
325 
326     /**
327      * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
328      * @param factory the (possibly <tt>null</tt>)KeyedPoolableObjectFactory to use to create, validate and destroy objects
329      * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
330      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
331      * @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})
332      * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
333      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
334      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
335      */
336     public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
337         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);
338     }
339 
340     /**
341      * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
342      * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
343      * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
344      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
345      * @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})
346      * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
347      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
348      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
349      * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
350      * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
351      * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
352      * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
353      */
354     public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
355         this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
356     }
357 
358     /**
359      * Create a new <tt>GenericKeyedObjectPool</tt> using the specified values.
360      * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
361      * @param maxActive the maximum number of objects that can be borrowed from me at one time (per key) (see {@link #setMaxActive})
362      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
363      * @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})
364      * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
365      * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal})
366      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
367      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
368      * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
369      * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
370      * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
371      * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
372      */
373     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) {
374         _factory = factory;
375         _maxActive = maxActive;
376         switch(whenExhaustedAction) {
377             case WHEN_EXHAUSTED_BLOCK:
378             case WHEN_EXHAUSTED_FAIL:
379             case WHEN_EXHAUSTED_GROW:
380                 _whenExhaustedAction = whenExhaustedAction;
381                 break;
382             default:
383                 throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
384         }
385         _maxWait = maxWait;
386         _maxIdle = maxIdle;
387         _maxTotal = maxTotal;
388         _testOnBorrow = testOnBorrow;
389         _testOnReturn = testOnReturn;
390         _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
391         _numTestsPerEvictionRun = numTestsPerEvictionRun;
392         _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
393         _testWhileIdle = testWhileIdle;
394 
395         _poolMap = new HashMap();
396         _activeMap = new HashMap();
397         _poolList = new CursorableLinkedList();
398 
399         startEvictor(_timeBetweenEvictionRunsMillis);
400     }
401 
402     //--- public methods ---------------------------------------------
403 
404     //--- configuration methods --------------------------------------
405 
406     /**
407      * Returns the cap on the number of active instances from my pool (per key).
408      * @return the cap on the number of active instances from my pool (per key).
409      * @see #setMaxActive
410      */
411     public synchronized int getMaxActive() {
412         return _maxActive;
413     }
414 
415     /**
416      * Sets the cap on the number of active instances from my pool (per key).
417      * @param maxActive The cap on the number of active instances from my pool (per key).
418      *                  Use a negative value for an infinite number of instances.
419      * @see #getMaxActive
420      */
421     public synchronized void setMaxActive(int maxActive) {
422         _maxActive = maxActive;
423         notifyAll();
424     }
425 
426     /**
427      * Returns the cap on the total number of instances from my pool.
428      * @return the cap on the total number of instances from my pool.
429      * @see #setMaxTotal
430      */
431     public synchronized int getMaxTotal() {
432         return _maxTotal;
433     }
434 
435     /**
436      * Sets the cap on the total number of instances from my pool.
437      * @param maxTotal The cap on the total number of instances from my pool.
438      *                  Use a negative value for an infinite number of instances.
439      * @see #getMaxTotal
440      */
441     public synchronized void setMaxTotal(int maxTotal) {
442         _maxTotal = maxTotal;
443         notifyAll();
444     }
445 
446     /**
447      * Returns the action to take when the {@link #borrowObject} method
448      * is invoked when the pool is exhausted (the maximum number
449      * of "active" objects has been reached).
450      *
451      * @return one of {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL} or {@link #WHEN_EXHAUSTED_GROW}
452      * @see #setWhenExhaustedAction
453      */
454     public synchronized byte getWhenExhaustedAction() {
455         return _whenExhaustedAction;
456     }
457 
458     /**
459      * Sets the action to take when the {@link #borrowObject} method
460      * is invoked when the pool is exhausted (the maximum number
461      * of "active" objects has been reached).
462      *
463      * @param whenExhaustedAction the action code, which must be one of
464      *        {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL},
465      *        or {@link #WHEN_EXHAUSTED_GROW}
466      * @see #getWhenExhaustedAction
467      */
468     public synchronized void setWhenExhaustedAction(byte whenExhaustedAction) {
469         switch(whenExhaustedAction) {
470             case WHEN_EXHAUSTED_BLOCK:
471             case WHEN_EXHAUSTED_FAIL:
472             case WHEN_EXHAUSTED_GROW:
473                 _whenExhaustedAction = whenExhaustedAction;
474                 notifyAll();
475                 break;
476             default:
477                 throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
478         }
479     }
480 
481 
482     /**
483      * Returns the maximum amount of time (in milliseconds) the
484      * {@link #borrowObject} method should block before throwing
485      * an exception when the pool is exhausted and the
486      * {@link #setWhenExhaustedAction "when exhausted" action} is
487      * {@link #WHEN_EXHAUSTED_BLOCK}.
488      *
489      * When less than 0, the {@link #borrowObject} method
490      * may block indefinitely.
491      *
492      * @see #setMaxWait
493      * @see #setWhenExhaustedAction
494      * @see #WHEN_EXHAUSTED_BLOCK
495      */
496     public synchronized long getMaxWait() {
497         return _maxWait;
498     }
499 
500     /**
501      * Sets the maximum amount of time (in milliseconds) the
502      * {@link #borrowObject} method should block before throwing
503      * an exception when the pool is exhausted and the
504      * {@link #setWhenExhaustedAction "when exhausted" action} is
505      * {@link #WHEN_EXHAUSTED_BLOCK}.
506      *
507      * When less than 0, the {@link #borrowObject} method
508      * may block indefinitely.
509      *
510      * @see #getMaxWait
511      * @see #setWhenExhaustedAction
512      * @see #WHEN_EXHAUSTED_BLOCK
513      */
514     public synchronized void setMaxWait(long maxWait) {
515         _maxWait = maxWait;
516     }
517 
518     /**
519      * Returns the cap on the number of "idle" instances in the pool.
520      * @return the cap on the number of "idle" instances in the pool.
521      * @see #setMaxIdle
522      */
523     public synchronized int getMaxIdle() {
524         return _maxIdle;
525     }
526 
527     /**
528      * Sets the cap on the number of "idle" instances in the pool.
529      * @param maxIdle The cap on the number of "idle" instances in the pool.
530      *                Use a negative value to indicate an unlimited number
531      *                of idle instances.
532      * @see #getMaxIdle
533      */
534     public synchronized void setMaxIdle(int maxIdle) {
535         _maxIdle = maxIdle;
536         notifyAll();
537     }
538 
539     /**
540      * When <tt>true</tt>, objects will be
541      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
542      * before being returned by the {@link #borrowObject}
543      * method.  If the object fails to validate,
544      * it will be dropped from the pool, and we will attempt
545      * to borrow another.
546      *
547      * @see #setTestOnBorrow
548      */
549     public synchronized boolean getTestOnBorrow() {
550         return _testOnBorrow;
551     }
552 
553     /**
554      * When <tt>true</tt>, objects will be
555      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
556      * before being returned by the {@link #borrowObject}
557      * method.  If the object fails to validate,
558      * it will be dropped from the pool, and we will attempt
559      * to borrow another.
560      *
561      * @see #getTestOnBorrow
562      */
563     public synchronized void setTestOnBorrow(boolean testOnBorrow) {
564         _testOnBorrow = testOnBorrow;
565     }
566 
567     /**
568      * When <tt>true</tt>, objects will be
569      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
570      * before being returned to the pool within the
571      * {@link #returnObject}.
572      *
573      * @see #setTestOnReturn
574      */
575     public synchronized boolean getTestOnReturn() {
576         return _testOnReturn;
577     }
578 
579     /**
580      * When <tt>true</tt>, objects will be
581      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
582      * before being returned to the pool within the
583      * {@link #returnObject}.
584      *
585      * @see #getTestOnReturn
586      */
587     public synchronized void setTestOnReturn(boolean testOnReturn) {
588         _testOnReturn = testOnReturn;
589     }
590 
591     /**
592      * Returns the number of milliseconds to sleep between runs of the
593      * idle object evictor thread.
594      * When non-positive, no idle object evictor thread will be
595      * run.
596      *
597      * @see #setTimeBetweenEvictionRunsMillis
598      */
599     public synchronized long getTimeBetweenEvictionRunsMillis() {
600         return _timeBetweenEvictionRunsMillis;
601     }
602 
603     /**
604      * Sets the number of milliseconds to sleep between runs of the
605      * idle object evictor thread.
606      * When non-positive, no idle object evictor thread will be
607      * run.
608      *
609      * @see #getTimeBetweenEvictionRunsMillis
610      */
611     public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
612         _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
613         startEvictor(_timeBetweenEvictionRunsMillis);
614     }
615 
616     /**
617      * Returns the number of objects to examine during each run of the
618      * idle object evictor thread (if any).
619      *
620      * @see #setNumTestsPerEvictionRun
621      * @see #setTimeBetweenEvictionRunsMillis
622      */
623     public synchronized int getNumTestsPerEvictionRun() {
624         return _numTestsPerEvictionRun;
625     }
626 
627     /**
628      * Sets the number of objects to examine during each run of the
629      * idle object evictor thread (if any).
630      * <p>
631      * When a negative value is supplied, <tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
632      * tests will be run.  I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
633      * idle objects will be tested per run.
634      *
635      * @see #getNumTestsPerEvictionRun
636      * @see #setTimeBetweenEvictionRunsMillis
637      */
638     public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
639         _numTestsPerEvictionRun = numTestsPerEvictionRun;
640     }
641 
642     /**
643      * Returns the minimum amount of time an object may sit idle in the pool
644      * before it is eligable for eviction by the idle object evictor
645      * (if any).
646      *
647      * @see #setMinEvictableIdleTimeMillis
648      * @see #setTimeBetweenEvictionRunsMillis
649      */
650     public synchronized long getMinEvictableIdleTimeMillis() {
651         return _minEvictableIdleTimeMillis;
652     }
653 
654     /**
655      * Sets the minimum amount of time an object may sit idle in the pool
656      * before it is eligable for eviction by the idle object evictor
657      * (if any).
658      * When non-positive, no objects will be evicted from the pool
659      * due to idle time alone.
660      *
661      * @see #getMinEvictableIdleTimeMillis
662      * @see #setTimeBetweenEvictionRunsMillis
663      */
664     public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
665         _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
666     }
667 
668     /**
669      * When <tt>true</tt>, objects will be
670      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
671      * by the idle object evictor (if any).  If an object
672      * fails to validate, it will be dropped from the pool.
673      *
674      * @see #setTestWhileIdle
675      * @see #setTimeBetweenEvictionRunsMillis
676      */
677     public synchronized boolean getTestWhileIdle() {
678         return _testWhileIdle;
679     }
680 
681     /**
682      * When <tt>true</tt>, objects will be
683      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
684      * by the idle object evictor (if any).  If an object
685      * fails to validate, it will be dropped from the pool.
686      *
687      * @see #getTestWhileIdle
688      * @see #setTimeBetweenEvictionRunsMillis
689      */
690     public synchronized void setTestWhileIdle(boolean testWhileIdle) {
691         _testWhileIdle = testWhileIdle;
692     }
693 
694     /**
695      * Sets my configuration.
696      * @see GenericKeyedObjectPool.Config
697      */
698     public synchronized void setConfig(GenericKeyedObjectPool.Config conf) {
699         setMaxIdle(conf.maxIdle);
700         setMaxActive(conf.maxActive);
701         setMaxTotal(conf.maxTotal);
702         setMaxWait(conf.maxWait);
703         setWhenExhaustedAction(conf.whenExhaustedAction);
704         setTestOnBorrow(conf.testOnBorrow);
705         setTestOnReturn(conf.testOnReturn);
706         setTestWhileIdle(conf.testWhileIdle);
707         setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);
708         setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);
709         setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);
710     }
711 
712     //-- ObjectPool methods ------------------------------------------
713 
714     public synchronized Object borrowObject(Object key) throws Exception {
715         long starttime = System.currentTimeMillis();
716         boolean newlyCreated = false;
717         for(;;) {
718             CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key));
719             if(null == pool) {
720                 pool = new CursorableLinkedList();
721                 _poolMap.put(key,pool);
722                 _poolList.add(key);
723             }
724             ObjectTimestampPair pair = null;
725             // if there are any sleeping, just grab one of those
726             try {
727                 pair = (ObjectTimestampPair)(pool.removeFirst());
728                 if(null != pair) {
729                     _totalIdle--;
730                 }
731             } catch(NoSuchElementException e) { /* ignored */
732             }
733             // otherwise
734             if(null == pair) {
735                 // if there is a totalMaxActive and we are at the limit then
736                 // we have to make room
737                 // TODO: this could be improved by only removing the oldest object
738                 if ((_maxTotal > 0) && (_totalActive + _totalIdle >= _maxTotal)) {
739                     clear();
740                 }
741                 
742                 // check if we can create one
743                 // (note we know that the num sleeping is 0, else we wouldn't be here)
744                 int active = getActiveCount(key);
745                 if ((_maxActive <= 0 || active < _maxActive) &&
746                     (_maxTotal <= 0 || _totalActive + _totalIdle < _maxTotal)) {
747                     Object obj = _factory.makeObject(key);
748                     pair = new ObjectTimestampPair(obj);
749                     newlyCreated = true;
750                 } else {
751                     // the pool is exhausted
752                     switch(_whenExhaustedAction) {
753                         case WHEN_EXHAUSTED_GROW:
754                             Object obj = _factory.makeObject(key);
755                             pair = new ObjectTimestampPair(obj);
756                             break;
757                         case WHEN_EXHAUSTED_FAIL:
758                             throw new NoSuchElementException();
759                         case WHEN_EXHAUSTED_BLOCK:
760                             try {
761                                 if(_maxWait <= 0) {
762                                     wait();
763                                 } else {
764                                     wait(_maxWait);
765                                 }
766                             } catch(InterruptedException e) {
767                                 // ignored
768                             }
769                             if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
770                                 throw new NoSuchElementException("Timeout waiting for idle object");
771                             } else {
772                                 continue; // keep looping
773                             }
774                         default:
775                             throw new IllegalArgumentException("whenExhaustedAction " + _whenExhaustedAction + " not recognized.");
776                     }
777                 }
778             }
779             _factory.activateObject(key,pair.value);
780             if(_testOnBorrow && !_factory.validateObject(key,pair.value)) {
781                 _factory.destroyObject(key,pair.value);
782                 if(newlyCreated) {
783                     throw new NoSuchElementException("Could not create a validated object");
784                 } // else keep looping
785             } else {
786                 incrementActiveCount(key);
787                 return pair.value;
788             }
789         }
790     }
791 
792     public synchronized void clear() {
793         for(Iterator keyiter = _poolList.iterator(); keyiter.hasNext(); ) {
794             Object key = keyiter.next();
795             CursorableLinkedList list = (CursorableLinkedList)(_poolMap.get(key));
796             for(Iterator it = list.iterator(); it.hasNext(); ) {
797                 try {
798                     _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
799                 } catch(Exception e) {
800                     // ignore error, keep destroying the rest
801                 }
802                 it.remove();
803             }
804         }
805         _poolMap.clear();
806         _poolList.clear();
807         _totalIdle = 0;
808         notifyAll();
809     }
810 
811     public synchronized void clear(Object key) {
812         CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.remove(key));
813         if(null == pool) {
814             return;
815         } else {
816             _poolList.remove(key);
817             for(Iterator it = pool.iterator(); it.hasNext(); ) {
818                 try {
819                     _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
820                 } catch(Exception e) {
821                     // ignore error, keep destroying the rest
822                 }
823                 it.remove();
824                 _totalIdle--;
825             }
826         }
827         notifyAll();
828     }
829 
830     public synchronized int getNumActive() {
831         return _totalActive;
832     }
833 
834     public synchronized int getNumIdle() {
835         return _totalIdle;
836     }
837 
838     public synchronized int getNumActive(Object key) {
839         return getActiveCount(key);
840     }
841 
842     public synchronized int getNumIdle(Object key) {
843         try {
844             return((CursorableLinkedList)(_poolMap.get(key))).size();
845         } catch(Exception e) {
846             return 0;
847         }
848     }
849 
850     public void returnObject(Object key, Object obj) throws Exception {
851 
852         // if we need to validate this object, do so
853         boolean success = true; // whether or not this object passed validation
854         if(_testOnReturn && !_factory.validateObject(key, obj)) {
855             success = false;
856             try {
857                 _factory.destroyObject(key, obj);
858             } catch(Exception e) {
859                 // ignored
860             }
861         } else {
862             try {
863                 _factory.passivateObject(key, obj);
864             } catch(Exception e) {
865                 success = false;
866             }
867         }
868 
869         boolean shouldDestroy = false;
870         synchronized(this) {
871             // grab the pool (list) of objects associated with the given key
872             CursorableLinkedList pool = (CursorableLinkedList) (_poolMap.get(key));
873             // if it doesn't exist, create it
874             if(null == pool) {
875                 pool = new CursorableLinkedList();
876                 _poolMap.put(key, pool);
877                 _poolList.add(key);
878             }
879             decrementActiveCount(key);
880             // if there's no space in the pool, flag the object for destruction
881             // else if we passivated succesfully, return it to the pool
882             if(_maxIdle >= 0 && (pool.size() >= _maxIdle)) {
883                 shouldDestroy = true;
884             } else if(success) {
885                 pool.addFirst(new ObjectTimestampPair(obj));
886                 _totalIdle++;
887             }
888             notifyAll();
889         }
890 
891         if(shouldDestroy) {
892             try {
893                 _factory.destroyObject(key, obj);
894             } catch(Exception e) {
895                 // ignored?
896             }
897         }
898     }
899 
900     public void invalidateObject(Object key, Object obj) throws Exception {
901         try {
902             _factory.destroyObject(key, obj);
903         }
904         finally {
905             synchronized(this) {
906                 decrementActiveCount(key);
907                 notifyAll(); // _totalActive has changed
908             }
909         }
910     }
911 
912     public void addObject(Object key) throws Exception {
913         Object obj = _factory.makeObject(key);
914         synchronized(this) {
915             incrementActiveCount(key); // returnObject will decrement this
916             returnObject(key,obj);
917         }
918     }
919 
920     public synchronized void close() throws Exception {
921         clear();
922         _poolList = null;
923         _poolMap = null;
924         _activeMap = null;
925         if(null != _evictionCursor) {
926             _evictionCursor.close();
927             _evictionCursor = null;
928         }
929         if(null != _evictionKeyCursor) {
930             _evictionKeyCursor.close();
931             _evictionKeyCursor = null;
932         }
933         if(null != _evictor) {
934             _evictor.cancel();
935             _evictor = null;
936         }
937     }
938 
939     public synchronized void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException {
940         if(0 < getNumActive()) {
941             throw new IllegalStateException("Objects are already active");
942         } else {
943             clear();
944             _factory = factory;
945         }
946     }
947 
948     public synchronized void evict() throws Exception {
949         Object key = null;
950         for(int i=0,m=getNumTests();i<m;i++) {
951             if(_poolMap.size() > 0) {
952                 // if we don't have a key cursor, then create one, and close any object cursor
953                 if(null == _evictionKeyCursor) {
954                     _evictionKeyCursor = _poolList.cursor();
955                     key = null;
956                     if(null != _evictionCursor) {
957                         _evictionCursor.close();
958                         _evictionCursor = null;
959                     }
960                 }
961                 // if we don't have an object cursor
962                 if(null == _evictionCursor) {
963                     // if the _evictionKeyCursor has a next value, then use it
964                     if(_evictionKeyCursor.hasNext()) {
965                         key = _evictionKeyCursor.next();
966                         CursorableLinkedList pool = (CursorableLinkedList)(_poolMap.get(key));
967                         _evictionCursor = pool.cursor(pool.size());
968                     } else {
969                         // else close the key cursor and loop back around
970                         if(null != _evictionKeyCursor) {
971                             _evictionKeyCursor.close();
972                             _evictionKeyCursor = _poolList.cursor();
973                             if(null != _evictionCursor) {
974                                 _evictionCursor.close();
975                                 _evictionCursor = null;
976                             }
977                         }
978                         continue;
979                     }
980                 }
981                 // if the _evictionCursor has a previous object, then test it
982                 if(_evictionCursor.hasPrevious()) {
983                     ObjectTimestampPair pair = (ObjectTimestampPair)(_evictionCursor.previous());
984                     boolean removeObject=false;
985                     if(_minEvictableIdleTimeMillis > 0 &&
986                        System.currentTimeMillis() - pair.tstamp > _minEvictableIdleTimeMillis) {
987                        removeObject=true;
988                     } else if(_testWhileIdle) {
989                         boolean active = false;
990                         try {
991                             _factory.activateObject(key,pair.value);
992                             active = true;
993                         } catch(Exception e) {
994                             removeObject=true;
995                         }
996                         if(active) {
997                             if(!_factory.validateObject(key,pair.value)) {
998                                 removeObject=true;
999                             } else {
1000                                try {
1001                                    _factory.passivateObject(key,pair.value);
1002                                } catch(Exception e) {
1003                                    removeObject=true;
1004                                }
1005                            }
1006                        }
1007                    }
1008                    if(removeObject) {
1009                        try {
1010                            _evictionCursor.remove();
1011                            _totalIdle--;
1012                            _factory.destroyObject(key,pair.value);
1013
1014                            // if that was the last object for that key, drop that pool
1015                            if( ((CursorableLinkedList)(_poolMap.get(key))).isEmpty() ) {
1016                                _poolMap.remove(key);
1017                                _poolList.remove(key);
1018                            }
1019                        } catch(Exception e) {
1020                            ; // ignored
1021                        }
1022                    }
1023                } else {
1024                    // else the _evictionCursor is done, so close it and loop around
1025                    if(_evictionCursor != null) {
1026                        _evictionCursor.close();
1027                        _evictionCursor = null;
1028                    }
1029                }
1030            }
1031        }
1032    }
1033
1034    //--- non-public methods ----------------------------------------
1035
1036    /**
1037     * Start the eviction thread or service, or when
1038     * <i>delay</i> is non-positive, stop it
1039     * if it is already running.
1040     */
1041    protected synchronized void startEvictor(long delay) {
1042        if(null != _evictor) {
1043            _evictor.cancel();
1044            _evictor = null;
1045        }
1046        if(delay > 0) {
1047            _evictor = new Evictor(delay);
1048            Thread t = new Thread(_evictor);
1049            t.setDaemon(true);
1050            t.start();
1051        }
1052    }
1053
1054    synchronized String debugInfo() {
1055        StringBuffer buf = new StringBuffer();
1056        buf.append("Active: ").append(getNumActive()).append("\n");
1057        buf.append("Idle: ").append(getNumIdle()).append("\n");
1058        Iterator it = _poolList.iterator();
1059        while(it.hasNext()) {
1060            buf.append("\t").append(_poolMap.get(it.next())).append("\n");
1061        }
1062        return buf.toString();
1063    }
1064
1065    private synchronized int getNumTests() {
1066        if(_numTestsPerEvictionRun >= 0) {
1067            return _numTestsPerEvictionRun;
1068        } else {
1069            return(int)(Math.ceil((double)_totalIdle/Math.abs((double)_numTestsPerEvictionRun)));
1070        }
1071    }
1072
1073    private synchronized void incrementActiveCount(Object key) {
1074        _totalActive++;
1075        Integer active = (Integer)(_activeMap.get(key));
1076        if(null == active) {
1077            _activeMap.put(key,new Integer(1));
1078        } else {
1079            _activeMap.put(key,new Integer(active.intValue() + 1));
1080        }
1081    }
1082
1083    private synchronized void decrementActiveCount(Object key) {
1084        _totalActive--;
1085        Integer active = (Integer)(_activeMap.get(key));
1086        if(null == active) {
1087            // do nothing, either null or zero is OK
1088        } else if(active.intValue() <= 1) {
1089            _activeMap.remove(key);
1090        } else {
1091            _activeMap.put(key, new Integer(active.intValue() - 1));
1092        }
1093    }
1094
1095    private synchronized int getActiveCount(Object key) {
1096        int active = 0;
1097        Integer act = (Integer)(_activeMap.get(key));
1098        if(null != act) {
1099            active = act.intValue();
1100        }
1101        return active;
1102    }
1103
1104    //--- inner classes ----------------------------------------------
1105
1106    /**
1107     * A simple "struct" encapsulating an object instance and a timestamp.
1108     */
1109    class ObjectTimestampPair {
1110        Object value;
1111        long tstamp;
1112
1113        ObjectTimestampPair(Object val) {
1114            value = val;
1115            tstamp = System.currentTimeMillis();
1116        }
1117
1118        ObjectTimestampPair(Object val, long time) {
1119            value = val;
1120            tstamp = time;
1121        }
1122
1123        public String toString() {
1124            return value + ";" + tstamp;
1125        }
1126    }
1127
1128    /**
1129     * The idle object evictor thread.
1130     * @see #setTimeBetweenEvictionRunsMillis
1131     */
1132    class Evictor implements Runnable {
1133        private boolean _cancelled = false;
1134        private long _delay = 0L;
1135
1136        public Evictor(long delay) {
1137            _delay = delay;
1138        }
1139
1140        void cancel() {
1141            _cancelled = true;
1142        }
1143
1144        public void run() {
1145            while(!_cancelled) {
1146                long sleeptime = 0L;
1147                synchronized(GenericKeyedObjectPool.this) {
1148                    sleeptime = _timeBetweenEvictionRunsMillis;
1149                }
1150                try {
1151                    Thread.sleep(sleeptime);
1152                } catch(Exception e) {
1153                    ; // ignored
1154                }
1155                try {
1156                    evict();
1157                } catch(Exception e) {
1158                    ; // ignored
1159                }
1160            }
1161            synchronized(GenericKeyedObjectPool.this) {
1162                if(null != _evictionCursor) {
1163                    _evictionCursor.close();
1164                    _evictionCursor = null;
1165                }
1166                if(null != _evictionKeyCursor) {
1167                    _evictionKeyCursor.close();
1168                    _evictionKeyCursor = null;
1169                }
1170            }
1171        }
1172    }
1173
1174    /**
1175     * A simple "struct" encapsulating the
1176     * configuration information for a {@link GenericKeyedObjectPool}.
1177     * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory,GenericKeyedObjectPool.Config)
1178     * @see GenericKeyedObjectPool#setConfig
1179     */
1180    public static class Config {
1181        public int maxIdle = GenericKeyedObjectPool.DEFAULT_MAX_IDLE;
1182        public int maxActive = GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE;
1183        public int maxTotal = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;
1184        public long maxWait = GenericKeyedObjectPool.DEFAULT_MAX_WAIT;
1185        public byte whenExhaustedAction = GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
1186        public boolean testOnBorrow = GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW;
1187        public boolean testOnReturn = GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN;
1188        public boolean testWhileIdle = GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE;
1189        public long timeBetweenEvictionRunsMillis = GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
1190        public int numTestsPerEvictionRun =  GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
1191        public long minEvictableIdleTimeMillis = GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
1192    }
1193
1194    //--- protected attributes ---------------------------------------
1195
1196    /**
1197     * The cap on the number of idle instances in the pool (per key).
1198     * @see #setMaxIdle
1199     * @see #getMaxIdle
1200     */
1201    private int _maxIdle = DEFAULT_MAX_IDLE;
1202
1203    /**
1204     * The cap on the number of active instances from the pool (per key).
1205     * @see #setMaxActive
1206     * @see #getMaxActive
1207     */
1208    private int _maxActive = DEFAULT_MAX_ACTIVE;
1209
1210    /**
1211     * The cap on the total number of instances from the pool.
1212     * @see #setMaxTotal
1213     * @see #getMaxTotal
1214     */
1215    private int _maxTotal = DEFAULT_MAX_TOTAL;
1216    
1217    /**
1218     * The maximum amount of time (in millis) the
1219     * {@link #borrowObject} method should block before throwing
1220     * an exception when the pool is exhausted and the
1221     * {@link #getWhenExhaustedAction "when exhausted" action} is
1222     * {@link #WHEN_EXHAUSTED_BLOCK}.
1223     *
1224     * When less than 0, the {@link #borrowObject} method
1225     * may block indefinitely.
1226     *
1227     * @see #setMaxWait
1228     * @see #getMaxWait
1229     * @see #WHEN_EXHAUSTED_BLOCK
1230     * @see #setWhenExhaustedAction
1231     * @see #getWhenExhaustedAction
1232     */
1233    private long _maxWait = DEFAULT_MAX_WAIT;
1234
1235    /**
1236     * The action to take when the {@link #borrowObject} method
1237     * is invoked when the pool is exhausted (the maximum number
1238     * of "active" objects has been reached).
1239     *
1240     * @see #WHEN_EXHAUSTED_BLOCK
1241     * @see #WHEN_EXHAUSTED_FAIL
1242     * @see #WHEN_EXHAUSTED_GROW
1243     * @see #DEFAULT_WHEN_EXHAUSTED_ACTION
1244     * @see #setWhenExhaustedAction
1245     * @see #getWhenExhaustedAction
1246     */
1247    private byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION;
1248
1249    /**
1250     * When <tt>true</tt>, objects will be
1251     * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
1252     * before being returned by the {@link #borrowObject}
1253     * method.  If the object fails to validate,
1254     * it will be dropped from the pool, and we will attempt
1255     * to borrow another.
1256     *
1257     * @see #setTestOnBorrow
1258     * @see #getTestOnBorrow
1259     */
1260    private boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW;
1261
1262    /**
1263     * When <tt>true</tt>, objects will be
1264     * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
1265     * before being returned to the pool within the
1266     * {@link #returnObject}.
1267     *
1268     * @see #getTestOnReturn
1269     * @see #setTestOnReturn
1270     */
1271    private boolean _testOnReturn = DEFAULT_TEST_ON_RETURN;
1272
1273    /**
1274     * When <tt>true</tt>, objects will be
1275     * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
1276     * by the idle object evictor (if any).  If an object
1277     * fails to validate, it will be dropped from the pool.
1278     *
1279     * @see #setTestWhileIdle
1280     * @see #getTestWhileIdle
1281     * @see #getTimeBetweenEvictionRunsMillis
1282     * @see #setTimeBetweenEvictionRunsMillis
1283     */
1284    private boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE;
1285
1286    /**
1287     * The number of milliseconds to sleep between runs of the
1288     * idle object evictor thread.
1289     * When non-positive, no idle object evictor thread will be
1290     * run.
1291     *
1292     * @see #setTimeBetweenEvictionRunsMillis
1293     * @see #getTimeBetweenEvictionRunsMillis
1294     */
1295    private long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
1296
1297    /**
1298     * The number of objects to examine during each run of the
1299     * idle object evictor thread (if any).
1300     * <p>
1301     * When a negative value is supplied, <tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
1302     * tests will be run.  I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
1303     * idle objects will be tested per run.
1304     *
1305     * @see #setNumTestsPerEvictionRun
1306     * @see #getNumTestsPerEvictionRun
1307     * @see #getTimeBetweenEvictionRunsMillis
1308     * @see #setTimeBetweenEvictionRunsMillis
1309     */
1310    private int _numTestsPerEvictionRun =  DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
1311
1312    /**
1313     * The minimum amount of time an object may sit idle in the pool
1314     * before it is eligable for eviction by the idle object evictor
1315     * (if any).
1316     * When non-positive, no objects will be evicted from the pool
1317     * due to idle time alone.
1318     *
1319     * @see #setMinEvictableIdleTimeMillis
1320     * @see #getMinEvictableIdleTimeMillis
1321     * @see #getTimeBetweenEvictionRunsMillis
1322     * @se