Coverage Report - org.apache.commons.pool.impl.TapestryKeyedObjectPool
 
Classes in this File Line Coverage Branch Coverage Complexity
TapestryKeyedObjectPool
0%
0/474
0%
0/208
3
TapestryKeyedObjectPool$1
N/A
N/A
3
TapestryKeyedObjectPool$Config
0%
0/14
N/A
3
TapestryKeyedObjectPool$Evictor
0%
0/8
N/A
3
TapestryKeyedObjectPool$ObjectQueue
0%
0/10
0%
0/2
3
TapestryKeyedObjectPool$ObjectTimestampPair
0%
0/12
0%
0/2
3
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.commons.pool.impl;
 19  
 
 20  
 import java.util.HashMap;
 21  
 import java.util.Iterator;
 22  
 import java.util.Map;
 23  
 import java.util.NoSuchElementException;
 24  
 import java.util.Set;
 25  
 import java.util.TreeMap;
 26  
 import java.util.TimerTask;
 27  
 
 28  
 import org.apache.commons.pool.BaseKeyedObjectPool;
 29  
 import org.apache.commons.pool.KeyedObjectPool;
 30  
 import org.apache.commons.pool.KeyedPoolableObjectFactory;
 31  
 
 32  
 /**
 33  
  * A configurable <code>KeyedObjectPool</code> implementation modifying the standard
 34  
  * version coming with commons-pool to not lock each and every pool access which led
 35  
  * to scalability issues and even deadlocks (TAPESTRY-2530, TAPESTRY-2382).
 36  
  * TODO: switch back to the standard version once it works better.
 37  
  *
 38  
  * <p>
 39  
  * When coupled with the appropriate {@link KeyedPoolableObjectFactory},
 40  
  * <code>GenericKeyedObjectPool</code> provides robust pooling functionality for
 41  
  * keyed objects. A <code>GenericKeyedObjectPool</code> can be viewed as a map
 42  
  * of pools, keyed on the (unique) key values provided to the 
 43  
  * {@link #preparePool preparePool}, {@link #addObject addObject} or
 44  
  * {@link #borrowObject borrowObject} methods. Each time a new key value is
 45  
  * provided to one of these methods, a new pool is created under the given key
 46  
  * to be managed by the containing <code>GenericKeyedObjectPool.</code>
 47  
  * </p>
 48  
  * <p>A <code>GenericKeyedObjectPool</code> provides a number of configurable
 49  
  * parameters:</p>
 50  
  * <ul>
 51  
  *  <li>
 52  
  *    {@link #setMaxActive maxActive} controls the maximum number of objects
 53  
  *    (per key) that can be borrowed from the pool at one time.  When
 54  
  *    non-positive, there is no limit to the number of objects per key.
 55  
  *    When {@link #setMaxActive maxActive} is exceeded, the keyed pool is said
 56  
  *    to be exhausted.  The default setting for this parameter is 8.
 57  
  *  </li>
 58  
  *  <li>
 59  
  *    {@link #setMaxTotal maxTotal} sets a global limit on the number of objects
 60  
  *    that can be in circulation (active or idle) within the combined set of
 61  
  *    pools.  When non-positive, there is no limit to the total number of
 62  
  *    objects in circulation. When {@link #setMaxTotal maxTotal} is exceeded,
 63  
  *    all keyed pools are exhausted. When <code>maxTotal</code> is set to a
 64  
  *    positive value and {@link #borrowObject borrowObject} is invoked
 65  
  *    when at the limit with no idle instances available, an attempt is made to
 66  
  *    create room by clearing the oldest 15% of the elements from the keyed
 67  
  *    pools. The default setting for this parameter is -1 (no limit).
 68  
  *  </li>
 69  
  *  <li>
 70  
  *    {@link #setMaxIdle maxIdle} controls the maximum number of objects that can
 71  
  *    sit idle in the pool (per key) at any time.  When negative, there
 72  
  *    is no limit to the number of objects that may be idle per key. The
 73  
  *    default setting for this parameter is 8.
 74  
  *  </li>
 75  
  *  <li>
 76  
  *    {@link #setWhenExhaustedAction whenExhaustedAction} specifies the
 77  
  *    behavior of the {@link #borrowObject borrowObject} method when a keyed
 78  
  *    pool is exhausted:
 79  
  *    <ul>
 80  
  *    <li>
 81  
  *      When {@link #setWhenExhaustedAction whenExhaustedAction} is
 82  
  *      {@link #WHEN_EXHAUSTED_FAIL}, {@link #borrowObject borrowObject} will throw
 83  
  *      a {@link NoSuchElementException}
 84  
  *    </li>
 85  
  *    <li>
 86  
  *      When {@link #setWhenExhaustedAction whenExhaustedAction} is
 87  
  *      {@link #WHEN_EXHAUSTED_GROW}, {@link #borrowObject borrowObject} will create a new
 88  
  *      object and return it (essentially making {@link #setMaxActive maxActive}
 89  
  *      meaningless.)
 90  
  *    </li>
 91  
  *    <li>
 92  
  *      When {@link #setWhenExhaustedAction whenExhaustedAction}
 93  
  *      is {@link #WHEN_EXHAUSTED_BLOCK}, {@link #borrowObject borrowObject} will block
 94  
  *      (invoke {@link Object#wait() wait} until a new or idle object is available.
 95  
  *      If a positive {@link #setMaxWait maxWait}
 96  
  *      value is supplied, the {@link #borrowObject borrowObject} will block for at
 97  
  *      most that many milliseconds, after which a {@link NoSuchElementException}
 98  
  *      will be thrown.  If {@link #setMaxWait maxWait} is non-positive,
 99  
  *      the {@link #borrowObject borrowObject} method will block indefinitely.
 100  
  *    </li>
 101  
  *    </ul>
 102  
  *    The default <code>whenExhaustedAction</code> setting is
 103  
  *    {@link #WHEN_EXHAUSTED_BLOCK}.
 104  
  *  </li>
 105  
  *  <li>
 106  
  *    When {@link #setTestOnBorrow testOnBorrow} is set, the pool will
 107  
  *    attempt to validate each object before it is returned from the
 108  
  *    {@link #borrowObject borrowObject} method. (Using the provided factory's
 109  
  *    {@link KeyedPoolableObjectFactory#validateObject validateObject} method.)
 110  
  *    Objects that fail to validate will be dropped from the pool, and a
 111  
  *    different object will be borrowed. The default setting for this parameter
 112  
  *    is <code>false.</code>
 113  
  *  </li>
 114  
  *  <li>
 115  
  *    When {@link #setTestOnReturn testOnReturn} is set, the pool will
 116  
  *    attempt to validate each object before it is returned to the pool in the
 117  
  *    {@link #returnObject returnObject} method. (Using the provided factory's
 118  
  *    {@link KeyedPoolableObjectFactory#validateObject validateObject}
 119  
  *    method.)  Objects that fail to validate will be dropped from the pool.
 120  
  *    The default setting for this parameter is <code>false.</code>
 121  
  *  </li>
 122  
  * </ul>
 123  
  * <p>
 124  
  * Optionally, one may configure the pool to examine and possibly evict objects
 125  
  * as they sit idle in the pool and to ensure that a minimum number of idle
 126  
  * objects is maintained for each key. This is performed by an
 127  
  * "idle object eviction" thread, which runs asynchronously. Caution should be
 128  
  * used when configuring this optional feature. Eviction runs require an
 129  
  * exclusive synchronization lock on the pool, so if they run too frequently
 130  
  * and / or incur excessive latency when creating, destroying or validating
 131  
  * object instances, performance issues may result.  The idle object eviction
 132  
  * thread may be configured using the following attributes:
 133  
  * <ul>
 134  
  *  <li>
 135  
  *   {@link #setTimeBetweenEvictionRunsMillis timeBetweenEvictionRunsMillis}
 136  
  *   indicates how long the eviction thread should sleep before "runs" of examining
 137  
  *   idle objects.  When non-positive, no eviction thread will be launched. The
 138  
  *   default setting for this parameter is -1 (i.e., by default, idle object
 139  
  *   eviction is disabled).
 140  
  *  </li>
 141  
  *  <li>
 142  
  *   {@link #setMinEvictableIdleTimeMillis minEvictableIdleTimeMillis}
 143  
  *   specifies the minimum amount of time that an object may sit idle in the
 144  
  *   pool before it is eligible for eviction due to idle time.  When
 145  
  *   non-positive, no object will be dropped from the pool due to idle time
 146  
  *   alone.  This setting has no effect unless 
 147  
  *   <code>timeBetweenEvictionRunsMillis > 0.</code>  The default setting
 148  
  *   for this parameter is 30 minutes.
 149  
  *  </li>
 150  
  *  <li>
 151  
  *   {@link #setTestWhileIdle testWhileIdle} indicates whether or not idle
 152  
  *   objects should be validated using the factory's
 153  
  *   {@link KeyedPoolableObjectFactory#validateObject validateObject} method
 154  
  *   during idle object eviction runs.  Objects that fail to validate will be
 155  
  *   dropped from the pool. This setting has no effect unless 
 156  
  *   <code>timeBetweenEvictionRunsMillis > 0.</code>  The default setting
 157  
  *   for this parameter is <code>false.</code>
 158  
  *  </li>
 159  
  *  <li>
 160  
  *    {@link #setMinIdle minIdle} sets a target value for the minimum number of
 161  
  *    idle objects (per key) that should always be available. If this parameter
 162  
  *    is set to a positive number and 
 163  
  *    <code>timeBetweenEvictionRunsMillis > 0,</code> each time the idle object
 164  
  *    eviction thread runs, it will try to create enough idle instances so that
 165  
  *    there will be <code>minIdle</code> idle instances available under each
 166  
  *    key. This parameter is also used by {@link #preparePool preparePool}
 167  
  *    if <code>true</code> is provided as that method's
 168  
  *    <code>populateImmediately</code> parameter. The default setting for this
 169  
  *    parameter is 0.
 170  
  *  </li>
 171  
  * </ul>
 172  
  * <p>
 173  
  * The pools can be configured to behave as LIFO queues with respect to idle
 174  
  * objects - always returning the most recently used object from the pool,
 175  
  * or as FIFO queues, where borrowObject always returns the oldest object
 176  
  * in the idle object pool.
 177  
  * <ul>
 178  
  *  <li>
 179  
  *   {@link #setLifo <i>Lifo</i>}
 180  
  *   determines whether or not the pools return idle objects in 
 181  
  *   last-in-first-out order. The default setting for this parameter is 
 182  
  *   <code>true.</code>
 183  
  *  </li>
 184  
  * </ul>
 185  
  * <p>
 186  
  * GenericKeyedObjectPool is not usable without a {@link KeyedPoolableObjectFactory}.  A
 187  
  * non-<code>null</code> factory must be provided either as a constructor argument
 188  
  * or via a call to {@link #setFactory setFactory} before the pool is used.
 189  
  * </p>
 190  
  * @see GenericObjectPool
 191  
  * @author Rodney Waldhoff
 192  
  * @author Dirk Verbeeck
 193  
  * @author Sandy McArthur
 194  
  * @version $Revision: 620830 $ $Date: 2008-02-12 16:41:58 +0100 (Di, 12 Feb 2008) $
 195  
  * @since Pool 1.0
 196  
  */
 197  0
 public class TapestryKeyedObjectPool extends BaseKeyedObjectPool implements KeyedObjectPool {
 198  
 
 199  
     //--- public constants -------------------------------------------
 200  
 
 201  
     /**
 202  
      * A "when exhausted action" type indicating that when the pool is
 203  
      * exhausted (i.e., the maximum number of active objects has
 204  
      * been reached), the {@link #borrowObject}
 205  
      * method should fail, throwing a {@link NoSuchElementException}.
 206  
      * @see #WHEN_EXHAUSTED_BLOCK
 207  
      * @see #WHEN_EXHAUSTED_GROW
 208  
      * @see #setWhenExhaustedAction
 209  
      */
 210  
     public static final byte WHEN_EXHAUSTED_FAIL   = 0;
 211  
 
 212  
     /**
 213  
      * A "when exhausted action" type indicating that when the pool
 214  
      * is exhausted (i.e., the maximum number
 215  
      * of active objects has been reached), the {@link #borrowObject}
 216  
      * method should block until a new object is available, or the
 217  
      * {@link #getMaxWait maximum wait time} has been reached.
 218  
      * @see #WHEN_EXHAUSTED_FAIL
 219  
      * @see #WHEN_EXHAUSTED_GROW
 220  
      * @see #setMaxWait
 221  
      * @see #getMaxWait
 222  
      * @see #setWhenExhaustedAction
 223  
      */
 224  
     public static final byte WHEN_EXHAUSTED_BLOCK  = 1;
 225  
 
 226  
     /**
 227  
      * A "when exhausted action" type indicating that when the pool is
 228  
      * exhausted (i.e., the maximum number
 229  
      * of active objects has been reached), the {@link #borrowObject}
 230  
      * method should simply create a new object anyway.
 231  
      * @see #WHEN_EXHAUSTED_FAIL
 232  
      * @see #WHEN_EXHAUSTED_GROW
 233  
      * @see #setWhenExhaustedAction
 234  
      */
 235  
     public static final byte WHEN_EXHAUSTED_GROW   = 2;
 236  
 
 237  
     /**
 238  
      * The default cap on the number of idle instances (per key) in the pool.
 239  
      * @see #getMaxIdle
 240  
      * @see #setMaxIdle
 241  
      */
 242  
     public static final int DEFAULT_MAX_IDLE  = 8;
 243  
 
 244  
     /**
 245  
      * The default cap on the total number of active instances (per key)
 246  
      * from the pool.
 247  
      * @see #getMaxActive
 248  
      * @see #setMaxActive
 249  
      */
 250  
     public static final int DEFAULT_MAX_ACTIVE  = 8;
 251  
 
 252  
     /**
 253  
      * The default cap on the the overall maximum number of objects that can
 254  
      * exist at one time.
 255  
      * @see #getMaxTotal
 256  
      * @see #setMaxTotal
 257  
      */
 258  
     public static final int DEFAULT_MAX_TOTAL  = -1;
 259  
 
 260  
     /**
 261  
      * The default "when exhausted action" for the pool.
 262  
      * @see #WHEN_EXHAUSTED_BLOCK
 263  
      * @see #WHEN_EXHAUSTED_FAIL
 264  
      * @see #WHEN_EXHAUSTED_GROW
 265  
      * @see #setWhenExhaustedAction
 266  
      */
 267  
     public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK;
 268  
 
 269  
     /**
 270  
      * The default maximum amount of time (in milliseconds) the
 271  
      * {@link #borrowObject} method should block before throwing
 272  
      * an exception when the pool is exhausted and the
 273  
      * {@link #getWhenExhaustedAction "when exhausted" action} is
 274  
      * {@link #WHEN_EXHAUSTED_BLOCK}.
 275  
      * @see #getMaxWait
 276  
      * @see #setMaxWait
 277  
      */
 278  
     public static final long DEFAULT_MAX_WAIT = -1L;
 279  
 
 280  
     /**
 281  
      * The default "test on borrow" value.
 282  
      * @see #getTestOnBorrow
 283  
      * @see #setTestOnBorrow
 284  
      */
 285  
     public static final boolean DEFAULT_TEST_ON_BORROW = false;
 286  
 
 287  
     /**
 288  
      * The default "test on return" value.
 289  
      * @see #getTestOnReturn
 290  
      * @see #setTestOnReturn
 291  
      */
 292  
     public static final boolean DEFAULT_TEST_ON_RETURN = false;
 293  
 
 294  
     /**
 295  
      * The default "test while idle" value.
 296  
      * @see #getTestWhileIdle
 297  
      * @see #setTestWhileIdle
 298  
      * @see #getTimeBetweenEvictionRunsMillis
 299  
      * @see #setTimeBetweenEvictionRunsMillis
 300  
      */
 301  
     public static final boolean DEFAULT_TEST_WHILE_IDLE = false;
 302  
 
 303  
     /**
 304  
      * The default "time between eviction runs" value.
 305  
      * @see #getTimeBetweenEvictionRunsMillis
 306  
      * @see #setTimeBetweenEvictionRunsMillis
 307  
      */
 308  
     public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;
 309  
 
 310  
     /**
 311  
      * The default number of objects to examine per run in the
 312  
      * idle object evictor.
 313  
      * @see #getNumTestsPerEvictionRun
 314  
      * @see #setNumTestsPerEvictionRun
 315  
      * @see #getTimeBetweenEvictionRunsMillis
 316  
      * @see #setTimeBetweenEvictionRunsMillis
 317  
      */
 318  
     public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;
 319  
 
 320  
     /**
 321  
      * The default value for {@link #getMinEvictableIdleTimeMillis}.
 322  
      * @see #getMinEvictableIdleTimeMillis
 323  
      * @see #setMinEvictableIdleTimeMillis
 324  
      */
 325  
     public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;
 326  
 
 327  
     /**
 328  
      * The default minimum level of idle objects in the pool.
 329  
      * @since Pool 1.3
 330  
      * @see #setMinIdle
 331  
      * @see #getMinIdle
 332  
      */
 333  
     public static final int DEFAULT_MIN_IDLE = 0;
 334  
     
 335  
     /**
 336  
      * The default LIFO status. True means that borrowObject returns the
 337  
      * most recently used ("last in") idle object in a pool (if there are
 338  
      * idle instances available).  False means that pools behave as FIFO
 339  
      * queues - objects are taken from idle object pools in the order that
 340  
      * they are returned.
 341  
      * @see #setLifo
 342  
      */
 343  
     public static final boolean DEFAULT_LIFO = true;
 344  
     
 345  
     //--- constructors -----------------------------------------------
 346  
 
 347  
     /**
 348  
      * Create a new <code>GenericKeyedObjectPool</code> with no factory.
 349  
      *
 350  
      * @see #GenericKeyedObjectPool(KeyedPoolableObjectFactory)
 351  
      * @see #setFactory(KeyedPoolableObjectFactory)
 352  
      */
 353  
     public TapestryKeyedObjectPool() {
 354  0
         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);
 355  0
     }
 356  
 
 357  
     /**
 358  
      * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
 359  
      * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
 360  
      */
 361  
     public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory) {
 362  0
         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);
 363  0
     }
 364  
 
 365  
     /**
 366  
      * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
 367  
      * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
 368  
      * @param config a non-<code>null</code> {@link GenericKeyedObjectPool.Config} describing the configuration
 369  
      */
 370  
     public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, GenericKeyedObjectPool.Config config) {
 371  0
         this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.maxTotal, config.minIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle,config.lifo);
 372  0
     }
 373  
 
 374  
     /**
 375  
      * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
 376  
      * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
 377  
      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
 378  
      */
 379  
     public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive) {
 380  0
         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);
 381  0
     }
 382  
 
 383  
     /**
 384  
      * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
 385  
      * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
 386  
      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
 387  
      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
 388  
      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
 389  
      */
 390  
     public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) {
 391  0
         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);
 392  0
     }
 393  
 
 394  
     /**
 395  
      * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
 396  
      * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
 397  
      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
 398  
      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
 399  
      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
 400  
      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
 401  
      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
 402  
      */
 403  
     public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) {
 404  0
         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);
 405  0
     }
 406  
 
 407  
     /**
 408  
      * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
 409  
      * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
 410  
      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
 411  
      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
 412  
      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
 413  
      * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
 414  
      */
 415  
     public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
 416  0
         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);
 417  0
     }
 418  
 
 419  
     /**
 420  
      * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
 421  
      * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
 422  
      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
 423  
      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
 424  
      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})
 425  
      * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
 426  
      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
 427  
      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
 428  
      */
 429  
     public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
 430  0
         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);
 431  0
     }
 432  
 
 433  
     /**
 434  
      * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
 435  
      * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
 436  
      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
 437  
      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
 438  
      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
 439  
      * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
 440  
      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
 441  
      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
 442  
      * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
 443  
      * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
 444  
      * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis})
 445  
      * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
 446  
      */
 447  
     public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
 448  0
         this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, GenericKeyedObjectPool.DEFAULT_MAX_TOTAL, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
 449  0
     }
 450  
 
 451  
     /**
 452  
      * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
 453  
      * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
 454  
      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
 455  
      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
 456  
      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
 457  
      * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
 458  
      * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal})
 459  
      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
 460  
      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
 461  
      * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
 462  
      * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
 463  
      * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis})
 464  
      * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
 465  
      */
 466  
     public TapestryKeyedObjectPool(KeyedPoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int maxTotal, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
 467  0
         this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, GenericKeyedObjectPool.DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
 468  0
     }
 469  
     
 470  
     /**
 471  
      * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
 472  
      * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
 473  
      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
 474  
      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
 475  
      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
 476  
      * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
 477  
      * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal})
 478  
      * @param minIdle the minimum number of idle objects to have in the pool at any one time (see {@link #setMinIdle})
 479  
      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
 480  
      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
 481  
      * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
 482  
      * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
 483  
      * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis})
 484  
      * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
 485  
      * @since Pool 1.3
 486  
      */
 487  
     public TapestryKeyedObjectPool(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) {
 488  0
         this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, maxTotal, minIdle, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle, DEFAULT_LIFO);
 489  0
     }
 490  
     
 491  
     /**
 492  
      * Create a new <code>GenericKeyedObjectPool</code> using the specified values.
 493  
      * @param factory the <code>KeyedPoolableObjectFactory</code> to use to create, validate, and destroy objects if not <code>null</code>
 494  
      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
 495  
      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
 496  
      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted and <code>whenExhaustedAction</code> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
 497  
      * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
 498  
      * @param maxTotal the maximum number of objects that can exists at one time (see {@link #setMaxTotal})
 499  
      * @param minIdle the minimum number of idle objects to have in the pool at any one time (see {@link #setMinIdle})
 500  
      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
 501  
      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
 502  
      * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
 503  
      * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
 504  
      * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligible for eviction (see {@link #setMinEvictableIdleTimeMillis})
 505  
      * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
 506  
      * @param lifo whether or not the pools behave as LIFO (last in first out) queues (see {@link #setLifo}) 
 507  
      * @since Pool 1.4
 508  
      */
 509  0
     public TapestryKeyedObjectPool(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, boolean lifo) {
 510  0
         _factory = factory;
 511  0
         _maxActive = maxActive;
 512  0
         _lifo = lifo;
 513  0
         switch(whenExhaustedAction) {
 514  
             case WHEN_EXHAUSTED_BLOCK:
 515  
             case WHEN_EXHAUSTED_FAIL:
 516  
             case WHEN_EXHAUSTED_GROW:
 517  0
                 _whenExhaustedAction = whenExhaustedAction;
 518  0
                 break;
 519  
             default:
 520  0
                 throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
 521  
         }
 522  0
         _maxWait = maxWait;
 523  0
         _maxIdle = maxIdle;
 524  0
         _maxTotal = maxTotal;
 525  0
         _minIdle = minIdle;
 526  0
         _testOnBorrow = testOnBorrow;
 527  0
         _testOnReturn = testOnReturn;
 528  0
         _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
 529  0
         _numTestsPerEvictionRun = numTestsPerEvictionRun;
 530  0
         _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
 531  0
         _testWhileIdle = testWhileIdle;
 532  
 
 533  0
         _poolMap = new HashMap();
 534  0
         _poolList = new CursorableLinkedList();
 535  
 
 536  0
         startEvictor(_timeBetweenEvictionRunsMillis);
 537  0
     }
 538  
 
 539  
     //--- public methods ---------------------------------------------
 540  
 
 541  
     //--- configuration methods --------------------------------------
 542  
 
 543  
     /**
 544  
      * Returns the cap on the number of active instances per key.
 545  
      * A negative value indicates no limit.
 546  
      * @return the cap on the number of active instances per key.
 547  
      * @see #setMaxActive
 548  
      */
 549  
     public synchronized int getMaxActive() {
 550  0
         return _maxActive;
 551  
     }
 552  
 
 553  
     /**
 554  
      * Sets the cap on the number of active instances per key.
 555  
      * @param maxActive The cap on the number of active instances per key.
 556  
      * Use a negative value for no limit.
 557  
      * @see #getMaxActive
 558  
      */
 559  
     public synchronized void setMaxActive(int maxActive) {
 560  0
         _maxActive = maxActive;
 561  0
         notifyAll();
 562  0
     }
 563  
 
 564  
     /**
 565  
      * Returns the overall maximum number of objects (across pools) that can
 566  
      * exist at one time. A negative value indicates no limit.
 567  
      * @return the maximum number of instances in circulation at one time.
 568  
      * @see #setMaxTotal
 569  
      */
 570  
     public synchronized int getMaxTotal() {
 571  0
         return _maxTotal;
 572  
     }
 573  
 
 574  
     /**
 575  
      * Sets the cap on the total number of instances from all pools combined.
 576  
      * When <code>maxTotal</code> is set to a
 577  
      * positive value and {@link #borrowObject borrowObject} is invoked
 578  
      * when at the limit with no idle instances available, an attempt is made to
 579  
      * create room by clearing the oldest 15% of the elements from the keyed
 580  
      * pools.
 581  
      * 
 582  
      * @param maxTotal The cap on the total number of instances across pools.
 583  
      * Use a negative value for no limit.
 584  
      * @see #getMaxTotal
 585  
      */
 586  
     public synchronized void setMaxTotal(int maxTotal) {
 587  0
         _maxTotal = maxTotal;
 588  0
         notifyAll();
 589  0
     }
 590  
 
 591  
     /**
 592  
      * Returns the action to take when the {@link #borrowObject} method
 593  
      * is invoked when the pool is exhausted (the maximum number
 594  
      * of "active" objects has been reached).
 595  
      *
 596  
      * @return one of {@link #WHEN_EXHAUSTED_BLOCK}, 
 597  
      * {@link #WHEN_EXHAUSTED_FAIL} or {@link #WHEN_EXHAUSTED_GROW}
 598  
      * @see #setWhenExhaustedAction
 599  
      */
 600  
     public synchronized byte getWhenExhaustedAction() {
 601  0
         return _whenExhaustedAction;
 602  
     }
 603  
 
 604  
     /**
 605  
      * Sets the action to take when the {@link #borrowObject} method
 606  
      * is invoked when the pool is exhausted (the maximum number
 607  
      * of "active" objects has been reached).
 608  
      *
 609  
      * @param whenExhaustedAction the action code, which must be one of
 610  
      *        {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL},
 611  
      *        or {@link #WHEN_EXHAUSTED_GROW}
 612  
      * @see #getWhenExhaustedAction
 613  
      */
 614  
     public synchronized void setWhenExhaustedAction(byte whenExhaustedAction) {
 615  0
         switch(whenExhaustedAction) {
 616  
             case WHEN_EXHAUSTED_BLOCK:
 617  
             case WHEN_EXHAUSTED_FAIL:
 618  
             case WHEN_EXHAUSTED_GROW:
 619  0
                 _whenExhaustedAction = whenExhaustedAction;
 620  0
                 notifyAll();
 621  0
                 break;
 622  
             default:
 623  0
                 throw new IllegalArgumentException("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
 624  
         }
 625  0
     }
 626  
 
 627  
 
 628  
     /**
 629  
      * Returns the maximum amount of time (in milliseconds) the
 630  
      * {@link #borrowObject} method should block before throwing
 631  
      * an exception when the pool is exhausted and the
 632  
      * {@link #setWhenExhaustedAction "when exhausted" action} is
 633  
      * {@link #WHEN_EXHAUSTED_BLOCK}.
 634  
      *
 635  
      * When less than or equal to 0, the {@link #borrowObject} method
 636  
      * may block indefinitely.
 637  
      *
 638  
      * @return the maximum number of milliseconds borrowObject will block.
 639  
      * @see #setMaxWait
 640  
      * @see #setWhenExhaustedAction
 641  
      * @see #WHEN_EXHAUSTED_BLOCK
 642  
      */
 643  
     public synchronized long getMaxWait() {
 644  0
         return _maxWait;
 645  
     }
 646  
 
 647  
     /**
 648  
      * Sets the maximum amount of time (in milliseconds) the
 649  
      * {@link #borrowObject} method should block before throwing
 650  
      * an exception when the pool is exhausted and the
 651  
      * {@link #setWhenExhaustedAction "when exhausted" action} is
 652  
      * {@link #WHEN_EXHAUSTED_BLOCK}.
 653  
      *
 654  
      * When less than or equal to 0, the {@link #borrowObject} method
 655  
      * may block indefinitely.
 656  
      *
 657  
      * @param maxWait the maximum number of milliseconds borrowObject will block or negative for indefinitely.
 658  
      * @see #getMaxWait
 659  
      * @see #setWhenExhaustedAction
 660  
      * @see #WHEN_EXHAUSTED_BLOCK
 661  
      */
 662  
     public synchronized void setMaxWait(long maxWait) {
 663  0
         _maxWait = maxWait;
 664  0
     }
 665  
 
 666  
     /**
 667  
      * Returns the cap on the number of "idle" instances per key.
 668  
      * @return the maximum number of "idle" instances that can be held
 669  
      * in a given keyed pool.
 670  
      * @see #setMaxIdle
 671  
      */
 672  
     public synchronized int getMaxIdle() {
 673  0
         return _maxIdle;
 674  
     }
 675  
 
 676  
     /**
 677  
      * Sets the cap on the number of "idle" instances in the pool.
 678  
      * @param maxIdle the maximum number of "idle" instances that can be held
 679  
      * in a given keyed pool. Use a negative value for no limit.
 680  
      * @see #getMaxIdle
 681  
      * @see #DEFAULT_MAX_IDLE
 682  
      */
 683  
     public synchronized void setMaxIdle(int maxIdle) {
 684  0
         _maxIdle = maxIdle;
 685  0
         notifyAll();
 686  0
     }
 687  
 
 688  
     /**
 689  
      * Sets the minimum number of idle objects to maintain in each of the keyed
 690  
      * pools. This setting has no effect unless 
 691  
      * <code>timeBetweenEvictionRunsMillis > 0</code> and attempts to ensure
 692  
      * that each pool has the required minimum number of instances are only
 693  
      * made during idle object eviction runs.
 694  
      * @param poolSize - The minimum size of the each keyed pool
 695  
      * @since Pool 1.3
 696  
      * @see #getMinIdle
 697  
      * @see #setTimeBetweenEvictionRunsMillis
 698  
      */
 699  
     public synchronized void setMinIdle(int poolSize) {
 700  0
         _minIdle = poolSize;
 701  0
     }
 702  
 
 703  
     /**
 704  
      * Returns the minimum number of idle objects to maintain in each of the keyed
 705  
      * pools. This setting has no effect unless 
 706  
      * <code>timeBetweenEvictionRunsMillis > 0</code> and attempts to ensure
 707  
      * that each pool has the required minimum number of instances are only
 708  
      * made during idle object eviction runs.
 709  
      * @return minimum size of the each keyed pool
 710  
      * @since Pool 1.3
 711  
      * @see #setTimeBetweenEvictionRunsMillis
 712  
      */
 713  
     public synchronized int getMinIdle() {
 714  0
         return _minIdle;
 715  
     }
 716  
 
 717  
     /**
 718  
      * When <code>true</code>, objects will be
 719  
      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
 720  
      * before being returned by the {@link #borrowObject}
 721  
      * method.  If the object fails to validate,
 722  
      * it will be dropped from the pool, and we will attempt
 723  
      * to borrow another.
 724  
      *
 725  
      * @return <code>true</code> if objects are validated before being borrowed.
 726  
      * @see #setTestOnBorrow
 727  
      */
 728  
     public boolean getTestOnBorrow() {
 729  0
         return _testOnBorrow;
 730  
     }
 731  
 
 732  
     /**
 733  
      * When <code>true</code>, objects will be
 734  
      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
 735  
      * before being returned by the {@link #borrowObject}
 736  
      * method.  If the object fails to validate,
 737  
      * it will be dropped from the pool, and we will attempt
 738  
      * to borrow another.
 739  
      *
 740  
      * @param testOnBorrow whether object should be validated before being returned by borrowObject.
 741  
      * @see #getTestOnBorrow
 742  
      */
 743  
     public void setTestOnBorrow(boolean testOnBorrow) {
 744  0
         _testOnBorrow = testOnBorrow;
 745  0
     }
 746  
 
 747  
     /**
 748  
      * When <code>true</code>, objects will be
 749  
      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
 750  
      * before being returned to the pool within the
 751  
      * {@link #returnObject}.
 752  
      *
 753  
      * @return <code>true</code> when objects will be validated before being returned.
 754  
      * @see #setTestOnReturn
 755  
      */
 756  
     public boolean getTestOnReturn() {
 757  0
         return _testOnReturn;
 758  
     }
 759  
 
 760  
     /**
 761  
      * When <code>true</code>, objects will be
 762  
      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
 763  
      * before being returned to the pool within the
 764  
      * {@link #returnObject}.
 765  
      *
 766  
      * @param testOnReturn <code>true</code> so objects will be validated before being returned.
 767  
      * @see #getTestOnReturn
 768  
      */
 769  
     public void setTestOnReturn(boolean testOnReturn) {
 770  0
         _testOnReturn = testOnReturn;
 771  0
     }
 772  
 
 773  
     /**
 774  
      * Returns the number of milliseconds to sleep between runs of the
 775  
      * idle object evictor thread.
 776  
      * When non-positive, no idle object evictor thread will be
 777  
      * run.
 778  
      *
 779  
      * @return milliseconds to sleep between evictor runs.
 780  
      * @see #setTimeBetweenEvictionRunsMillis
 781  
      */
 782  
     public synchronized long getTimeBetweenEvictionRunsMillis() {
 783  0
         return _timeBetweenEvictionRunsMillis;
 784  
     }
 785  
 
 786  
     /**
 787  
      * Sets the number of milliseconds to sleep between runs of the
 788  
      * idle object evictor thread.
 789  
      * When non-positive, no idle object evictor thread will be
 790  
      * run.
 791  
      *
 792  
      * @param timeBetweenEvictionRunsMillis milliseconds to sleep between evictor runs.
 793  
      * @see #getTimeBetweenEvictionRunsMillis
 794  
      */
 795  
     public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
 796  0
         _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
 797  0
         startEvictor(_timeBetweenEvictionRunsMillis);
 798  0
     }
 799  
 
 800  
     /**
 801  
      * Returns the number of objects to examine during each run of the
 802  
      * idle object evictor thread (if any).
 803  
      *
 804  
      * @return number of objects to examine each eviction run.
 805  
      * @see #setNumTestsPerEvictionRun
 806  
      * @see #setTimeBetweenEvictionRunsMillis
 807  
      */
 808  
     public synchronized int getNumTestsPerEvictionRun() {
 809  0
         return _numTestsPerEvictionRun;
 810  
     }
 811  
 
 812  
     /**
 813  
      * Sets the number of objects to examine during each run of the
 814  
      * idle object evictor thread (if any).
 815  
      * <p>
 816  
      * When a negative value is supplied, <code>ceil({@link #getNumIdle()})/abs({@link #getNumTestsPerEvictionRun})</code>
 817  
      * tests will be run.  I.e., when the value is <code>-n</code>, roughly one <code>n</code>th of the
 818  
      * idle objects will be tested per run.
 819  
      *
 820  
      * @param numTestsPerEvictionRun number of objects to examine each eviction run.
 821  
      * @see #getNumTestsPerEvictionRun
 822  
      * @see #setTimeBetweenEvictionRunsMillis
 823  
      */
 824  
     public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
 825  0
         _numTestsPerEvictionRun = numTestsPerEvictionRun;
 826  0
     }
 827  
 
 828  
     /**
 829  
      * Returns the minimum amount of time an object may sit idle in the pool
 830  
      * before it is eligible for eviction by the idle object evictor
 831  
      * (if any).
 832  
      *
 833  
      * @return minimum amount of time an object may sit idle in the pool before it is eligible for eviction.
 834  
      * @see #setMinEvictableIdleTimeMillis
 835  
      * @see #setTimeBetweenEvictionRunsMillis
 836  
      */
 837  
     public synchronized long getMinEvictableIdleTimeMillis() {
 838  0
         return _minEvictableIdleTimeMillis;
 839  
     }
 840  
 
 841  
     /**
 842  
      * Sets the minimum amount of time an object may sit idle in the pool
 843  
      * before it is eligible for eviction by the idle object evictor
 844  
      * (if any).
 845  
      * When non-positive, no objects will be evicted from the pool
 846  
      * due to idle time alone.
 847  
      *
 848  
      * @param minEvictableIdleTimeMillis minimum amount of time an object may sit idle in the pool before it is eligible for eviction.
 849  
      * @see #getMinEvictableIdleTimeMillis
 850  
      * @see #setTimeBetweenEvictionRunsMillis
 851  
      */
 852  
     public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
 853  0
         _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
 854  0
     }
 855  
 
 856  
     /**
 857  
      * When <code>true</code>, objects will be
 858  
      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
 859  
      * by the idle object evictor (if any).  If an object
 860  
      * fails to validate, it will be dropped from the pool.
 861  
      *
 862  
      * @return <code>true</code> when objects are validated when borrowed.
 863  
      * @see #setTestWhileIdle
 864  
      * @see #setTimeBetweenEvictionRunsMillis
 865  
      */
 866  
     public synchronized boolean getTestWhileIdle() {
 867  0
         return _testWhileIdle;
 868  
     }
 869  
 
 870  
     /**
 871  
      * When <code>true</code>, objects will be
 872  
      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
 873  
      * by the idle object evictor (if any).  If an object
 874  
      * fails to validate, it will be dropped from the pool.
 875  
      *
 876  
      * @param testWhileIdle <code>true</code> so objects are validated when borrowed.
 877  
      * @see #getTestWhileIdle
 878  
      * @see #setTimeBetweenEvictionRunsMillis
 879  
      */
 880  
     public synchronized void setTestWhileIdle(boolean testWhileIdle) {
 881  0
         _testWhileIdle = testWhileIdle;
 882  0
     }
 883  
 
 884  
     /**
 885  
      * Sets the configuration.
 886  
      * @param conf the new configuration to use.
 887  
      * @see GenericKeyedObjectPool.Config
 888  
      */
 889  
     public synchronized void setConfig(GenericKeyedObjectPool.Config conf) {
 890  0
         setMaxIdle(conf.maxIdle);
 891  0
         setMaxActive(conf.maxActive);
 892  0
         setMaxTotal(conf.maxTotal);
 893  0
         setMinIdle(conf.minIdle);
 894  0
         setMaxWait(conf.maxWait);
 895  0
         setWhenExhaustedAction(conf.whenExhaustedAction);
 896  0
         setTestOnBorrow(conf.testOnBorrow);
 897  0
         setTestOnReturn(conf.testOnReturn);
 898  0
         setTestWhileIdle(conf.testWhileIdle);
 899  0
         setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);
 900  0
         setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);
 901  0
         setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);
 902  0
     }
 903  
     
 904  
     /**
 905  
      * Whether or not the idle object pools act as LIFO queues. True means
 906  
      * that borrowObject returns the most recently used ("last in") idle object
 907  
      * in a pool (if there are idle instances available).  False means that
 908  
      * the pools behave as FIFO queues - objects are taken from idle object
 909  
      * pools in the order that they are returned.
 910  
      * 
 911  
      * @return <code>true</code> if the pools are configured to act as LIFO queues
 912  
      * @since 1.4
 913  
      */
 914  
      public synchronized boolean getLifo() {
 915  0
          return _lifo;
 916  
      }
 917  
 
 918  
      /**
 919  
       * Sets the LIFO property of the pools. True means that borrowObject returns
 920  
       * the most recently used ("last in") idle object in a pool (if there are
 921  
       * idle instances available).  False means that the pools behave as FIFO
 922  
       * queues - objects are taken from idle object pools in the order that
 923  
       * they are returned.
 924  
       * 
 925  
       * @param lifo the new value for the lifo property
 926  
       * @since 1.4
 927  
       */
 928  
      public synchronized void setLifo(boolean lifo) {
 929  0
          this._lifo = lifo;
 930  0
      }
 931  
 
 932  
     //-- ObjectPool methods ------------------------------------------
 933  
 
 934  
     public Object borrowObject(Object key) throws Exception {
 935  0
         long starttime = System.currentTimeMillis();
 936  0
         boolean newlyCreated = false;
 937  
         for(;;) {
 938  0
             ObjectTimestampPair pair = null;
 939  0
             ObjectQueue pool = null;
 940  0
             synchronized (_poolMap) {
 941  0
                 assertOpen();
 942  0
                 pool = (ObjectQueue)(_poolMap.get(key));
 943  0
                 if(null == pool) {
 944  0
                     pool = new ObjectQueue();
 945  0
                     _poolMap.put(key,pool);
 946  0
                     _poolList.add(key);
 947  
                 }
 948  0
             }
 949  
                 // if there are any sleeping, just grab one of those
 950  
                 try {
 951  0
                         synchronized (pool) {
 952  0
                                 pair = (ObjectTimestampPair)(pool.queue.removeFirst());
 953  0
                         }
 954  0
                     if(null != pair) {
 955  0
                         _totalIdle--;
 956  
                     }
 957  0
                 } catch(NoSuchElementException e) { /* ignored */
 958  0
                 }
 959  
                 // otherwise
 960  0
                 if(null == pair) {
 961  
                     // if there is a totalMaxActive and we are at the limit then
 962  
                     // we have to make room
 963  0
                     if ((_maxTotal > 0) && (_totalActive + _totalIdle >= _maxTotal)) {
 964  0
                         clearOldest();
 965  
                     }
 966  
     
 967  
                     // check if we can create one
 968  
                     // (note we know that the num sleeping is 0, else we wouldn't be here)
 969  0
                     if ((_maxActive < 0 || pool.activeCount < _maxActive) &&
 970  
                         (_maxTotal < 0 || _totalActive + _totalIdle < _maxTotal)) {
 971  0
                         Object obj = _factory.makeObject(key);
 972  0
                         pair = new ObjectTimestampPair(obj);
 973  0
                         newlyCreated = true;
 974  0
                     } else {
 975  
                         // the pool is exhausted
 976  0
                         switch(_whenExhaustedAction) {
 977  
                             case WHEN_EXHAUSTED_GROW:
 978  0
                                 Object obj = _factory.makeObject(key);
 979  0
                                 pair = new ObjectTimestampPair(obj);
 980  0
                                 break;
 981  
                             case WHEN_EXHAUSTED_FAIL:
 982  0
                                 throw new NoSuchElementException();
 983  
                             case WHEN_EXHAUSTED_BLOCK:
 984  
                                 try {
 985  0
                                     if(_maxWait <= 0) {
 986  0
                                         wait();
 987  
                                     } else {
 988  
                                         // this code may be executed again after a notify then continue cycle
 989  
                                         // so, need to calculate the amount of time to wait
 990  0
                                         final long elapsed = (System.currentTimeMillis() - starttime);
 991  0
                                         final long waitTime = _maxWait - elapsed;
 992  0
                                         if (waitTime > 0)
 993  
                                         {
 994  0
                                             wait(waitTime);
 995  
                                         }
 996  
                                     }
 997  0
                                 } catch(InterruptedException e) {
 998  
                                     // ignored
 999  0
                                 }
 1000  0
                                 if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
 1001  0
                                     throw new NoSuchElementException("Timeout waiting for idle object");
 1002  
                                 } else {
 1003  
                                     continue; // keep looping
 1004  
                                 }
 1005  
                             default:
 1006  0
                                 throw new IllegalArgumentException("whenExhaustedAction " + _whenExhaustedAction + " not recognized.");
 1007  
                         }
 1008  
                     }
 1009  
                 
 1010  0
                 pool.incrementActiveCount();
 1011  
             }
 1012  
             
 1013  
             // Activate.  If activate fails, decrement active count and destroy.
 1014  
             // If instance failing activation is new, throw NoSuchElementException;
 1015  
             // otherwise keep looping
 1016  
             try {
 1017  0
                 _factory.activateObject(key, pair.value);
 1018  0
             } catch (Exception e) {
 1019  
                 try {
 1020  0
                     _factory.destroyObject(key,pair.value);
 1021  0
                     synchronized (this) {
 1022  0
                         pool.decrementActiveCount();
 1023  0
                     }
 1024  0
                 } catch (Exception e2) {
 1025  
                     // swallowed
 1026  0
                 }
 1027  0
                 if(newlyCreated) {
 1028  0
                     throw new NoSuchElementException(
 1029  
                        "Could not create a validated object, cause: "
 1030  
                             + e.getMessage());
 1031  
                 }
 1032  
                 else {
 1033  0
                     continue; // keep looping
 1034  
                 }
 1035  0
             }
 1036  
 
 1037  
             // Validate.  If validation fails, decrement active count and
 1038  
             // destroy. If instance failing validation is new, throw
 1039  
             // NoSuchElementException; otherwise keep looping
 1040  0
             boolean invalid = true;
 1041  
             try {
 1042  0
                 invalid = _testOnBorrow && !_factory.validateObject(key, pair.value);
 1043  0
             } catch (Exception e) {
 1044  
                 // swallowed
 1045  0
             }
 1046  0
             if (invalid) {
 1047  
                 try {
 1048  0
                     _factory.destroyObject(key,pair.value);
 1049  0
                     synchronized (pool) {
 1050  0
                         pool.decrementActiveCount();
 1051  0
                     }
 1052  0
                 } catch (Exception e) {
 1053  
                     // swallowed
 1054  0
                 }
 1055  0
                 if(newlyCreated) {
 1056  0
                     throw new NoSuchElementException("Could not create a validated object");
 1057  
                 } // else keep looping
 1058  
             } else {
 1059  0
                 return pair.value;
 1060  
             }
 1061  0
         }
 1062  
     }
 1063  
 
 1064  
     /**
 1065  
      * Clears the pool, removing all pooled instances.
 1066  
      */
 1067  
     public synchronized void clear() {
 1068  0
         for(Iterator entries = _poolMap.entrySet().iterator(); entries.hasNext(); ) {
 1069  0
             final Map.Entry entry = (Map.Entry)entries.next();
 1070  0
             final Object key = entry.getKey();
 1071  0
             final CursorableLinkedList list = ((ObjectQueue)(entry.getValue())).queue;
 1072  0
             for(Iterator it = list.iterator(); it.hasNext(); ) {
 1073  
                 try {
 1074  0
                     _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
 1075  0
                 } catch(Exception e) {
 1076  
                     // ignore error, keep destroying the rest
 1077  0
                 }
 1078  0
                 it.remove();
 1079  
             }
 1080  0
         }
 1081  0
         _poolMap.clear();
 1082  0
         _poolList.clear();
 1083  0
         _totalIdle = 0;
 1084  0
         notifyAll();
 1085  0
     }
 1086  
 
 1087  
     /**
 1088  
      * Method clears oldest 15% of objects in pool.  The method sorts the
 1089  
      * objects into a TreeMap and then iterates the first 15% for removal
 1090  
      * @since Pool 1.3
 1091  
      */
 1092  
     public synchronized void clearOldest() {
 1093  
         // build sorted map of idle objects
 1094  0
         final Map map = new TreeMap();
 1095  0
         for (Iterator keyiter = _poolMap.keySet().iterator(); keyiter.hasNext();) {
 1096  0
             final Object key = keyiter.next();
 1097  0
             final CursorableLinkedList list = ((ObjectQueue)_poolMap.get(key)).queue;
 1098  0
             for (Iterator it = list.iterator(); it.hasNext();) {
 1099  
                 // each item into the map uses the objectimestamppair object
 1100  
                 // as the key.  It then gets sorted based on the timstamp field
 1101  
                 // each value in the map is the parent list it belongs in.
 1102  0
                 map.put(it.next(), key);
 1103  
             }
 1104  0
         }
 1105  
 
 1106  
         // Now iterate created map and kill the first 15% plus one to account for zero
 1107  0
         Set setPairKeys = map.entrySet();
 1108  0
         int itemsToRemove = ((int) (map.size() * 0.15)) + 1;
 1109  
 
 1110  0
         Iterator iter = setPairKeys.iterator();
 1111  0
         while (iter.hasNext() && itemsToRemove > 0) {
 1112  0
             Map.Entry entry = (Map.Entry) iter.next();
 1113  
             // kind of backwards on naming.  In the map, each key is the objecttimestamppair
 1114  
             // because it has the ordering with the timestamp value.  Each value that the
 1115  
             // key references is the key of the list it belongs to.
 1116  0
             Object key = entry.getValue();
 1117  0
             ObjectTimestampPair pairTimeStamp = (ObjectTimestampPair) entry.getKey();
 1118  0
             final CursorableLinkedList list = 
 1119  
                 ((ObjectQueue)(_poolMap.get(key))).queue;
 1120  0
             list.remove(pairTimeStamp);
 1121  
 
 1122  
             try {
 1123  0
                 _factory.destroyObject(key, pairTimeStamp.value);
 1124  0
             } catch (Exception e) {
 1125  
                 // ignore error, keep destroying the rest
 1126  0
             }
 1127  
             // if that was the last object for that key, drop that pool
 1128  0
             if (list.isEmpty()) {
 1129  0
                 _poolMap.remove(key);
 1130  0
                 _poolList.remove(key);
 1131  
             }
 1132  0
             _totalIdle--;
 1133  0
             itemsToRemove--;
 1134  0
         }
 1135  0
         notifyAll();
 1136  0
     }
 1137  
 
 1138  
     /**
 1139  
      * Clears the specified pool, removing all pooled instances corresponding to the given <code>key</code>.
 1140  
      *
 1141  
      * @param key the key to clear
 1142  
      */
 1143  
     public synchronized void clear(Object key) {
 1144  0
         final ObjectQueue pool = (ObjectQueue)(_poolMap.remove(key));
 1145  0
         if(null == pool) {
 1146  0
             return;
 1147  
         } else {
 1148  0
             _poolList.remove(key);
 1149  0
             for(Iterator it = pool.queue.iterator(); it.hasNext(); ) {
 1150  
                 try {
 1151  0
                     _factory.destroyObject(key,((ObjectTimestampPair)(it.next())).value);
 1152  0
                 } catch(Exception e) {
 1153  
                     // ignore error, keep destroying the rest
 1154  0
                 }
 1155  0
                 it.remove();
 1156  0
                 _totalIdle--;
 1157  
             }
 1158  
         }
 1159  
         
 1160  0
         notifyAll();
 1161  0
     }
 1162  
 
 1163  
     /**
 1164  
      * Returns the total number of instances current borrowed from this pool but not yet returned.
 1165  
      *
 1166  
      * @return the total number of instances currently borrowed from this pool
 1167  
      */
 1168  
     public synchronized int getNumActive() {
 1169  0
         return _totalActive;
 1170  
     }
 1171  
 
 1172  
     /**
 1173  
      * Returns the total number of instances currently idle in this pool.
 1174  
      *
 1175  
      * @return the total number of instances currently idle in this pool
 1176  
      */
 1177  
     public synchronized int getNumIdle() {
 1178  0
         return _totalIdle;
 1179  
     }
 1180  
 
 1181  
     /**
 1182  
      * Returns the number of instances currently borrowed from but not yet returned
 1183  
      * to the pool corresponding to the given <code>key</code>.
 1184  
      *
 1185  
      * @param key the key to query
 1186  
      * @return the number of instances corresponding to the given <code>key</code> currently borrowed in this pool
 1187  
      */
 1188  
     public synchronized int getNumActive(Object key) {
 1189  0
         final ObjectQueue pool = (ObjectQueue)(_poolMap.get(key));
 1190  0
         return pool != null ? pool.activeCount : 0;
 1191  
     }
 1192  
 
 1193  
     /**
 1194  
      * Returns the number of instances corresponding to the given <code>key</code> currently idle in this pool.
 1195  
      *
 1196  
      * @param key the key to query
 1197  
      * @return the number of instances corresponding to the given <code>key</code> currently idle in this pool
 1198  
      */
 1199  
     public synchronized int getNumIdle(Object key) {
 1200  0
         final ObjectQueue pool = (ObjectQueue)(_poolMap.get(key));
 1201  0
         return pool != null ? pool.queue.size() : 0;
 1202  
     }
 1203  
 
 1204  
     public void returnObject(Object key, Object obj) throws Exception {
 1205  
         try {
 1206  0
             addObjectToPool(key, obj, true);
 1207  0
         } catch (Exception e) {
 1208  0
             if (_factory != null) {
 1209  
                 try {
 1210  0
                     _factory.destroyObject(key, obj);
 1211  0
                 } catch (Exception e2) {
 1212  
                     // swallowed
 1213  0
                 }
 1214  
                 // TODO: Correctness here depends on control in addObjectToPool.
 1215  
                 // These two methods should be refactored, removing the 
 1216  
                 // "behavior flag",decrementNumActive, from addObjectToPool.
 1217  0
                 ObjectQueue pool = (ObjectQueue) (_poolMap.get(key));
 1218  0
                 if (pool != null) {
 1219  0
                     synchronized(pool) {
 1220  0
                         pool.decrementActiveCount();
 1221  0
                         notifyAll();
 1222  0
                     }  
 1223  
                 }
 1224  
             }
 1225  0
         }
 1226  0
     }
 1227  
 
 1228  
     private void addObjectToPool(Object key, Object obj,
 1229  
             boolean decrementNumActive) throws Exception {
 1230  
 
 1231  
         // if we need to validate this object, do so
 1232  0
         boolean success = true; // whether or not this object passed validation
 1233  0
         if(_testOnReturn && !_factory.validateObject(key, obj)) {
 1234  0
             success = false;
 1235  
         } else {
 1236  0
             _factory.passivateObject(key, obj);
 1237  
         }
 1238  
 
 1239  0
         boolean shouldDestroy = !success;
 1240  
         ObjectQueue pool;
 1241  
         
 1242  
         // Add instance to pool if there is room and it has passed validation
 1243  
         // (if testOnreturn is set)
 1244  0
         synchronized (this) {
 1245  
             // grab the pool (list) of objects associated with the given key
 1246  0
             pool = (ObjectQueue) (_poolMap.get(key));
 1247  
             // if it doesn't exist, create it
 1248  0
             if(null == pool) {
 1249  0
                 pool = new ObjectQueue();
 1250  0
                 _poolMap.put(key, pool);
 1251  0
                 _poolList.add(key);
 1252  
             }
 1253  0
         }
 1254  0
         synchronized (pool) {
 1255  0
             if (isClosed()) {
 1256  0
                 shouldDestroy = true;
 1257  
             } else {
 1258  
                 // if there's no space in the pool, flag the object for destruction
 1259  
                 // else if we passivated successfully, return it to the pool
 1260  0
                 if(_maxIdle >= 0 && (pool.queue.size() >= _maxIdle)) {
 1261  0
                     shouldDestroy = true;
 1262  0
                 } else if(success) {
 1263  
                     // borrowObject always takes the first element from the queue,
 1264  
                     // so for LIFO, push on top, FIFO add to end
 1265  0
                     if (_lifo) {
 1266  0
                         pool.queue.addFirst(new ObjectTimestampPair(obj)); 
 1267  
                     } else {
 1268  0
                         pool.queue.addLast(new ObjectTimestampPair(obj));
 1269  
                     }
 1270  0
                     _totalIdle++;
 1271  
                 }
 1272  
             }
 1273  0
         }
 1274  
 
 1275  
         // Destroy the instance if necessary 
 1276  0
         if(shouldDestroy) {
 1277  
             try {
 1278  0
                 _factory.destroyObject(key, obj);
 1279  0
             } catch(Exception e) {
 1280  
                 // ignored?
 1281  0
             }
 1282  
         }
 1283  
         
 1284  
         // Decrement active count *after* destroy if applicable
 1285  0
         if (decrementNumActive) {
 1286  0
             synchronized(this) {
 1287  0
                 pool.decrementActiveCount();
 1288  0
                 notifyAll();
 1289  0
             }
 1290  
         }
 1291  0
     }
 1292  
 
 1293  
     public void invalidateObject(Object key, Object obj) throws Exception {
 1294  
         try {
 1295  0
             _factory.destroyObject(key, obj);
 1296  
         } finally {
 1297  0
             synchronized (this) {
 1298  0
                 ObjectQueue pool = (ObjectQueue) (_poolMap.get(key));
 1299  0
                 if(null == pool) {
 1300  0
                     pool = new ObjectQueue();
 1301  0
                     _poolMap.put(key, pool);
 1302  0
                     _poolList.add(key);
 1303  
                 }
 1304  0
                 pool.decrementActiveCount();
 1305  0
                 notifyAll(); // _totalActive has changed
 1306  0
             }
 1307  0
         }
 1308  0
     }
 1309  
 
 1310  
     /**
 1311  
      * Create an object using the {@link KeyedPoolableObjectFactory#makeObject factory},
 1312  
      * passivate it, and then place it in the idle object pool.
 1313  
      * <code>addObject</code> is useful for "pre-loading" a pool with idle objects.
 1314  
      *
 1315  
      * @param key the key a new instance should be added to
 1316  
      * @throws Exception when {@link KeyedPoolableObjectFactory#makeObject} fails.
 1317  
      * @throws IllegalStateException when no {@link #setFactory factory} has been set or after {@link #close} has been called on this pool.
 1318  
      */
 1319  
     public void addObject(Object key) throws Exception {
 1320  0
         assertOpen();
 1321  0
         if (_factory == null) {
 1322  0
             throw new IllegalStateException("Cannot add objects without a factory.");
 1323  
         }
 1324  0
         Object obj = _factory.makeObject(key);
 1325  0
         synchronized (this) {
 1326  
             try {
 1327  0
                 assertOpen();
 1328  0
                 addObjectToPool(key, obj, false);
 1329  0
             } catch (IllegalStateException ex) { // Pool closed
 1330  
                 try {
 1331  0
                     _factory.destroyObject(key, obj);
 1332  0
                 } catch (Exception ex2) {
 1333  
                     // swallow
 1334  0
                 }
 1335  0
                 throw ex;
 1336  0
             }
 1337  0
         }
 1338  0
     }
 1339  
 
 1340  
     /**
 1341  
      * Registers a key for pool control.
 1342  
      *
 1343  
      * If <code>populateImmediately</code> is <code>true</code> and
 1344  
      * <code>minIdle > 0,</code> the pool under the given key will be
 1345  
      * populated immediately with <code>minIdle</code> idle instances.
 1346  
      *
 1347  
      * @param key - The key to register for pool control.
 1348  
      * @param populateImmediately - If this is <code>true</code>, the pool
 1349  
      * will be populated immediately.
 1350  
      * @since Pool 1.3
 1351  
      */
 1352  
     public synchronized void preparePool(Object key, boolean populateImmediately) {
 1353  0
         ObjectQueue pool = (ObjectQueue)(_poolMap.get(key));
 1354  0
         if (null == pool) {
 1355  0
             pool = new ObjectQueue();
 1356  0
             _poolMap.put(key,pool);
 1357  0
             _poolList.add(key);
 1358  
         }
 1359  
 
 1360  0
         if (populateImmediately) {
 1361  
             try {
 1362  
                 // Create the pooled objects
 1363  0
                 ensureMinIdle(key);
 1364  
             }
 1365  0
             catch (Exception e) {
 1366  
                 //Do nothing
 1367  0
             }
 1368  
         }
 1369  0
     }
 1370  
 
 1371  
     public void close() throws Exception {
 1372  0
         super.close();
 1373  0
         synchronized (this) {
 1374  0
             clear();
 1375  0
             if(null != _evictionCursor) {
 1376  0
                 _evictionCursor.close();
 1377  0
                 _evictionCursor = null;
 1378  
             }
 1379  0
             if(null != _evictionKeyCursor) {
 1380  0
                 _evictionKeyCursor.close();
 1381  0
                 _evictionKeyCursor = null;
 1382  
             }
 1383  0
             startEvictor(-1L);
 1384  0
         }
 1385  0
     }
 1386  
 
 1387  
     public synchronized void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException {
 1388  0
         assertOpen();
 1389  0
         if(0 < getNumActive()) {
 1390  0
             throw new IllegalStateException("Objects are already active");
 1391  
         } else {
 1392  0
             clear();
 1393  0
             _factory = factory;
 1394  
         }
 1395  0
     }
 1396  
 
 1397  
     /**
 1398  
      * <p>Perform <code>numTests</code> idle object eviction tests, evicting
 1399  
      * examined objects that meet the criteria for eviction. If 
 1400  
      * <code>testWhileIdle</code> is true, examined objects are validated
 1401  
      * when visited (and removed if invalid); otherwise only objects that
 1402  
      * have been idle for more than <code>minEvicableIdletimeMillis</code>
 1403  
      * are removed.</p>
 1404  
      * 
 1405  
      * <p>Successive activations of this method examine objects in keyed pools
 1406  
      * in sequence, cycling through the keys and examining objects in
 1407  
      * oldest-to-youngest order within the keyed pools.</p>
 1408  
      *
 1409  
      * @throws Exception when there is a problem evicting idle objects.
 1410  
      */
 1411  
     public synchronized void evict() throws Exception {
 1412  
         // Initialize key to last key value
 1413  0
         Object key = null;
 1414  0
         if (_evictionKeyCursor != null && 
 1415  
                 _evictionKeyCursor._lastReturned != null) {
 1416  0
             key = _evictionKeyCursor._lastReturned.value();
 1417  
         }
 1418  
         
 1419  0
         for (int i=0,m=getNumTests(); i<m; i++) {
 1420  
             // make sure pool map is not empty; otherwise do nothing
 1421  0
             if (_poolMap == null || _poolMap.size() == 0) {
 1422  0
                 continue;
 1423  
             }
 1424  
 
 1425  
             // if we don't have a key cursor, then create one
 1426  0
             if (null == _evictionKeyCursor) {
 1427  0
                 resetEvictionKeyCursor();
 1428  0
                 key = null;
 1429  
             }
 1430  
 
 1431  
             // if we don't have an object cursor, create one
 1432  0
             if (null == _evictionCursor) {
 1433  
                 // if the _evictionKeyCursor has a next value, use this key
 1434  0
                 if (_evictionKeyCursor.hasNext()) {
 1435  0
                     key = _evictionKeyCursor.next();
 1436  0
                     resetEvictionObjectCursor(key);
 1437  
                 } else {
 1438  
                     // Reset the key cursor and try again
 1439  0
                     resetEvictionKeyCursor();
 1440  0
                     if (_evictionKeyCursor != null) {
 1441  0
                         if (_evictionKeyCursor.hasNext()) {
 1442  0
                             key = _evictionKeyCursor.next();
 1443  0
                             resetEvictionObjectCursor(key);
 1444  
                         }
 1445  
                     }
 1446  
                 }
 1447  
             }  
 1448  
 
 1449  0
             if (_evictionCursor == null) {
 1450  0
                 continue; // should never happen; do nothing
 1451  
             }
 1452  
 
 1453  
             // If eviction cursor is exhausted, try to move
 1454  
             // to the next key and reset
 1455  0
             if((_lifo && !_evictionCursor.hasPrevious()) ||
 1456  
                     (!_lifo && !_evictionCursor.hasNext())) {
 1457  0
                 if (_evictionKeyCursor != null) {
 1458  0
                     if (_evictionKeyCursor.hasNext()) {
 1459  0
                         key = _evictionKeyCursor.next();
 1460  0
                         resetEvictionObjectCursor(key);
 1461  
                     } else { // Need to reset Key cursor
 1462  0
                         resetEvictionKeyCursor();
 1463  0
                         if (_evictionKeyCursor != null) {
 1464  0
                             if (_evictionKeyCursor.hasNext()) {
 1465  0
                                 key = _evictionKeyCursor.next();
 1466  0
                                 resetEvictionObjectCursor(key);
 1467  
                             }
 1468  
                         }
 1469  
                     }
 1470  
                 }
 1471  
             }
 1472  
 
 1473  0
             if((_lifo && !_evictionCursor.hasPrevious()) ||
 1474  
                     (!_lifo && !_evictionCursor.hasNext())) {
 1475  0
                 continue; // reset failed, do nothing
 1476  
             }
 1477  
 
 1478  
             // if LIFO and the _evictionCursor has a previous object, 
 1479  
             // or FIFO and _evictionCursor has a next object, test it
 1480  0
             ObjectTimestampPair pair = _lifo ? 
 1481  
                     (ObjectTimestampPair) _evictionCursor.previous() : 
 1482  
                     (ObjectTimestampPair) _evictionCursor.next();
 1483  0
             boolean removeObject=false;
 1484  0
             if((_minEvictableIdleTimeMillis > 0) &&
 1485  
                (System.currentTimeMillis() - pair.tstamp > 
 1486  
                _minEvictableIdleTimeMillis)) {
 1487  0
                 removeObject=true;
 1488  
             }
 1489  0
             if(_testWhileIdle && removeObject == false) {
 1490  0
                 boolean active = false;
 1491  
                 try {
 1492  0
                     _factory.activateObject(key,pair.value);
 1493  0
                     active = true;
 1494  0
                 } catch(Exception e) {
 1495  0
                     removeObject=true;
 1496  0
                 }
 1497  0
                 if(active) {
 1498  0
                     if(!_factory.validateObject(key,pair.value)) {
 1499  0
                         removeObject=true;
 1500  
                     } else {
 1501  
                         try {
 1502  0
                             _factory.passivateObject(key,pair.value);
 1503  0
                         } catch(Exception e) {
 1504  0
                             removeObject=true;
 1505  0
                         }
 1506  
                     }
 1507  
                 }
 1508  
             }
 1509  0
             if(removeObject) {
 1510  
                 try {
 1511  0
                     _evictionCursor.remove();
 1512  0
                     _totalIdle--;
 1513  0
                     _factory.destroyObject(key, pair.value);
 1514  
                     // Do not remove the key from the _poolList or _poolmap,
 1515  
                     // even if the list stored in the _poolMap for this key is
 1516  
                     // empty when minIdle > 0.
 1517  
                     //
 1518  
                     // Otherwise if it was the last object for that key,
 1519  
                     // drop that pool
 1520  0
                     if (_minIdle == 0) {
 1521  0
                         ObjectQueue objectQueue = 
 1522  
                             (ObjectQueue)_poolMap.get(key);
 1523  0
                         if (objectQueue != null && 
 1524  
                                 objectQueue.queue.isEmpty()) {
 1525  0
                             _poolMap.remove(key);
 1526  0
                             _poolList.remove(key);  
 1527  
                         }
 1528  
                     }
 1529  0
                 } catch(Exception e) {
 1530  
                     ; // ignored
 1531  0
                 }
 1532  
             }
 1533  
         }
 1534  0
     }
 1535  
     
 1536  
     /**
 1537  
      * Resets the eviction key cursor and closes any
 1538  
      * associated eviction object cursor
 1539  
      */
 1540  
     private void resetEvictionKeyCursor() {
 1541  0
         if (_evictionKeyCursor != null) {
 1542  0
             _evictionKeyCursor.close();
 1543  
         }
 1544  0
         _evictionKeyCursor = _poolList.cursor();
 1545  0
         if (null != _evictionCursor) {
 1546  0
             _evictionCursor.close();
 1547  0
             _evictionCursor = null;
 1548  
         }  
 1549  0
     }
 1550  
     
 1551  
     /**
 1552  
      * Resets the eviction object cursor for the given key
 1553  
      * 
 1554  
      * @param key eviction key
 1555  
      */
 1556  
     private void resetEvictionObjectCursor(Object key) {
 1557  0
         if (_evictionCursor != null) {
 1558  0
             _evictionCursor.close();
 1559  
         }
 1560  0
         if (_poolMap == null) { 
 1561  0
             return;
 1562  
         }
 1563  0
         ObjectQueue pool = (ObjectQueue) (_poolMap.get(key));
 1564  0
         if (pool != null) {
 1565  0
             CursorableLinkedList queue = 
 1566  
                 (CursorableLinkedList)(pool.queue);
 1567  0
             _evictionCursor = queue.cursor(_lifo ? queue.size() : 0);   
 1568  
         }
 1569  0
     }
 1570  
 
 1571  
     /**
 1572  
      * Iterates through all the known keys and creates any necessary objects to maintain
 1573  
      * the minimum level of pooled objects.
 1574  
      * @see #getMinIdle
 1575  
      * @see #setMinIdle
 1576  
      * @throws Exception If there was an error whilst creating the pooled objects.
 1577  
      */
 1578  
     private synchronized void ensureMinIdle() throws Exception {
 1579  0
         Iterator iterator = _poolMap.keySet().iterator();
 1580  
 
 1581  
         //Check if should sustain the pool
 1582  0
         if (_minIdle > 0) {
 1583  
             // Loop through all elements in _poolList
 1584  
             // Find out the total number of max active and max idle for that class
 1585  
             // If the number is less than the minIdle, do creation loop to boost numbers
 1586  
             // Increment idle count + 1
 1587  0
             while (iterator.hasNext()) {
 1588  
                 //Get the next key to process
 1589  0
                 Object key = iterator.next();
 1590  0
                 ensureMinIdle(key);
 1591  0
             }
 1592  
         }
 1593  0
     }
 1594  
 
 1595  
     /**
 1596  
      * Re-creates any needed objects to maintain the minimum levels of
 1597  
      * pooled objects for the specified key.
 1598  
      *
 1599  
      * This method uses {@link #calculateDefecit} to calculate the number
 1600  
      * of objects to be created. {@link #calculateDefecit} can be overridden to
 1601  
      * provide a different method of calculating the number of objects to be
 1602  
      * created.
 1603  
      * @param key The key to process
 1604  
      * @throws Exception If there was an error whilst creating the pooled objects
 1605  
      */
 1606  
     private synchronized void ensureMinIdle(Object key) throws Exception {
 1607  
         // Calculate current pool objects
 1608  0
         int numberToCreate = calculateDefecit(key);
 1609  
 
 1610  
         //Create required pool objects, if none to create, this loop will not be run.
 1611  0
         for (int i = 0; i < numberToCreate; i++) {
 1612  0
             addObject(key);
 1613  
         }
 1614  0
     }
 1615  
 
 1616  
     //--- non-public methods ----------------------------------------
 1617  
 
 1618  
     /**
 1619  
      * Start the eviction thread or service, or when
 1620  
      * <code>delay</code> is non-positive, stop it
 1621  
      * if it is already running.
 1622  
      *
 1623  
      * @param delay milliseconds between evictor runs.
 1624  
      */
 1625  
     protected synchronized void startEvictor(long delay) {
 1626  0
         if(null != _evictor) {
 1627  0
             EvictionTimer.cancel(_evictor);
 1628  0
             _evictor = null;
 1629  
         }
 1630  0
         if(delay > 0) {
 1631  0
             _evictor = new Evictor();
 1632  0
             EvictionTimer.schedule(_evictor, delay, delay);
 1633  
         }
 1634  0
     }
 1635  
 
 1636  
     synchronized String debugInfo() {
 1637  0
         StringBuffer buf = new StringBuffer();
 1638  0
         buf.append("Active: ").append(getNumActive()).append("\n");
 1639  0
         buf.append("Idle: ").append(getNumIdle()).append("\n");
 1640  0
         Iterator it = _poolMap.keySet().iterator();
 1641  0
         while(it.hasNext()) {
 1642  0
             buf.append("\t").append(_poolMap.get(it.next())).append("\n");
 1643  
         }
 1644  0
         return buf.toString();
 1645  
     }
 1646  
 
 1647  
     private int getNumTests() {
 1648  0
         if(_numTestsPerEvictionRun >= 0) {
 1649  0
             return _numTestsPerEvictionRun;
 1650  
         } else {
 1651  0
             return(int)(Math.ceil((double)_totalIdle/Math.abs((double)_numTestsPerEvictionRun)));
 1652  
         }
 1653  
     }
 1654  
 
 1655  
     /**
 1656  
      * This returns the number of objects to create during the pool
 1657  
      * sustain cycle. This will ensure that the minimum number of idle
 1658  
      * connections is maintained without going past the maxPool value.
 1659  
      * <p>
 1660  
      * This method has been left public so derived classes can override
 1661  
      * the way the defecit is calculated. ie... Increase/decrease the pool
 1662  
      * size at certain times of day to accomodate for usage patterns.
 1663  
      *
 1664  
      * @param key - The key of the pool to calculate the number of
 1665  
      *              objects to be re-created
 1666  
      * @return The number of objects to be created
 1667  
      */
 1668  
     private int calculateDefecit(Object key) {
 1669  0
         int objectDefecit = 0;
 1670  
 
 1671  
         //Calculate no of objects needed to be created, in order to have
 1672  
         //the number of pooled objects < maxActive();
 1673  0
         objectDefecit = getMinIdle() - getNumIdle(key);
 1674  0
         if (getMaxActive() > 0) {
 1675  0
             int growLimit = Math.max(0, getMaxActive() - getNumActive(key) - getNumIdle(key));
 1676  0
             objectDefecit = Math.min(objectDefecit, growLimit);
 1677  
         }
 1678  
 
 1679  
         // Take the maxTotal limit into account
 1680  0
         if (getMaxTotal() > 0) {
 1681  0
             int growLimit = Math.max(0, getMaxTotal() - getNumActive() - getNumIdle());
 1682  0
             objectDefecit = Math.min(objectDefecit, growLimit);
 1683  
         }
 1684  
 
 1685  0
         return objectDefecit;
 1686  
     }
 1687  
 
 1688  
     //--- inner classes ----------------------------------------------
 1689  
 
 1690  
     /**
 1691  
      * A "struct" that keeps additional information about the actual queue of pooled objects.
 1692  
      */
 1693  0
     private class ObjectQueue {
 1694  0
         private int activeCount = 0;
 1695  0
         private final CursorableLinkedList queue = new CursorableLinkedList();
 1696  
 
 1697  
         void incrementActiveCount() {
 1698  0
             _totalActive++;
 1699  0
             activeCount++;
 1700  0
         }
 1701  
 
 1702  
         void decrementActiveCount() {
 1703  0
             _totalActive--;
 1704  0
             if (activeCount > 0) {
 1705  0
                 activeCount--;
 1706  
             }
 1707  0
         }
 1708  
     }
 1709  
     
 1710  
     /**
 1711  
      * A simple "struct" encapsulating an object instance and a timestamp.
 1712  
      *
 1713  
      * Implements Comparable, objects are sorted from old to new.
 1714  
      *
 1715  
      * This is also used by {@link GenericObjectPool}.
 1716  
      */
 1717  
     static class ObjectTimestampPair implements Comparable {
 1718  
         Object value;
 1719  
         long tstamp;
 1720  
 
 1721  
         ObjectTimestampPair(Object val) {
 1722  0
             this(val, System.currentTimeMillis());
 1723  0
         }
 1724  
 
 1725  0
         ObjectTimestampPair(Object val, long time) {
 1726  0
             value = val;
 1727  0
             tstamp = time;
 1728  0
         }
 1729  
 
 1730  
         public String toString() {
 1731  0
             return value + ";" + tstamp;
 1732  
         }
 1733  
 
 1734  
         public int compareTo(Object obj) {
 1735  0
             return compareTo((ObjectTimestampPair) obj);
 1736  
         }
 1737  
 
 1738  
         public int compareTo(ObjectTimestampPair other) {
 1739  0
             final long tstampdiff = this.tstamp - other.tstamp;
 1740  0
             if (tstampdiff == 0) {
 1741  
                 // make sure the natural ordering is consistent with equals
 1742  
                 // see java.lang.Comparable Javadocs
 1743  0
                 return System.identityHashCode(this) - System.identityHashCode(other);
 1744  
             } else {
 1745  
                 // handle int overflow
 1746  0
                 return (int)Math.min(Math.max(tstampdiff, Integer.MIN_VALUE), Integer.MAX_VALUE);
 1747  
             }
 1748  
         }
 1749  
     }
 1750  
 
 1751  
     /**
 1752  
      * The idle object evictor {@link TimerTask}.
 1753  
      * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
 1754  
      */
 1755  0
     private class Evictor extends TimerTask {
 1756  
         public void run() {
 1757  
             //Evict from the pool
 1758  
             try {
 1759  0
                 evict();
 1760  0
             } catch(Exception e) {
 1761  
                 // ignored
 1762  0
             }
 1763  
             //Re-create the connections.
 1764  
             try {
 1765  0
                 ensureMinIdle();
 1766  0
             } catch (Exception e) {
 1767  
                 // ignored
 1768  0
             }
 1769  0
         }
 1770  
     }
 1771  
 
 1772  
     /**
 1773  
      * A simple "struct" encapsulating the
 1774  
      * configuration information for a <code>GenericKeyedObjectPool</code>.
 1775  
      * @see GenericKeyedObjectPool#GenericKeyedObjectPool(KeyedPoolableObjectFactory,GenericKeyedObjectPool.Config)
 1776  
      * @see GenericKeyedObjectPool#setConfig
 1777  
      */
 1778  0
     public static class Config {
 1779  
         /**
 1780  
          * @see GenericKeyedObjectPool#setMaxIdle
 1781  
          */
 1782  0
         public int maxIdle = GenericKeyedObjectPool.DEFAULT_MAX_IDLE;
 1783  
         /**
 1784  
          * @see GenericKeyedObjectPool#setMaxActive
 1785  
          */
 1786  0
         public int maxActive = GenericKeyedObjectPool.DEFAULT_MAX_ACTIVE;
 1787  
         /**
 1788  
          * @see GenericKeyedObjectPool#setMaxTotal
 1789  
          */
 1790  0
         public int maxTotal = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;
 1791  
         /**
 1792  
          * @see GenericKeyedObjectPool#setMinIdle
 1793  
          */
 1794  0
         public int minIdle = GenericKeyedObjectPool.DEFAULT_MIN_IDLE;
 1795  
         /**
 1796  
          * @see GenericKeyedObjectPool#setMaxWait
 1797  
          */
 1798  0
         public long maxWait = GenericKeyedObjectPool.DEFAULT_MAX_WAIT;
 1799  
         /**
 1800  
          * @see GenericKeyedObjectPool#setWhenExhaustedAction
 1801  
          */
 1802  0
         public byte whenExhaustedAction = GenericKeyedObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
 1803  
         /**
 1804  
          * @see GenericKeyedObjectPool#setTestOnBorrow
 1805  
          */
 1806  0
         public boolean testOnBorrow = GenericKeyedObjectPool.DEFAULT_TEST_ON_BORROW;
 1807  
         /**
 1808  
          * @see GenericKeyedObjectPool#setTestOnReturn
 1809  
          */
 1810  0
         public boolean testOnReturn = GenericKeyedObjectPool.DEFAULT_TEST_ON_RETURN;
 1811  
         /**
 1812  
          * @see GenericKeyedObjectPool#setTestWhileIdle
 1813  
          */
 1814  0
         public boolean testWhileIdle = GenericKeyedObjectPool.DEFAULT_TEST_WHILE_IDLE;
 1815  
         /**
 1816  
          * @see GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis
 1817  
          */
 1818  0
         public long timeBetweenEvictionRunsMillis = GenericKeyedObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
 1819  
         /**
 1820  
          * @see GenericKeyedObjectPool#setNumTestsPerEvictionRun
 1821  
          */
 1822  0
         public int numTestsPerEvictionRun =  GenericKeyedObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
 1823  
         /**
 1824  
          * @see GenericKeyedObjectPool#setMinEvictableIdleTimeMillis
 1825  
          */
 1826  0
         public long minEvictableIdleTimeMillis = GenericKeyedObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
 1827  
         /**
 1828  
          * @see GenericKeyedObjectPool#setLifo
 1829  
          */
 1830  0
         public boolean lifo = GenericKeyedObjectPool.DEFAULT_LIFO;
 1831  
     }
 1832  
 
 1833  
     //--- protected attributes ---------------------------------------
 1834  
 
 1835  
     /**
 1836  
      * The cap on the number of idle instances in the pool.
 1837  
      * @see #setMaxIdle
 1838  
      * @see #getMaxIdle
 1839  
      */
 1840  0
     private int _maxIdle = DEFAULT_MAX_IDLE;
 1841  
 
 1842  
     /**
 1843  
      * The minimum no of idle objects to keep in the pool.
 1844  
      * @see #setMinIdle
 1845  
      * @see #getMinIdle
 1846  
      */
 1847  0
     private int _minIdle = DEFAULT_MIN_IDLE;
 1848  
 
 1849  
     /**
 1850  
      * The cap on the number of active instances from the pool.
 1851  
      * @see #setMaxActive
 1852  
      * @see #getMaxActive
 1853  
      */
 1854  0
     private int _maxActive = DEFAULT_MAX_ACTIVE;
 1855  
 
 1856  
     /**
 1857  
      * The cap on the total number of instances from the pool if non-positive.
 1858  
      * @see #setMaxTotal
 1859  
      * @see #getMaxTotal
 1860  
      */
 1861  0
     private int _maxTotal = DEFAULT_MAX_TOTAL;
 1862  
     
 1863  
     /**
 1864  
      * The maximum amount of time (in millis) the
 1865  
      * {@link #borrowObject} method should block before throwing
 1866  
      * an exception when the pool is exhausted and the
 1867  
      * {@link #getWhenExhaustedAction "when exhausted" action} is
 1868  
      * {@link #WHEN_EXHAUSTED_BLOCK}.
 1869  
      *
 1870  
      * When less than or equal to 0, the {@link #borrowObject} method
 1871  
      * may block indefinitely.
 1872  
      *
 1873  
      * @see #setMaxWait
 1874  
      * @see #getMaxWait
 1875  
      * @see #WHEN_EXHAUSTED_BLOCK
 1876  
      * @see #setWhenExhaustedAction
 1877  
      * @see #getWhenExhaustedAction
 1878  
      */
 1879  0
     private long _maxWait = DEFAULT_MAX_WAIT;
 1880  
 
 1881  
     /**
 1882  
      * The action to take when the {@link #borrowObject} method
 1883  
      * is invoked when the pool is exhausted (the maximum number
 1884  
      * of "active" objects has been reached).
 1885  
      *
 1886  
      * @see #WHEN_EXHAUSTED_BLOCK
 1887  
      * @see #WHEN_EXHAUSTED_FAIL
 1888  
      * @see #WHEN_EXHAUSTED_GROW
 1889  
      * @see #DEFAULT_WHEN_EXHAUSTED_ACTION
 1890  
      * @see #setWhenExhaustedAction
 1891  
      * @see #getWhenExhaustedAction
 1892  
      */
 1893  0
     private byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION;
 1894  
 
 1895  
     /**
 1896  
      * When <code>true</code>, objects will be
 1897  
      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
 1898  
      * before being returned by the {@link #borrowObject}
 1899  
      * method.  If the object fails to validate,
 1900  
      * it will be dropped from the pool, and we will attempt
 1901  
      * to borrow another.
 1902  
      *
 1903  
      * @see #setTestOnBorrow
 1904  
      * @see #getTestOnBorrow
 1905  
      */
 1906  0
     private volatile boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW;
 1907  
 
 1908  
     /**
 1909  
      * When <code>true</code>, objects will be
 1910  
      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
 1911  
      * before being returned to the pool within the
 1912  
      * {@link #returnObject}.
 1913  
      *
 1914  
      * @see #getTestOnReturn
 1915  
      * @see #setTestOnReturn
 1916  
      */
 1917  0
     private volatile boolean _testOnReturn = DEFAULT_TEST_ON_RETURN;
 1918  
 
 1919  
     /**
 1920  
      * When <code>true</code>, objects will be
 1921  
      * {@link org.apache.commons.pool.PoolableObjectFactory#validateObject validated}
 1922  
      * by the idle object evictor (if any).  If an object
 1923  
      * fails to validate, it will be dropped from the pool.
 1924  
      *
 1925  
      * @see #setTestWhileIdle
 1926  
      * @see #getTestWhileIdle
 1927  
      * @see #getTimeBetweenEvictionRunsMillis
 1928  
      * @see #setTimeBetweenEvictionRunsMillis
 1929  
      */
 1930  0
     private boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE;
 1931  
 
 1932  
     /**
 1933  
      * The number of milliseconds to sleep between runs of the
 1934  
      * idle object evictor thread.
 1935  
      * When non-positive, no idle object evictor thread will be
 1936  
      * run.
 1937  
      *
 1938  
      * @see #setTimeBetweenEvictionRunsMillis
 1939  
      * @see #getTimeBetweenEvictionRunsMillis
 1940  
      */
 1941  0
     private long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
 1942  
 
 1943  
     /**
 1944  
      * The number of objects to examine during each run of the
 1945  
      * idle object evictor thread (if any).
 1946  
      * <p>
 1947  
      * When a negative value is supplied, <code>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</code>
 1948  
      * tests will be run.  I.e., when the value is <code>-n</code>, roughly one <code>n</code>th of the
 1949  
      * idle objects will be tested per run.
 1950  
      *
 1951  
      * @see #setNumTestsPerEvictionRun
 1952  
      * @see #getNumTestsPerEvictionRun
 1953  
      * @see #getTimeBetweenEvictionRunsMillis
 1954  
      * @see #setTimeBetweenEvictionRunsMillis
 1955  
      */
 1956  0
     private int _numTestsPerEvictionRun =  DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
 1957  
 
 1958  
     /**
 1959  
      * The minimum amount of time an object may sit idle in the pool
 1960  
      * before it is eligible for eviction by the idle object evictor
 1961  
      * (if any).
 1962  
      * When non-positive, no objects will be evicted from the pool
 1963  
      * due to idle time alone.
 1964  
      *
 1965  
      * @see #setMinEvictableIdleTimeMillis
 1966  
      * @see #getMinEvictableIdleTimeMillis
 1967  
      * @see #getTimeBetweenEvictionRunsMillis
 1968  
      * @see #setTimeBetweenEvictionRunsMillis
 1969  
      */
 1970  0
     private long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
 1971  
 
 1972  
     /** My hash of pools (ObjectQueue). */
 1973  0
     private Map _poolMap = null;
 1974  
 
 1975  
     /** The total number of active instances. */
 1976  0
     private int _totalActive = 0;
 1977  
 
 1978  
     /** The total number of idle instances. */
 1979  0
     private int _totalIdle = 0;
 1980  
 
 1981  
     /** My {@link KeyedPoolableObjectFactory}. */
 1982  0
     private KeyedPoolableObjectFactory _factory = null;
 1983  
 
 1984  
     /**
 1985  
      * My idle object eviction {@link TimerTask}, if any.
 1986  
      */
 1987  0
     private Evictor _evictor = null;
 1988  
 
 1989  
     /**
 1990  
      * A cursorable list of my pools.
 1991  
      * @see GenericKeyedObjectPool.Evictor#run
 1992  
      */
 1993  0
     private CursorableLinkedList _poolList = null;
 1994  
     
 1995  0
     private CursorableLinkedList.Cursor _evictionCursor = null;
 1996  0
     private CursorableLinkedList.Cursor _evictionKeyCursor = null;
 1997  
     
 1998  
     /** Whether or not the pools behave as LIFO queues (last in first out) */
 1999  0
     private boolean _lifo = DEFAULT_LIFO;
 2000  
 }