Coverage Report - org.apache.commons.pool.PoolUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
PoolUtils
0%
0/93
0%
0/56
1.786
PoolUtils$CheckedKeyedObjectPool
0%
0/46
0%
0/10
1.786
PoolUtils$CheckedObjectPool
0%
0/42
0%
0/10
1.786
PoolUtils$ErodingFactor
0%
0/15
N/A
1.786
PoolUtils$ErodingKeyedObjectPool
0%
0/49
0%
0/8
1.786
PoolUtils$ErodingObjectPool
0%
0/37
0%
0/6
1.786
PoolUtils$ErodingPerKeyKeyedObjectPool
0%
0/11
0%
0/2
1.786
PoolUtils$KeyedObjectPoolAdaptor
0%
0/35
0%
0/2
1.786
PoolUtils$KeyedObjectPoolMinIdleTimerTask
0%
0/23
0%
0/6
1.786
PoolUtils$KeyedPoolableObjectFactoryAdaptor
0%
0/18
0%
0/2
1.786
PoolUtils$ObjectPoolAdaptor
0%
0/35
0%
0/4
1.786
PoolUtils$ObjectPoolMinIdleTimerTask
0%
0/21
0%
0/6
1.786
PoolUtils$PoolableObjectFactoryAdaptor
0%
0/22
0%
0/4
1.786
PoolUtils$SynchronizedKeyedObjectPool
0%
0/60
0%
0/2
1.786
PoolUtils$SynchronizedKeyedPoolableObjectFactory
0%
0/29
0%
0/2
1.786
PoolUtils$SynchronizedObjectPool
0%
0/50
0%
0/2
1.786
PoolUtils$SynchronizedPoolableObjectFactory
0%
0/29
0%
0/2
1.786
 
 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;
 19  
 
 20  
 import java.util.Collection;
 21  
 import java.util.HashMap;
 22  
 import java.util.Iterator;
 23  
 import java.util.Map;
 24  
 import java.util.NoSuchElementException;
 25  
 import java.util.Timer;
 26  
 import java.util.TimerTask;
 27  
 import java.util.Collections;
 28  
 
 29  
 /**
 30  
  * This class consists exclusively of static methods that operate on or return ObjectPool
 31  
  * or KeyedObjectPool related interfaces.
 32  
  *
 33  
  * @author Sandy McArthur
 34  
  * @version $Revision: 1206485 $ $Date: 2011-11-26 09:39:32 -0700 (Sat, 26 Nov 2011) $
 35  
  * @since Pool 1.3
 36  
  */
 37  
 public final class PoolUtils {
 38  
 
 39  
     /**
 40  
      * Timer used to periodically check pools idle object count.
 41  
      * Because a {@link Timer} creates a {@link Thread} this is lazily instantiated.
 42  
      */
 43  
     private static Timer MIN_IDLE_TIMER; //@GuardedBy("this")
 44  
 
 45  
     /**
 46  
      * PoolUtils instances should NOT be constructed in standard programming.
 47  
      * Instead, the class should be used procedurally: PoolUtils.adapt(aPool);.
 48  
      * This constructor is public to permit tools that require a JavaBean instance to operate.
 49  
      */
 50  0
     public PoolUtils() {
 51  0
     }
 52  
 
 53  
     /**
 54  
      * Should the supplied Throwable be re-thrown (eg if it is an instance of
 55  
      * one of the Throwables that should never be swallowed). Used by the pool
 56  
      * error handling for operations that throw exceptions that normally need to
 57  
      * be ignored.
 58  
      * @param t The Throwable to check
 59  
      * @throws ThreadDeath if that is passed in
 60  
      * @throws VirtualMachineError if that is passed in
 61  
      * @since Pool 1.5.5
 62  
      */
 63  
     public static void checkRethrow(Throwable t) {
 64  0
         if (t instanceof ThreadDeath) {
 65  0
             throw (ThreadDeath) t;
 66  
         }
 67  0
         if (t instanceof VirtualMachineError) {
 68  0
             throw (VirtualMachineError) t;
 69  
         }
 70  
         // All other instances of Throwable will be silently swallowed
 71  0
     }
 72  
 
 73  
     /**
 74  
      * Adapt a <code>KeyedPoolableObjectFactory</code> instance to work where a <code>PoolableObjectFactory</code> is
 75  
      * needed. This method is the equivalent of calling
 76  
      * {@link #adapt(KeyedPoolableObjectFactory, Object) PoolUtils.adapt(aKeyedPoolableObjectFactory, new Object())}.
 77  
      *
 78  
      * @param keyedFactory the {@link KeyedPoolableObjectFactory} to delegate to.
 79  
      * @return a {@link PoolableObjectFactory} that delegates to <code>keyedFactory</code> with an internal key.
 80  
      * @throws IllegalArgumentException when <code>keyedFactory</code> is <code>null</code>.
 81  
      * @see #adapt(KeyedPoolableObjectFactory, Object)
 82  
      * @since Pool 1.3
 83  
      */
 84  
     public static PoolableObjectFactory adapt(final KeyedPoolableObjectFactory keyedFactory) throws IllegalArgumentException {
 85  0
         return adapt(keyedFactory, new Object());
 86  
     }
 87  
 
 88  
     /**
 89  
      * Adapt a <code>KeyedPoolableObjectFactory</code> instance to work where a <code>PoolableObjectFactory</code> is
 90  
      * needed using the specified <code>key</code> when delegating.
 91  
      *
 92  
      * @param keyedFactory the {@link KeyedPoolableObjectFactory} to delegate to.
 93  
      * @param key the key to use when delegating.
 94  
      * @return a {@link PoolableObjectFactory} that delegates to <code>keyedFactory</code> with the specified key.
 95  
      * @throws IllegalArgumentException when <code>keyedFactory</code> or <code>key</code> is <code>null</code>.
 96  
      * @see #adapt(KeyedPoolableObjectFactory)
 97  
      * @since Pool 1.3
 98  
      */
 99  
     public static PoolableObjectFactory adapt(final KeyedPoolableObjectFactory keyedFactory, final Object key) throws IllegalArgumentException {
 100  0
         return new PoolableObjectFactoryAdaptor(keyedFactory, key);
 101  
     }
 102  
 
 103  
     /**
 104  
      * Adapt a <code>PoolableObjectFactory</code> instance to work where a <code>KeyedPoolableObjectFactory</code> is
 105  
      * needed. The key is ignored.
 106  
      *
 107  
      * @param factory the {@link PoolableObjectFactory} to delegate to.
 108  
      * @return a {@link KeyedPoolableObjectFactory} that delegates to <code>factory</code> ignoring the key.
 109  
      * @throws IllegalArgumentException when <code>factory</code> is <code>null</code>.
 110  
      * @since Pool 1.3
 111  
      */
 112  
     public static KeyedPoolableObjectFactory adapt(final PoolableObjectFactory factory) throws IllegalArgumentException {
 113  0
         return new KeyedPoolableObjectFactoryAdaptor(factory);
 114  
     }
 115  
 
 116  
     /**
 117  
      * Adapt a <code>KeyedObjectPool</code> instance to work where an <code>ObjectPool</code> is needed. This is the
 118  
      * equivalent of calling {@link #adapt(KeyedObjectPool, Object) PoolUtils.adapt(aKeyedObjectPool, new Object())}.
 119  
      *
 120  
      * @param keyedPool the {@link KeyedObjectPool} to delegate to.
 121  
      * @return an {@link ObjectPool} that delegates to <code>keyedPool</code> with an internal key.
 122  
      * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code>.
 123  
      * @see #adapt(KeyedObjectPool, Object)
 124  
      * @since Pool 1.3
 125  
      */
 126  
     public static ObjectPool adapt(final KeyedObjectPool keyedPool) throws IllegalArgumentException {
 127  0
         return adapt(keyedPool, new Object());
 128  
     }
 129  
 
 130  
     /**
 131  
      * Adapt a <code>KeyedObjectPool</code> instance to work where an <code>ObjectPool</code> is needed using the
 132  
      * specified <code>key</code> when delegating.
 133  
      *
 134  
      * @param keyedPool the {@link KeyedObjectPool} to delegate to.
 135  
      * @param key the key to use when delegating.
 136  
      * @return an {@link ObjectPool} that delegates to <code>keyedPool</code> with the specified key.
 137  
      * @throws IllegalArgumentException when <code>keyedPool</code> or <code>key</code> is <code>null</code>.
 138  
      * @see #adapt(KeyedObjectPool)
 139  
      * @since Pool 1.3
 140  
      */
 141  
     public static ObjectPool adapt(final KeyedObjectPool keyedPool, final Object key) throws IllegalArgumentException {
 142  0
         return new ObjectPoolAdaptor(keyedPool, key);
 143  
     }
 144  
 
 145  
     /**
 146  
      * Adapt an <code>ObjectPool</code> to work where an <code>KeyedObjectPool</code> is needed.
 147  
      * The key is ignored.
 148  
      *
 149  
      * @param pool the {@link ObjectPool} to delegate to.
 150  
      * @return a {@link KeyedObjectPool} that delegates to <code>pool</code> ignoring the key.
 151  
      * @throws IllegalArgumentException when <code>pool</code> is <code>null</code>.
 152  
      * @since Pool 1.3
 153  
      */
 154  
     public static KeyedObjectPool adapt(final ObjectPool pool) throws IllegalArgumentException {
 155  0
         return new KeyedObjectPoolAdaptor(pool);
 156  
     }
 157  
 
 158  
     /**
 159  
      * Wraps an <code>ObjectPool</code> and dynamically checks the type of objects borrowed and returned to the pool.
 160  
      * If an object is passed to the pool that isn't of type <code>type</code> a {@link ClassCastException} will be thrown.
 161  
      *
 162  
      * @param pool the pool to enforce type safety on
 163  
      * @param type the class type to enforce.
 164  
      * @return an <code>ObjectPool</code> that will only allow objects of <code>type</code>
 165  
      * @since Pool 1.3
 166  
      */
 167  
     public static ObjectPool checkedPool(final ObjectPool pool, final Class type) {
 168  0
         if (pool == null) {
 169  0
             throw new IllegalArgumentException("pool must not be null.");
 170  
         }
 171  0
         if (type == null) {
 172  0
             throw new IllegalArgumentException("type must not be null.");
 173  
         }
 174  0
         return new CheckedObjectPool(pool, type);
 175  
     }
 176  
 
 177  
     /**
 178  
      * Wraps a <code>KeyedObjectPool</code> and dynamically checks the type of objects borrowed and returned to the keyedPool.
 179  
      * If an object is passed to the keyedPool that isn't of type <code>type</code> a {@link ClassCastException} will be thrown.
 180  
      *
 181  
      * @param keyedPool the keyedPool to enforce type safety on
 182  
      * @param type the class type to enforce.
 183  
      * @return a <code>KeyedObjectPool</code> that will only allow objects of <code>type</code>
 184  
      * @since Pool 1.3
 185  
      */
 186  
     public static KeyedObjectPool checkedPool(final KeyedObjectPool keyedPool, final Class type) {
 187  0
         if (keyedPool == null) {
 188  0
             throw new IllegalArgumentException("keyedPool must not be null.");
 189  
         }
 190  0
         if (type == null) {
 191  0
             throw new IllegalArgumentException("type must not be null.");
 192  
         }
 193  0
         return new CheckedKeyedObjectPool(keyedPool, type);
 194  
     }
 195  
 
 196  
     /**
 197  
      * Periodically check the idle object count for the pool. At most one idle object will be added per period.
 198  
      * If there is an exception when calling {@link ObjectPool#addObject()} then no more checks will be performed.
 199  
      *
 200  
      * @param pool the pool to check periodically.
 201  
      * @param minIdle if the {@link ObjectPool#getNumIdle()} is less than this then add an idle object.
 202  
      * @param period the frequency to check the number of idle objects in a pool, see
 203  
      *      {@link Timer#schedule(TimerTask, long, long)}.
 204  
      * @return the {@link TimerTask} that will periodically check the pools idle object count.
 205  
      * @throws IllegalArgumentException when <code>pool</code> is <code>null</code> or
 206  
      *      when <code>minIdle</code> is negative or when <code>period</code> isn't
 207  
      *      valid for {@link Timer#schedule(TimerTask, long, long)}.
 208  
      * @since Pool 1.3
 209  
      */
 210  
     public static TimerTask checkMinIdle(final ObjectPool pool, final int minIdle, final long period) throws IllegalArgumentException {
 211  0
         if (pool == null) {
 212  0
             throw new IllegalArgumentException("keyedPool must not be null.");
 213  
         }
 214  0
         if (minIdle < 0) {
 215  0
             throw new IllegalArgumentException("minIdle must be non-negative.");
 216  
         }
 217  0
         final TimerTask task = new ObjectPoolMinIdleTimerTask(pool, minIdle);
 218  0
         getMinIdleTimer().schedule(task, 0L, period);
 219  0
         return task;
 220  
     }
 221  
 
 222  
     /**
 223  
      * Periodically check the idle object count for the key in the keyedPool. At most one idle object will be added per period.
 224  
      * If there is an exception when calling {@link KeyedObjectPool#addObject(Object)} then no more checks for that key
 225  
      * will be performed.
 226  
      *
 227  
      * @param keyedPool the keyedPool to check periodically.
 228  
      * @param key the key to check the idle count of.
 229  
      * @param minIdle if the {@link KeyedObjectPool#getNumIdle(Object)} is less than this then add an idle object.
 230  
      * @param period the frequency to check the number of idle objects in a keyedPool, see
 231  
      *      {@link Timer#schedule(TimerTask, long, long)}.
 232  
      * @return the {@link TimerTask} that will periodically check the pools idle object count.
 233  
      * @throws IllegalArgumentException when <code>keyedPool</code>, <code>key</code> is <code>null</code> or
 234  
      *      when <code>minIdle</code> is negative or when <code>period</code> isn't
 235  
      *      valid for {@link Timer#schedule(TimerTask, long, long)}.
 236  
      * @since Pool 1.3
 237  
      */
 238  
     public static TimerTask checkMinIdle(final KeyedObjectPool keyedPool, final Object key, final int minIdle, final long period) throws IllegalArgumentException {
 239  0
         if (keyedPool == null) {
 240  0
             throw new IllegalArgumentException("keyedPool must not be null.");
 241  
         }
 242  0
         if (key == null) {
 243  0
             throw new IllegalArgumentException("key must not be null.");
 244  
         }
 245  0
         if (minIdle < 0) {
 246  0
             throw new IllegalArgumentException("minIdle must be non-negative.");
 247  
         }
 248  0
         final TimerTask task = new KeyedObjectPoolMinIdleTimerTask(keyedPool, key, minIdle);
 249  0
         getMinIdleTimer().schedule(task, 0L, period);
 250  0
         return task;
 251  
     }
 252  
 
 253  
     /**
 254  
      * Periodically check the idle object count for each key in the <code>Collection</code> <code>keys</code> in the keyedPool.
 255  
      * At most one idle object will be added per period.
 256  
      *
 257  
      * @param keyedPool the keyedPool to check periodically.
 258  
      * @param keys a collection of keys to check the idle object count.
 259  
      * @param minIdle if the {@link KeyedObjectPool#getNumIdle(Object)} is less than this then add an idle object.
 260  
      * @param period the frequency to check the number of idle objects in a keyedPool, see
 261  
      *      {@link Timer#schedule(TimerTask, long, long)}.
 262  
      * @return a {@link Map} of key and {@link TimerTask} pairs that will periodically check the pools idle object count.
 263  
      * @throws IllegalArgumentException when <code>keyedPool</code>, <code>keys</code>, or any of the values in the
 264  
      *      collection is <code>null</code> or when <code>minIdle</code> is negative or when <code>period</code> isn't
 265  
      *      valid for {@link Timer#schedule(TimerTask, long, long)}.
 266  
      * @see #checkMinIdle(KeyedObjectPool, Object, int, long)
 267  
      * @since Pool 1.3
 268  
      */
 269  
     public static Map checkMinIdle(final KeyedObjectPool keyedPool, final Collection keys, final int minIdle, final long period) throws IllegalArgumentException {
 270  0
         if (keys == null) {
 271  0
             throw new IllegalArgumentException("keys must not be null.");
 272  
         }
 273  0
         final Map tasks = new HashMap(keys.size());
 274  0
         final Iterator iter = keys.iterator();
 275  0
         while (iter.hasNext()) {
 276  0
             final Object key = iter.next();
 277  0
             final TimerTask task = checkMinIdle(keyedPool, key, minIdle, period);
 278  0
             tasks.put(key, task);
 279  0
         }
 280  0
         return tasks;
 281  
     }
 282  
 
 283  
     /**
 284  
      * Call <code>addObject()</code> on <code>pool</code> <code>count</code> number of times.
 285  
      *
 286  
      * @param pool the pool to prefill.
 287  
      * @param count the number of idle objects to add.
 288  
      * @throws Exception when {@link ObjectPool#addObject()} fails.
 289  
      * @throws IllegalArgumentException when <code>pool</code> is <code>null</code>.
 290  
      * @since Pool 1.3
 291  
      */
 292  
     public static void prefill(final ObjectPool pool, final int count) throws Exception, IllegalArgumentException {
 293  0
         if (pool == null) {
 294  0
             throw new IllegalArgumentException("pool must not be null.");
 295  
         }
 296  0
         for (int i = 0; i < count; i++) {
 297  0
             pool.addObject();
 298  
         }
 299  0
     }
 300  
 
 301  
     /**
 302  
      * Call <code>addObject(Object)</code> on <code>keyedPool</code> with <code>key</code> <code>count</code>
 303  
      * number of times.
 304  
      *
 305  
      * @param keyedPool the keyedPool to prefill.
 306  
      * @param key the key to add objects for.
 307  
      * @param count the number of idle objects to add for <code>key</code>.
 308  
      * @throws Exception when {@link KeyedObjectPool#addObject(Object)} fails.
 309  
      * @throws IllegalArgumentException when <code>keyedPool</code> or <code>key</code> is <code>null</code>.
 310  
      * @since Pool 1.3
 311  
      */
 312  
     public static void prefill(final KeyedObjectPool keyedPool, final Object key, final int count) throws Exception, IllegalArgumentException {
 313  0
         if (keyedPool == null) {
 314  0
             throw new IllegalArgumentException("keyedPool must not be null.");
 315  
         }
 316  0
         if (key == null) {
 317  0
             throw new IllegalArgumentException("key must not be null.");
 318  
         }
 319  0
         for (int i = 0; i < count; i++) {
 320  0
             keyedPool.addObject(key);
 321  
         }
 322  0
     }
 323  
 
 324  
     /**
 325  
      * Call <code>addObject(Object)</code> on <code>keyedPool</code> with each key in <code>keys</code> for
 326  
      * <code>count</code> number of times. This has the same effect as calling
 327  
      * {@link #prefill(KeyedObjectPool, Object, int)} for each key in the <code>keys</code> collection.
 328  
      *
 329  
      * @param keyedPool the keyedPool to prefill.
 330  
      * @param keys {@link Collection} of keys to add objects for.
 331  
      * @param count the number of idle objects to add for each <code>key</code>.
 332  
      * @throws Exception when {@link KeyedObjectPool#addObject(Object)} fails.
 333  
      * @throws IllegalArgumentException when <code>keyedPool</code>, <code>keys</code>, or
 334  
      *      any value in <code>keys</code> is <code>null</code>.
 335  
      * @see #prefill(KeyedObjectPool, Object, int)
 336  
      * @since Pool 1.3
 337  
      */
 338  
     public static void prefill(final KeyedObjectPool keyedPool, final Collection keys, final int count) throws Exception, IllegalArgumentException {
 339  0
         if (keys == null) {
 340  0
             throw new IllegalArgumentException("keys must not be null.");
 341  
         }
 342  0
         final Iterator iter = keys.iterator();
 343  0
         while (iter.hasNext()) {
 344  0
             prefill(keyedPool, iter.next(), count);
 345  
         }
 346  0
     }
 347  
 
 348  
     /**
 349  
      * Returns a synchronized (thread-safe) ObjectPool backed by the specified ObjectPool.
 350  
      *
 351  
      * <p><b>Note:</b>
 352  
      * This should not be used on pool implementations that already provide proper synchronization
 353  
      * such as the pools provided in the Commons Pool library. Wrapping a pool that
 354  
      * {@link #wait() waits} for poolable objects to be returned before allowing another one to be
 355  
      * borrowed with another layer of synchronization will cause liveliness issues or a deadlock.
 356  
      * </p>
 357  
      *
 358  
      * @param pool the ObjectPool to be "wrapped" in a synchronized ObjectPool.
 359  
      * @return a synchronized view of the specified ObjectPool.
 360  
      * @since Pool 1.3
 361  
      */
 362  
     public static ObjectPool synchronizedPool(final ObjectPool pool) {
 363  0
         if (pool == null) {
 364  0
             throw new IllegalArgumentException("pool must not be null.");
 365  
         }
 366  
         /*
 367  
         assert !(pool instanceof GenericObjectPool)
 368  
                 : "GenericObjectPool is already thread-safe";
 369  
         assert !(pool instanceof SoftReferenceObjectPool)
 370  
                 : "SoftReferenceObjectPool is already thread-safe";
 371  
         assert !(pool instanceof StackObjectPool)
 372  
                 : "StackObjectPool is already thread-safe";
 373  
         assert !"org.apache.commons.pool.composite.CompositeObjectPool".equals(pool.getClass().getName())
 374  
                 : "CompositeObjectPools are already thread-safe";
 375  
         */
 376  0
         return new SynchronizedObjectPool(pool);
 377  
     }
 378  
 
 379  
     /**
 380  
      * Returns a synchronized (thread-safe) KeyedObjectPool backed by the specified KeyedObjectPool.
 381  
      *
 382  
      * <p><b>Note:</b>
 383  
      * This should not be used on pool implementations that already provide proper synchronization
 384  
      * such as the pools provided in the Commons Pool library. Wrapping a pool that
 385  
      * {@link #wait() waits} for poolable objects to be returned before allowing another one to be
 386  
      * borrowed with another layer of synchronization will cause liveliness issues or a deadlock.
 387  
      * </p>
 388  
      *
 389  
      * @param keyedPool the KeyedObjectPool to be "wrapped" in a synchronized KeyedObjectPool.
 390  
      * @return a synchronized view of the specified KeyedObjectPool.
 391  
      * @since Pool 1.3
 392  
      */
 393  
     public static KeyedObjectPool synchronizedPool(final KeyedObjectPool keyedPool) {
 394  0
         if (keyedPool == null) {
 395  0
             throw new IllegalArgumentException("keyedPool must not be null.");
 396  
         }
 397  
         /*
 398  
         assert !(keyedPool instanceof GenericKeyedObjectPool)
 399  
                 : "GenericKeyedObjectPool is already thread-safe";
 400  
         assert !(keyedPool instanceof StackKeyedObjectPool)
 401  
                 : "StackKeyedObjectPool is already thread-safe";
 402  
         assert !"org.apache.commons.pool.composite.CompositeKeyedObjectPool".equals(keyedPool.getClass().getName())
 403  
                 : "CompositeKeyedObjectPools are already thread-safe";
 404  
         */
 405  0
         return new SynchronizedKeyedObjectPool(keyedPool);
 406  
     }
 407  
 
 408  
     /**
 409  
      * Returns a synchronized (thread-safe) PoolableObjectFactory backed by the specified PoolableObjectFactory.
 410  
      *
 411  
      * @param factory the PoolableObjectFactory to be "wrapped" in a synchronized PoolableObjectFactory.
 412  
      * @return a synchronized view of the specified PoolableObjectFactory.
 413  
      * @since Pool 1.3
 414  
      */
 415  
     public static PoolableObjectFactory synchronizedPoolableFactory(final PoolableObjectFactory factory) {
 416  0
         return new SynchronizedPoolableObjectFactory(factory);
 417  
     }
 418  
 
 419  
     /**
 420  
      * Returns a synchronized (thread-safe) KeyedPoolableObjectFactory backed by the specified KeyedPoolableObjectFactory.
 421  
      *
 422  
      * @param keyedFactory the KeyedPoolableObjectFactory to be "wrapped" in a synchronized KeyedPoolableObjectFactory.
 423  
      * @return a synchronized view of the specified KeyedPoolableObjectFactory.
 424  
      * @since Pool 1.3
 425  
      */
 426  
     public static KeyedPoolableObjectFactory synchronizedPoolableFactory(final KeyedPoolableObjectFactory keyedFactory) {
 427  0
         return new SynchronizedKeyedPoolableObjectFactory(keyedFactory);
 428  
     }
 429  
 
 430  
     /**
 431  
      * Returns a pool that adaptively decreases it's size when idle objects are no longer needed.
 432  
      * This is intended as an always thread-safe alternative to using an idle object evictor
 433  
      * provided by many pool implementations. This is also an effective way to shrink FIFO ordered
 434  
      * pools that experience load spikes.
 435  
      *
 436  
      * @param pool the ObjectPool to be decorated so it shrinks it's idle count when possible.
 437  
      * @return a pool that adaptively decreases it's size when idle objects are no longer needed.
 438  
      * @see #erodingPool(ObjectPool, float)
 439  
      * @since Pool 1.4
 440  
      */
 441  
     public static ObjectPool erodingPool(final ObjectPool pool) {
 442  0
         return erodingPool(pool, 1f);
 443  
     }
 444  
 
 445  
     /**
 446  
      * Returns a pool that adaptively decreases it's size when idle objects are no longer needed.
 447  
      * This is intended as an always thread-safe alternative to using an idle object evictor
 448  
      * provided by many pool implementations. This is also an effective way to shrink FIFO ordered
 449  
      * pools that experience load spikes.
 450  
      *
 451  
      * <p>
 452  
      * The factor parameter provides a mechanism to tweak the rate at which the pool tries to shrink
 453  
      * it's size. Values between 0 and 1 cause the pool to try to shrink it's size more often.
 454  
      * Values greater than 1 cause the pool to less frequently try to shrink it's size.
 455  
      * </p>
 456  
      *
 457  
      * @param pool the ObjectPool to be decorated so it shrinks it's idle count when possible.
 458  
      * @param factor a positive value to scale the rate at which the pool tries to reduce it's size.
 459  
      * If 0 &lt; factor &lt; 1 then the pool shrinks more aggressively.
 460  
      * If 1 &lt; factor then the pool shrinks less aggressively.
 461  
      * @return a pool that adaptively decreases it's size when idle objects are no longer needed.
 462  
      * @see #erodingPool(ObjectPool)
 463  
      * @since Pool 1.4
 464  
      */
 465  
     public static ObjectPool erodingPool(final ObjectPool pool, final float factor) {
 466  0
         if (pool == null) {
 467  0
             throw new IllegalArgumentException("pool must not be null.");
 468  
         }
 469  0
         if (factor <= 0f) {
 470  0
             throw new IllegalArgumentException("factor must be positive.");
 471  
         }
 472  0
         return new ErodingObjectPool(pool, factor);
 473  
     }
 474  
 
 475  
     /**
 476  
      * Returns a pool that adaptively decreases it's size when idle objects are no longer needed.
 477  
      * This is intended as an always thread-safe alternative to using an idle object evictor
 478  
      * provided by many pool implementations. This is also an effective way to shrink FIFO ordered
 479  
      * pools that experience load spikes.
 480  
      *
 481  
      * @param keyedPool the KeyedObjectPool to be decorated so it shrinks it's idle count when
 482  
      * possible.
 483  
      * @return a pool that adaptively decreases it's size when idle objects are no longer needed.
 484  
      * @see #erodingPool(KeyedObjectPool, float)
 485  
      * @see #erodingPool(KeyedObjectPool, float, boolean)
 486  
      * @since Pool 1.4
 487  
      */
 488  
     public static KeyedObjectPool erodingPool(final KeyedObjectPool keyedPool) {
 489  0
         return erodingPool(keyedPool, 1f);
 490  
     }
 491  
 
 492  
     /**
 493  
      * Returns a pool that adaptively decreases it's size when idle objects are no longer needed.
 494  
      * This is intended as an always thread-safe alternative to using an idle object evictor
 495  
      * provided by many pool implementations. This is also an effective way to shrink FIFO ordered
 496  
      * pools that experience load spikes.
 497  
      *
 498  
      * <p>
 499  
      * The factor parameter provides a mechanism to tweak the rate at which the pool tries to shrink
 500  
      * it's size. Values between 0 and 1 cause the pool to try to shrink it's size more often.
 501  
      * Values greater than 1 cause the pool to less frequently try to shrink it's size.
 502  
      * </p>
 503  
      *
 504  
      * @param keyedPool the KeyedObjectPool to be decorated so it shrinks it's idle count when
 505  
      * possible.
 506  
      * @param factor a positive value to scale the rate at which the pool tries to reduce it's size.
 507  
      * If 0 &lt; factor &lt; 1 then the pool shrinks more aggressively.
 508  
      * If 1 &lt; factor then the pool shrinks less aggressively.
 509  
      * @return a pool that adaptively decreases it's size when idle objects are no longer needed.
 510  
      * @see #erodingPool(KeyedObjectPool, float, boolean)
 511  
      * @since Pool 1.4
 512  
      */
 513  
     public static KeyedObjectPool erodingPool(final KeyedObjectPool keyedPool, final float factor) {
 514  0
         return erodingPool(keyedPool, factor, false);
 515  
     }
 516  
 
 517  
     /**
 518  
      * Returns a pool that adaptively decreases it's size when idle objects are no longer needed.
 519  
      * This is intended as an always thread-safe alternative to using an idle object evictor
 520  
      * provided by many pool implementations. This is also an effective way to shrink FIFO ordered
 521  
      * pools that experience load spikes.
 522  
      *
 523  
      * <p>
 524  
      * The factor parameter provides a mechanism to tweak the rate at which the pool tries to shrink
 525  
      * it's size. Values between 0 and 1 cause the pool to try to shrink it's size more often.
 526  
      * Values greater than 1 cause the pool to less frequently try to shrink it's size.
 527  
      * </p>
 528  
      *
 529  
      * <p>
 530  
      * The perKey parameter determines if the pool shrinks on a whole pool basis or a per key basis.
 531  
      * When perKey is false, the keys do not have an effect on the rate at which the pool tries to
 532  
      * shrink it's size. When perKey is true, each key is shrunk independently.
 533  
      * </p>
 534  
      *
 535  
      * @param keyedPool the KeyedObjectPool to be decorated so it shrinks it's idle count when
 536  
      * possible.
 537  
      * @param factor a positive value to scale the rate at which the pool tries to reduce it's size.
 538  
      * If 0 &lt; factor &lt; 1 then the pool shrinks more aggressively.
 539  
      * If 1 &lt; factor then the pool shrinks less aggressively.
 540  
      * @param perKey when true, each key is treated independently.
 541  
      * @return a pool that adaptively decreases it's size when idle objects are no longer needed.
 542  
      * @see #erodingPool(KeyedObjectPool)
 543  
      * @see #erodingPool(KeyedObjectPool, float)
 544  
      * @since Pool 1.4
 545  
      */
 546  
     public static KeyedObjectPool erodingPool(final KeyedObjectPool keyedPool, final float factor, final boolean perKey) {
 547  0
         if (keyedPool == null) {
 548  0
             throw new IllegalArgumentException("keyedPool must not be null.");
 549  
         }
 550  0
         if (factor <= 0f) {
 551  0
             throw new IllegalArgumentException("factor must be positive.");
 552  
         }
 553  0
         if (perKey) {
 554  0
             return new ErodingPerKeyKeyedObjectPool(keyedPool, factor);
 555  
         } else {
 556  0
             return new ErodingKeyedObjectPool(keyedPool, factor);
 557  
         }
 558  
     }
 559  
 
 560  
     /**
 561  
      * Get the <code>Timer</code> for checking keyedPool's idle count. Lazily create the {@link Timer} as needed.
 562  
      *
 563  
      * @return the {@link Timer} for checking keyedPool's idle count.
 564  
      * @since Pool 1.3
 565  
      */
 566  
     private static synchronized Timer getMinIdleTimer() {
 567  0
         if (MIN_IDLE_TIMER == null) {
 568  0
             MIN_IDLE_TIMER = new Timer(true);
 569  
         }
 570  0
         return MIN_IDLE_TIMER;
 571  
     }
 572  
 
 573  
     /**
 574  
      * Adaptor class that wraps and converts a KeyedPoolableObjectFactory with a fixed
 575  
      * key to a PoolableObjectFactory.
 576  
      */
 577  
     private static class PoolableObjectFactoryAdaptor implements PoolableObjectFactory {
 578  
         /** Fixed key */
 579  
         private final Object key;
 580  
         
 581  
         /** Wrapped factory */
 582  
         private final KeyedPoolableObjectFactory keyedFactory;
 583  
 
 584  
         /**
 585  
          * Create a PoolableObjectFactoryAdaptor wrapping the provided KeyedPoolableObjectFactory with the 
 586  
          * given fixed key.
 587  
          * 
 588  
          * @param keyedFactory KeyedPoolableObjectFactory that will manage objects
 589  
          * @param key fixed key
 590  
          * @throws IllegalArgumentException if either of the parameters is null
 591  
          */
 592  
         PoolableObjectFactoryAdaptor(final KeyedPoolableObjectFactory keyedFactory, final Object key)
 593  0
         throws IllegalArgumentException {
 594  0
             if (keyedFactory == null) {
 595  0
                 throw new IllegalArgumentException("keyedFactory must not be null.");
 596  
             }
 597  0
             if (key == null) {
 598  0
                 throw new IllegalArgumentException("key must not be null.");
 599  
             }
 600  0
             this.keyedFactory = keyedFactory;
 601  0
             this.key = key;
 602  0
         }
 603  
 
 604  
         /**
 605  
          * Create an object instance using the configured factory and key.
 606  
          * 
 607  
          * @return new object instance
 608  
          */
 609  
         public Object makeObject() throws Exception {
 610  0
             return keyedFactory.makeObject(key);
 611  
         }
 612  
 
 613  
         /**
 614  
          * Destroy the object, passing the fixed key to the factory.
 615  
          * 
 616  
          * @param obj object to destroy
 617  
          */
 618  
         public void destroyObject(final Object obj) throws Exception {
 619  0
             keyedFactory.destroyObject(key, obj);
 620  0
         }
 621  
 
 622  
         /**
 623  
          * Validate the object, passing the fixed key to the factory.
 624  
          * 
 625  
          * @param obj object to validate
 626  
          * @return true if validation is successful
 627  
          */
 628  
         public boolean validateObject(final Object obj) {
 629  0
             return keyedFactory.validateObject(key, obj);
 630  
         }
 631  
 
 632  
         /**
 633  
          * Activate the object, passing the fixed key to the factory.
 634  
          * 
 635  
          * @param obj object to activate
 636  
          */
 637  
         public void activateObject(final Object obj) throws Exception {
 638  0
             keyedFactory.activateObject(key, obj);
 639  0
         }
 640  
 
 641  
         /**
 642  
          * Passivate the object, passing the fixed key to the factory.
 643  
          * 
 644  
          * @param obj object to passivate
 645  
          */
 646  
         public void passivateObject(final Object obj) throws Exception {
 647  0
             keyedFactory.passivateObject(key, obj);
 648  0
         }
 649  
 
 650  
         /**
 651  
          * {@inheritDoc}
 652  
          */
 653  
         public String toString() {
 654  0
             final StringBuffer sb = new StringBuffer();
 655  0
             sb.append("PoolableObjectFactoryAdaptor");
 656  0
             sb.append("{key=").append(key);
 657  0
             sb.append(", keyedFactory=").append(keyedFactory);
 658  0
             sb.append('}');
 659  0
             return sb.toString();
 660  
         }
 661  
     }
 662  
 
 663  
     /**
 664  
      * Adaptor class that turns a PoolableObjectFactory into a KeyedPoolableObjectFactory by
 665  
      * ignoring keys.
 666  
      */
 667  
     private static class KeyedPoolableObjectFactoryAdaptor implements KeyedPoolableObjectFactory {
 668  
         
 669  
         /** Underlying PoolableObjectFactory */
 670  
         private final PoolableObjectFactory factory;
 671  
 
 672  
         /**
 673  
          * Create a new KeyedPoolableObjectFactoryAdaptor using the given PoolableObjectFactory to
 674  
          * manage objects.
 675  
          * 
 676  
          * @param factory wrapped PoolableObjectFactory 
 677  
          * @throws IllegalArgumentException if the factory is null
 678  
          */
 679  0
         KeyedPoolableObjectFactoryAdaptor(final PoolableObjectFactory factory) throws IllegalArgumentException {
 680  0
             if (factory == null) {
 681  0
                 throw new IllegalArgumentException("factory must not be null.");
 682  
             }
 683  0
             this.factory = factory;
 684  0
         }
 685  
 
 686  
         /**
 687  
          * Create a new object instance, ignoring the key
 688  
          * 
 689  
          * @param key ignored
 690  
          * @return newly created object instance
 691  
          */
 692  
         public Object makeObject(final Object key) throws Exception {
 693  0
             return factory.makeObject();
 694  
         }
 695  
 
 696  
         /**
 697  
          * Destroy the object, ignoring the key.
 698  
          * 
 699  
          * @param key ignored
 700  
          * @param obj instance to destroy
 701  
          */
 702  
         public void destroyObject(final Object key, final Object obj) throws Exception {
 703  0
             factory.destroyObject(obj);
 704  0
         }
 705  
 
 706  
         /**
 707  
          * Validate the object, ignoring the key
 708  
          * 
 709  
          * @param key ignored
 710  
          * @param obj object to validate
 711  
          * @return true if validation is successful
 712  
          */
 713  
         public boolean validateObject(final Object key, final Object obj) {
 714  0
             return factory.validateObject(obj);
 715  
         }
 716  
 
 717  
         /**
 718  
          * Activate the object, ignoring the key.
 719  
          * 
 720  
          * @param key ignored
 721  
          * @param obj object to be activated
 722  
          */
 723  
         public void activateObject(final Object key, final Object obj) throws Exception {
 724  0
             factory.activateObject(obj);
 725  0
         }
 726  
 
 727  
         /**
 728  
          * Passivate the object, ignoring the key.
 729  
          * 
 730  
          * @param key ignored
 731  
          * @param obj object to passivate
 732  
          */
 733  
         public void passivateObject(final Object key, final Object obj) throws Exception {
 734  0
             factory.passivateObject(obj);
 735  0
         }
 736  
 
 737  
         /**
 738  
          * {@inheritDoc}
 739  
          */
 740  
         public String toString() {
 741  0
             final StringBuffer sb = new StringBuffer();
 742  0
             sb.append("KeyedPoolableObjectFactoryAdaptor");
 743  0
             sb.append("{factory=").append(factory);
 744  0
             sb.append('}');
 745  0
             return sb.toString();
 746  
         }
 747  
     }
 748  
 
 749  
     /**
 750  
      * Adapts a KeyedObjectPool to make it an ObjectPool by fixing restricting to
 751  
      * a fixed key.
 752  
      */
 753  
     private static class ObjectPoolAdaptor implements ObjectPool {
 754  
         
 755  
         /** Fixed key */
 756  
         private final Object key;
 757  
         
 758  
         /** Underlying KeyedObjectPool */
 759  
         private final KeyedObjectPool keyedPool;
 760  
 
 761  
         /**
 762  
          * Create a new ObjectPoolAdaptor using the provided KeyedObjectPool and fixed key.
 763  
          * 
 764  
          * @param keyedPool underlying KeyedObjectPool
 765  
          * @param key fixed key
 766  
          * @throws IllegalArgumentException if either of the parameters is null
 767  
          */
 768  0
         ObjectPoolAdaptor(final KeyedObjectPool keyedPool, final Object key) throws IllegalArgumentException {
 769  0
             if (keyedPool == null) {
 770  0
                 throw new IllegalArgumentException("keyedPool must not be null.");
 771  
             }
 772  0
             if (key == null) {
 773  0
                 throw new IllegalArgumentException("key must not be null.");
 774  
             }
 775  0
             this.keyedPool = keyedPool;
 776  0
             this.key = key;
 777  0
         }
 778  
 
 779  
         /**
 780  
          * {@inheritDoc}
 781  
          */
 782  
         public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
 783  0
             return keyedPool.borrowObject(key);
 784  
         }
 785  
 
 786  
         /**
 787  
          * {@inheritDoc}
 788  
          */
 789  
         public void returnObject(final Object obj) {
 790  
             try {
 791  0
                 keyedPool.returnObject(key, obj);
 792  0
             } catch (Exception e) {
 793  
                 // swallowed as of Pool 2
 794  0
             }
 795  0
         }
 796  
 
 797  
         /**
 798  
          * {@inheritDoc}
 799  
          */
 800  
         public void invalidateObject(final Object obj) {
 801  
             try {
 802  0
                 keyedPool.invalidateObject(key, obj);
 803  0
             } catch (Exception e) {
 804  
                 // swallowed as of Pool 2
 805  0
             }
 806  0
         }
 807  
 
 808  
         /**
 809  
          * {@inheritDoc}
 810  
          */
 811  
         public void addObject() throws Exception, IllegalStateException {
 812  0
             keyedPool.addObject(key);
 813  0
         }
 814  
 
 815  
         /**
 816  
          * {@inheritDoc}
 817  
          */
 818  
         public int getNumIdle() throws UnsupportedOperationException {
 819  0
             return keyedPool.getNumIdle(key);
 820  
         }
 821  
 
 822  
         /**
 823  
          * {@inheritDoc}
 824  
          */
 825  
         public int getNumActive() throws UnsupportedOperationException {
 826  0
             return keyedPool.getNumActive(key);
 827  
         }
 828  
 
 829  
         /**
 830  
          * {@inheritDoc}
 831  
          */
 832  
         public void clear() throws Exception, UnsupportedOperationException {
 833  0
             keyedPool.clear();
 834  0
         }
 835  
 
 836  
         /**
 837  
          * {@inheritDoc}
 838  
          */
 839  
         public void close() {
 840  
             try {
 841  0
                 keyedPool.close();
 842  0
             } catch (Exception e) {
 843  
                 // swallowed as of Pool 2
 844  0
             }
 845  0
         }
 846  
 
 847  
         /**
 848  
          * Sets the PoolableObjectFactory for the pool.
 849  
          * 
 850  
          * @param factory new PoolableObjectFactory 
 851  
          * @deprecated to be removed in version 2.0
 852  
          */
 853  
         public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
 854  0
             keyedPool.setFactory(adapt(factory));
 855  0
         }
 856  
 
 857  
         /**
 858  
          * {@inheritDoc}
 859  
          */
 860  
         public String toString() {
 861  0
             final StringBuffer sb = new StringBuffer();
 862  0
             sb.append("ObjectPoolAdaptor");
 863  0
             sb.append("{key=").append(key);
 864  0
             sb.append(", keyedPool=").append(keyedPool);
 865  0
             sb.append('}');
 866  0
             return sb.toString();
 867  
         }
 868  
     }
 869  
 
 870  
     /**
 871  
      * Adapts an ObjectPool to implement KeyedObjectPool by ignoring key arguments.
 872  
      */
 873  
     private static class KeyedObjectPoolAdaptor implements KeyedObjectPool {
 874  
        
 875  
         /** Underlying pool */
 876  
         private final ObjectPool pool;
 877  
 
 878  
         /**
 879  
          * Create a new KeyedObjectPoolAdaptor wrapping the given ObjectPool
 880  
          * 
 881  
          * @param pool underlying object pool
 882  
          * @throws IllegalArgumentException if pool is null
 883  
          */
 884  0
         KeyedObjectPoolAdaptor(final ObjectPool pool) throws IllegalArgumentException {
 885  0
             if (pool == null) {
 886  0
                 throw new IllegalArgumentException("pool must not be null.");
 887  
             }
 888  0
             this.pool = pool;
 889  0
         }
 890  
 
 891  
         /**
 892  
          * Borrow and object from the pool, ignoring the key
 893  
          * 
 894  
          * @param key ignored
 895  
          * @return newly created object instance
 896  
          */
 897  
         public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException {
 898  0
             return pool.borrowObject();
 899  
         }
 900  
 
 901  
         /**
 902  
          * Return and object to the pool, ignoring the key
 903  
          * 
 904  
          * @param key ignored
 905  
          * @param obj object to return
 906  
          */
 907  
         public void returnObject(final Object key, final Object obj) {
 908  
             try {
 909  0
                 pool.returnObject(obj);
 910  0
             } catch (Exception e) {
 911  
                 // swallowed as of Pool 2
 912  0
             }
 913  0
         }
 914  
 
 915  
         /**
 916  
          * Invalidate and object, ignoring the key
 917  
          * 
 918  
          * @param obj object to invalidate
 919  
          * @param key ignored
 920  
          */
 921  
         public void invalidateObject(final Object key, final Object obj) {
 922  
             try {
 923  0
                 pool.invalidateObject(obj);
 924  0
             } catch (Exception e) {
 925  
                 // swallowed as of Pool 2
 926  0
             }
 927  0
         }
 928  
 
 929  
         /**
 930  
          * Add an object to the pool, ignoring the key
 931  
          * 
 932  
          * @param key ignored
 933  
          */
 934  
         public void addObject(final Object key) throws Exception, IllegalStateException {
 935  0
             pool.addObject();
 936  0
         }
 937  
 
 938  
         /**
 939  
          * Return the number of objects idle in the pool, ignoring the key.
 940  
          * 
 941  
          * @param key ignored
 942  
          * @return idle instance count
 943  
          */
 944  
         public int getNumIdle(final Object key) throws UnsupportedOperationException {
 945  0
             return pool.getNumIdle();
 946  
         }
 947  
 
 948  
         /**
 949  
          * Return the number of objects checked out from the pool, ignoring the key.
 950  
          * 
 951  
          * @param key ignored
 952  
          * @return active instance count
 953  
          */
 954  
         public int getNumActive(final Object key) throws UnsupportedOperationException {
 955  0
             return pool.getNumActive();
 956  
         }
 957  
 
 958  
         /**
 959  
          * {@inheritDoc}
 960  
          */
 961  
         public int getNumIdle() throws UnsupportedOperationException {
 962  0
             return pool.getNumIdle();
 963  
         }
 964  
 
 965  
         /**
 966  
          * {@inheritDoc}
 967  
          */
 968  
         public int getNumActive() throws UnsupportedOperationException {
 969  0
             return pool.getNumActive();
 970  
         }
 971  
 
 972  
         /**
 973  
          * {@inheritDoc}
 974  
          */
 975  
         public void clear() throws Exception, UnsupportedOperationException {
 976  0
             pool.clear();
 977  0
         }
 978  
 
 979  
         /**
 980  
          * Clear the pool, ignoring the key (has same effect as {@link #clear()}.
 981  
          * 
 982  
          * @param key ignored.
 983  
          */
 984  
         public void clear(final Object key) throws Exception, UnsupportedOperationException {
 985  0
             pool.clear();
 986  0
         }
 987  
 
 988  
         /**
 989  
          * {@inheritDoc}
 990  
          */
 991  
         public void close() {
 992  
             try {
 993  0
                 pool.close();
 994  0
             } catch (Exception e) {
 995  
                 // swallowed as of Pool 2
 996  0
             }
 997  0
         }
 998  
 
 999  
         /**
 1000  
          * Sets the factory used to manage objects.
 1001  
          * 
 1002  
          * @param factory new factory to use managing object instances
 1003  
          * @deprecated to be removed in version 2.0
 1004  
          */
 1005  
         public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
 1006  0
             pool.setFactory(adapt(factory));
 1007  0
         }
 1008  
 
 1009  
         /**
 1010  
          * {@inheritDoc}
 1011  
          */
 1012  
         public String toString() {
 1013  0
             final StringBuffer sb = new StringBuffer();
 1014  0
             sb.append("KeyedObjectPoolAdaptor");
 1015  0
             sb.append("{pool=").append(pool);
 1016  0
             sb.append('}');
 1017  0
             return sb.toString();
 1018  
         }
 1019  
     }
 1020  
 
 1021  
     /**
 1022  
      * An object pool that performs type checking on objects passed
 1023  
      * to pool methods.
 1024  
      *
 1025  
      */
 1026  
     private static class CheckedObjectPool implements ObjectPool {
 1027  
         /** 
 1028  
          * Type of objects allowed in the pool. This should be a subtype of the return type of
 1029  
          * the underlying pool's associated object factory.
 1030  
          */
 1031  
         private final Class type;
 1032  
        
 1033  
         /** Underlying object pool */
 1034  
         private final ObjectPool pool;
 1035  
 
 1036  
         /**
 1037  
          * Create a CheckedObjectPool accepting objects of the given type using
 1038  
          * the given pool.
 1039  
          * 
 1040  
          * @param pool underlying object pool
 1041  
          * @param type expected pooled object type
 1042  
          * @throws IllegalArgumentException if either parameter is null
 1043  
          */
 1044  0
         CheckedObjectPool(final ObjectPool pool, final Class type) {
 1045  0
             if (pool == null) {
 1046  0
                 throw new IllegalArgumentException("pool must not be null.");
 1047  
             }
 1048  0
             if (type == null) {
 1049  0
                 throw new IllegalArgumentException("type must not be null.");
 1050  
             }
 1051  0
             this.pool = pool;
 1052  0
             this.type = type;
 1053  0
         }
 1054  
 
 1055  
         /**
 1056  
          * Borrow an object from the pool, checking its type.
 1057  
          * 
 1058  
          * @return a type-checked object from the pool
 1059  
          * @throws ClassCastException if the object returned by the pool is not of the expected type
 1060  
          */
 1061  
         public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
 1062  0
             final Object obj = pool.borrowObject();
 1063  0
             if (type.isInstance(obj)) {
 1064  0
                 return obj;
 1065  
             } else {
 1066  0
                 throw new ClassCastException("Borrowed object is not of type: " + type.getName() + " was: " + obj);
 1067  
             }
 1068  
         }
 1069  
 
 1070  
         /**
 1071  
          * Return an object to the pool, verifying that it is of the correct type.
 1072  
          * 
 1073  
          * @param obj object to return
 1074  
          * @throws ClassCastException if obj is not of the expected type
 1075  
          */
 1076  
         public void returnObject(final Object obj) {
 1077  0
             if (type.isInstance(obj)) {
 1078  
                 try {
 1079  0
                     pool.returnObject(obj);
 1080  0
                 } catch (Exception e) {
 1081  
                     // swallowed as of Pool 2
 1082  0
                 }
 1083  
             } else {
 1084  0
                 throw new ClassCastException("Returned object is not of type: " + type.getName() + " was: " + obj);
 1085  
             }
 1086  0
         }
 1087  
 
 1088  
         /**
 1089  
          * Invalidates an object from the pool, verifying that it is of the expected type.
 1090  
          * 
 1091  
          * @param obj object to invalidate
 1092  
          * @throws ClassCastException if obj is not of the expected type
 1093  
          */
 1094  
         public void invalidateObject(final Object obj) {
 1095  0
             if (type.isInstance(obj)) {
 1096  
                 try {
 1097  0
                     pool.invalidateObject(obj);
 1098  0
                 } catch (Exception e) {
 1099  
                     // swallowed as of Pool 2
 1100  0
                 }
 1101  
             } else {
 1102  0
                 throw new ClassCastException("Invalidated object is not of type: " + type.getName() + " was: " + obj);
 1103  
             }
 1104  0
         }
 1105  
 
 1106  
         /**
 1107  
          * {@inheritDoc}
 1108  
          */
 1109  
         public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {
 1110  0
             pool.addObject();
 1111  0
         }
 1112  
 
 1113  
         /**
 1114  
          * {@inheritDoc}
 1115  
          */
 1116  
         public int getNumIdle() throws UnsupportedOperationException {
 1117  0
             return pool.getNumIdle();
 1118  
         }
 1119  
 
 1120  
         /**
 1121  
          * {@inheritDoc}
 1122  
          */
 1123  
         public int getNumActive() throws UnsupportedOperationException {
 1124  0
             return pool.getNumActive();
 1125  
         }
 1126  
 
 1127  
         /**
 1128  
          * {@inheritDoc}
 1129  
          */
 1130  
         public void clear() throws Exception, UnsupportedOperationException {
 1131  0
             pool.clear();
 1132  0
         }
 1133  
 
 1134  
         /**
 1135  
          * {@inheritDoc}
 1136  
          */
 1137  
         public void close() {
 1138  
             try {
 1139  0
                 pool.close();
 1140  0
             } catch (Exception e) {
 1141  
                 // swallowed as of Pool 2
 1142  0
             }
 1143  0
         }
 1144  
 
 1145  
         /**
 1146  
          * Sets the object factory associated with the pool
 1147  
          * 
 1148  
          * @param factory object factory
 1149  
          * @deprecated to be removed in version 2.0
 1150  
          */
 1151  
         public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
 1152  0
             pool.setFactory(factory);
 1153  0
         }
 1154  
 
 1155  
         /**
 1156  
          * {@inheritDoc}
 1157  
          */
 1158  
         public String toString() {
 1159  0
             final StringBuffer sb = new StringBuffer();
 1160  0
             sb.append("CheckedObjectPool");
 1161  0
             sb.append("{type=").append(type);
 1162  0
             sb.append(", pool=").append(pool);
 1163  0
             sb.append('}');
 1164  0
             return sb.toString();
 1165  
         }
 1166  
     }
 1167  
 
 1168  
     /**
 1169  
      * A keyed object pool that performs type checking on objects passed
 1170  
      * to pool methods.
 1171  
      *
 1172  
      */
 1173  
     private static class CheckedKeyedObjectPool implements KeyedObjectPool {
 1174  
         /** 
 1175  
          * Expected type of objects managed by the pool.  This should be
 1176  
          * a subtype of the return type of the object factory used by the pool.
 1177  
          */
 1178  
         private final Class type;
 1179  
         
 1180  
         /** Underlying pool */
 1181  
         private final KeyedObjectPool keyedPool;
 1182  
 
 1183  
         /**
 1184  
          * Create a new CheckedKeyedObjectPool from the given pool with given expected object type.
 1185  
          * 
 1186  
          * @param keyedPool underlying pool
 1187  
          * @param type expected object type
 1188  
          * @throws IllegalArgumentException if either parameter is null
 1189  
          */
 1190  0
         CheckedKeyedObjectPool(final KeyedObjectPool keyedPool, final Class type) {
 1191  0
             if (keyedPool == null) {
 1192  0
                 throw new IllegalArgumentException("keyedPool must not be null.");
 1193  
             }
 1194  0
             if (type == null) {
 1195  0
                 throw new IllegalArgumentException("type must not be null.");
 1196  
             }
 1197  0
             this.keyedPool = keyedPool;
 1198  0
             this.type = type;
 1199  0
         }
 1200  
 
 1201  
         /**
 1202  
          * Borrow an object from the pool, verifying correct return type.
 1203  
          * 
 1204  
          * @param key pool key
 1205  
          * @return type-checked object from the pool under the given key
 1206  
          * @throws ClassCastException if the object returned by the pool is not of the expected type
 1207  
          */
 1208  
         public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException {
 1209  0
             Object obj = keyedPool.borrowObject(key);
 1210  0
             if (type.isInstance(obj)) {
 1211  0
                 return obj;
 1212  
             } else {
 1213  0
                 throw new ClassCastException("Borrowed object for key: " + key + " is not of type: " + type.getName() + " was: " + obj);
 1214  
             }
 1215  
         }
 1216  
 
 1217  
         /**
 1218  
          * Return an object to the pool, checking its type.
 1219  
          * 
 1220  
          * @param key the associated key (not type-checked)
 1221  
          * @param obj the object to return (type-checked)
 1222  
          * @throws ClassCastException if obj is not of the expected type
 1223  
          */
 1224  
         public void returnObject(final Object key, final Object obj) {
 1225  0
             if (type.isInstance(obj)) {
 1226  
                 try {
 1227  0
                     keyedPool.returnObject(key, obj);
 1228  0
                 } catch (Exception e) {
 1229  
                     // swallowed as of Pool 2
 1230  0
                 }
 1231  
             } else {
 1232  0
                 throw new ClassCastException("Returned object for key: " + key + " is not of type: " + type.getName() + " was: " + obj);
 1233  
             }
 1234  0
         }
 1235  
 
 1236  
         /**
 1237  
          * Invalidate an object to the pool, checking its type.
 1238  
          * 
 1239  
          * @param key the associated key (not type-checked)
 1240  
          * @param obj the object to return (type-checked)
 1241  
          * @throws ClassCastException if obj is not of the expected type
 1242  
          */
 1243  
         public void invalidateObject(final Object key, final Object obj) {
 1244  0
             if (type.isInstance(obj)) {
 1245  
                 try {
 1246  0
                     keyedPool.invalidateObject(key, obj);
 1247  0
                 } catch (Exception e) {
 1248  
                     // swallowed as of Pool 2
 1249  0
                 }
 1250  
             } else {
 1251  0
                 throw new ClassCastException("Invalidated object for key: " + key + " is not of type: " + type.getName() + " was: " + obj);
 1252  
             }
 1253  0
         }
 1254  
 
 1255  
         /**
 1256  
          * {@inheritDoc}
 1257  
          */
 1258  
         public void addObject(final Object key) throws Exception, IllegalStateException, UnsupportedOperationException {
 1259  0
             keyedPool.addObject(key);
 1260  0
         }
 1261  
         
 1262  
         /**
 1263  
          * {@inheritDoc}
 1264  
          */
 1265  
         public int getNumIdle(final Object key) throws UnsupportedOperationException {
 1266  0
             return keyedPool.getNumIdle(key);
 1267  
         }
 1268  
 
 1269  
         /**
 1270  
          * {@inheritDoc}
 1271  
          */
 1272  
         public int getNumActive(final Object key) throws UnsupportedOperationException {
 1273  0
             return keyedPool.getNumActive(key);
 1274  
         }
 1275  
 
 1276  
         /**
 1277  
          * {@inheritDoc}
 1278  
          */
 1279  
         public int getNumIdle() throws UnsupportedOperationException {
 1280  0
             return keyedPool.getNumIdle();
 1281  
         }
 1282  
 
 1283  
         /**
 1284  
          * {@inheritDoc}
 1285  
          */
 1286  
         public int getNumActive() throws UnsupportedOperationException {
 1287  0
             return keyedPool.getNumActive();
 1288  
         }
 1289  
 
 1290  
         /**
 1291  
          * {@inheritDoc}
 1292  
          */
 1293  
         public void clear() throws Exception, UnsupportedOperationException {
 1294  0
             keyedPool.clear();
 1295  0
         }
 1296  
 
 1297  
         /**
 1298  
          * {@inheritDoc}
 1299  
          */
 1300  
         public void clear(final Object key) throws Exception, UnsupportedOperationException {
 1301  0
             keyedPool.clear(key);
 1302  0
         }
 1303  
 
 1304  
         /**
 1305  
          * {@inheritDoc}
 1306  
          */
 1307  
         public void close() {
 1308  
             try {
 1309  0
                 keyedPool.close();
 1310  0
             } catch (Exception e) {
 1311  
                 // swallowed as of Pool 2
 1312  0
             }
 1313  0
         }
 1314  
 
 1315  
         /**
 1316  
          * Sets the object factory associated with the pool
 1317  
          * 
 1318  
          * @param factory object factory
 1319  
          * @deprecated to be removed in version 2.0
 1320  
          */
 1321  
         public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
 1322  0
             keyedPool.setFactory(factory);
 1323  0
         }
 1324  
 
 1325  
         /**
 1326  
          * {@inheritDoc}
 1327  
          */
 1328  
         public String toString() {
 1329  0
             final StringBuffer sb = new StringBuffer();
 1330  0
             sb.append("CheckedKeyedObjectPool");
 1331  0
             sb.append("{type=").append(type);
 1332  0
             sb.append(", keyedPool=").append(keyedPool);
 1333  0
             sb.append('}');
 1334  0
             return sb.toString();
 1335  
         }
 1336  
     }
 1337  
 
 1338  
     /**
 1339  
      * Timer task that adds objects to the pool until the number of idle
 1340  
      * instances reaches the configured minIdle.  Note that this is not the
 1341  
      * same as the pool's minIdle setting.
 1342  
      * 
 1343  
      */
 1344  
     private static class ObjectPoolMinIdleTimerTask extends TimerTask {
 1345  
         
 1346  
         /** Minimum number of idle instances.  Not the same as pool.getMinIdle(). */
 1347  
         private final int minIdle;
 1348  
         
 1349  
         /** Object pool */
 1350  
         private final ObjectPool pool;
 1351  
 
 1352  
         /**
 1353  
          * Create a new ObjectPoolMinIdleTimerTask for the given pool with the given minIdle setting.
 1354  
          * 
 1355  
          * @param pool object pool
 1356  
          * @param minIdle number of idle instances to maintain
 1357  
          * @throws IllegalArgumentException if the pool is null
 1358  
          */
 1359  0
         ObjectPoolMinIdleTimerTask(final ObjectPool pool, final int minIdle) throws IllegalArgumentException {
 1360  0
             if (pool == null) {
 1361  0
                 throw new IllegalArgumentException("pool must not be null.");
 1362  
             }
 1363  0
             this.pool = pool;
 1364  0
             this.minIdle = minIdle;
 1365  0
         }
 1366  
 
 1367  
         /**
 1368  
          * {@inheritDoc}
 1369  
          */
 1370  
         public void run() {
 1371  0
             boolean success = false;
 1372  
             try {
 1373  0
                 if (pool.getNumIdle() < minIdle) {
 1374  0
                     pool.addObject();
 1375  
                 }
 1376  0
                 success = true;
 1377  
 
 1378  0
             } catch (Exception e) {
 1379  0
                 cancel();
 1380  
 
 1381  
             } finally {
 1382  
                 // detect other types of Throwable and cancel this Timer
 1383  0
                 if (!success) {
 1384  0
                     cancel();
 1385  
                 }
 1386  
             }
 1387  0
         }
 1388  
 
 1389  
         /**
 1390  
          * {@inheritDoc}
 1391  
          */
 1392  
         public String toString() {
 1393  0
             final StringBuffer sb = new StringBuffer();
 1394  0
             sb.append("ObjectPoolMinIdleTimerTask");
 1395  0
             sb.append("{minIdle=").append(minIdle);
 1396  0
             sb.append(", pool=").append(pool);
 1397  0
             sb.append('}');
 1398  0
             return sb.toString();
 1399  
         }
 1400  
     }
 1401  
 
 1402  
     /**
 1403  
      * Timer task that adds objects to the pool until the number of idle
 1404  
      * instances for the given key reaches the configured minIdle.  Note that this is not the
 1405  
      * same as the pool's minIdle setting.
 1406  
      * 
 1407  
      */
 1408  
     private static class KeyedObjectPoolMinIdleTimerTask extends TimerTask {
 1409  
         /** Minimum number of idle instances.  Not the same as pool.getMinIdle(). */
 1410  
         private final int minIdle;
 1411  
         
 1412  
         /** Key to ensure minIdle for */
 1413  
         private final Object key;
 1414  
         
 1415  
         /** Keyed object pool */
 1416  
         private final KeyedObjectPool keyedPool;
 1417  
 
 1418  
         /**
 1419  
          * Create a new KeyedObjecPoolMinIdleTimerTask.
 1420  
          * 
 1421  
          * @param keyedPool keyed object pool
 1422  
          * @param key key to ensure minimum number of idle instances
 1423  
          * @param minIdle minimum number of idle instances 
 1424  
          * @throws IllegalArgumentException if the key is null
 1425  
          */
 1426  0
         KeyedObjectPoolMinIdleTimerTask(final KeyedObjectPool keyedPool, final Object key, final int minIdle) throws IllegalArgumentException {
 1427  0
             if (keyedPool == null) {
 1428  0
                 throw new IllegalArgumentException("keyedPool must not be null.");
 1429  
             }
 1430  0
             this.keyedPool = keyedPool;
 1431  0
             this.key = key;
 1432  0
             this.minIdle = minIdle;
 1433  0
         }
 1434  
 
 1435  
         /**
 1436  
          * {@inheritDoc}
 1437  
          */
 1438  
         public void run() {
 1439  0
             boolean success = false;
 1440  
             try {
 1441  0
                 if (keyedPool.getNumIdle(key) < minIdle) {
 1442  0
                     keyedPool.addObject(key);
 1443  
                 }
 1444  0
                 success = true;
 1445  
 
 1446  0
             } catch (Exception e) {
 1447  0
                 cancel();
 1448  
 
 1449  
             } finally {
 1450  
                 // detect other types of Throwable and cancel this Timer
 1451  0
                 if (!success) {
 1452  0
                     cancel();
 1453  
                 }
 1454  
             }
 1455  0
         }
 1456  
 
 1457  
         /**
 1458  
          * {@inheritDoc}
 1459  
          */
 1460  
         public String toString() {
 1461  0
             final StringBuffer sb = new StringBuffer();
 1462  0
             sb.append("KeyedObjectPoolMinIdleTimerTask");
 1463  0
             sb.append("{minIdle=").append(minIdle);
 1464  0
             sb.append(", key=").append(key);
 1465  0
             sb.append(", keyedPool=").append(keyedPool);
 1466  0
             sb.append('}');
 1467  0
             return sb.toString();
 1468  
         }
 1469  
     }
 1470  
 
 1471  
     /**
 1472  
      * A synchronized (thread-safe) ObjectPool backed by the specified ObjectPool.
 1473  
      *
 1474  
      * <p><b>Note:</b>
 1475  
      * This should not be used on pool implementations that already provide proper synchronization
 1476  
      * such as the pools provided in the Commons Pool library. Wrapping a pool that
 1477  
      * {@link #wait() waits} for poolable objects to be returned before allowing another one to be
 1478  
      * borrowed with another layer of synchronization will cause liveliness issues or a deadlock.
 1479  
      * </p>
 1480  
      */
 1481  
     private static class SynchronizedObjectPool implements ObjectPool {
 1482  
         
 1483  
         /** Object whose monitor is used to synchronize methods on the wrapped pool. */
 1484  
         private final Object lock;
 1485  
         
 1486  
         /** the underlying object pool */
 1487  
         private final ObjectPool pool;
 1488  
 
 1489  
         /**
 1490  
          * Create a new SynchronizedObjectPool wrapping the given pool.
 1491  
          * 
 1492  
          * @param pool the ObjectPool to be "wrapped" in a synchronized ObjectPool.
 1493  
          * @throws IllegalArgumentException if the pool is null
 1494  
          */
 1495  0
         SynchronizedObjectPool(final ObjectPool pool) throws IllegalArgumentException {
 1496  0
             if (pool == null) {
 1497  0
                 throw new IllegalArgumentException("pool must not be null.");
 1498  
             }
 1499  0
             this.pool = pool;
 1500  0
             lock = new Object();
 1501  0
         }
 1502  
 
 1503  
         /**
 1504  
          * {@inheritDoc}
 1505  
          */
 1506  
         public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
 1507  0
             synchronized (lock) {
 1508  0
                 return pool.borrowObject();
 1509  0
             }
 1510  
         }
 1511  
 
 1512  
         /**
 1513  
          * {@inheritDoc}
 1514  
          */
 1515  
         public void returnObject(final Object obj) {
 1516  0
             synchronized (lock) {
 1517  
                 try {
 1518  0
                     pool.returnObject(obj);
 1519  0
                 } catch (Exception e) {
 1520  
                     // swallowed as of Pool 2
 1521  0
                 }
 1522  0
             }
 1523  0
         }
 1524  
 
 1525  
         /**
 1526  
          * {@inheritDoc}
 1527  
          */
 1528  
         public void invalidateObject(final Object obj) {
 1529  0
             synchronized (lock) {
 1530  
                 try {
 1531  0
                     pool.invalidateObject(obj);
 1532  0
                 } catch (Exception e) {
 1533  
                     // swallowed as of Pool 2
 1534  0
                 }
 1535  0
             }
 1536  0
         }
 1537  
 
 1538  
         /**
 1539  
          * {@inheritDoc}
 1540  
          */
 1541  
         public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {
 1542  0
             synchronized (lock) {
 1543  0
                 pool.addObject();
 1544  0
             }
 1545  0
         }
 1546  
 
 1547  
         /**
 1548  
          * {@inheritDoc}
 1549  
          */
 1550  
         public int getNumIdle() throws UnsupportedOperationException {
 1551  0
             synchronized (lock) {
 1552  0
                 return pool.getNumIdle();
 1553  0
             }
 1554  
         }
 1555  
 
 1556  
         /**
 1557  
          * {@inheritDoc}
 1558  
          */
 1559  
         public int getNumActive() throws UnsupportedOperationException {
 1560  0
             synchronized (lock) {
 1561  0
                 return pool.getNumActive();
 1562  0
             }
 1563  
         }
 1564  
 
 1565  
         /**
 1566  
          * {@inheritDoc}
 1567  
          */
 1568  
         public void clear() throws Exception, UnsupportedOperationException {
 1569  0
             synchronized (lock) {
 1570  0
                 pool.clear();
 1571  0
             }
 1572  0
         }
 1573  
 
 1574  
         /**
 1575  
          * {@inheritDoc}
 1576  
          */
 1577  
         public void close() {
 1578  
             try {
 1579  0
                 synchronized (lock) {
 1580  0
                     pool.close();
 1581  0
                 }
 1582  0
             } catch (Exception e) {
 1583  
                 // swallowed as of Pool 2
 1584  0
             }
 1585  0
         }
 1586  
 
 1587  
         /**
 1588  
          * Sets the factory used by the pool.
 1589  
          * 
 1590  
          * @param factory new PoolableObjectFactory
 1591  
          * @deprecated to be removed in pool 2.0
 1592  
          */
 1593  
         public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
 1594  0
             synchronized (lock) {
 1595  0
                 pool.setFactory(factory);
 1596  0
             }
 1597  0
         }
 1598  
 
 1599  
         /**
 1600  
          * {@inheritDoc}
 1601  
          */
 1602  
         public String toString() {
 1603  0
             final StringBuffer sb = new StringBuffer();
 1604  0
             sb.append("SynchronizedObjectPool");
 1605  0
             sb.append("{pool=").append(pool);
 1606  0
             sb.append('}');
 1607  0
             return sb.toString();
 1608  
         }
 1609  
     }
 1610  
 
 1611  
     /**
 1612  
      * A synchronized (thread-safe) KeyedObjectPool backed by the specified KeyedObjectPool.
 1613  
      *
 1614  
      * <p><b>Note:</b>
 1615  
      * This should not be used on pool implementations that already provide proper synchronization
 1616  
      * such as the pools provided in the Commons Pool library. Wrapping a pool that
 1617  
      * {@link #wait() waits} for poolable objects to be returned before allowing another one to be
 1618  
      * borrowed with another layer of synchronization will cause liveliness issues or a deadlock.
 1619  
      * </p>
 1620  
      */
 1621  
     private static class SynchronizedKeyedObjectPool implements KeyedObjectPool {
 1622  
         
 1623  
         /** Object whose monitor is used to synchronize methods on the wrapped pool. */
 1624  
         private final Object lock;
 1625  
         
 1626  
         /** Underlying object pool */
 1627  
         private final KeyedObjectPool keyedPool;
 1628  
 
 1629  
         /**
 1630  
          * Create a new SynchronizedKeyedObjectPool wrapping the given pool
 1631  
          * 
 1632  
          * @param keyedPool KeyedObjectPool to wrap
 1633  
          * @throws IllegalArgumentException if keyedPool is null
 1634  
          */
 1635  0
         SynchronizedKeyedObjectPool(final KeyedObjectPool keyedPool) throws IllegalArgumentException {
 1636  0
             if (keyedPool == null) {
 1637  0
                 throw new IllegalArgumentException("keyedPool must not be null.");
 1638  
             }
 1639  0
             this.keyedPool = keyedPool;
 1640  0
             lock = new Object();
 1641  0
         }
 1642  
 
 1643  
         /**
 1644  
          * {@inheritDoc}
 1645  
          */
 1646  
         public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException {
 1647  0
             synchronized (lock) {
 1648  0
                 return keyedPool.borrowObject(key);
 1649  0
             }
 1650  
         }
 1651  
 
 1652  
         /**
 1653  
          * {@inheritDoc}
 1654  
          */
 1655  
         public void returnObject(final Object key, final Object obj) {
 1656  0
             synchronized (lock) {
 1657  
                 try {
 1658  0
                     keyedPool.returnObject(key, obj);
 1659  0
                 } catch (Exception e) {
 1660  
                     // swallowed
 1661  0
                 }
 1662  0
             }
 1663  0
         }
 1664  
 
 1665  
         /**
 1666  
          * {@inheritDoc}
 1667  
          */
 1668  
         public void invalidateObject(final Object key, final Object obj) {
 1669  0
             synchronized (lock) {
 1670  
                 try {
 1671  0
                     keyedPool.invalidateObject(key, obj);
 1672  0
                 } catch (Exception e) {
 1673  
                     // swallowed as of Pool 2
 1674  0
                 }
 1675  0
             }
 1676  0
         }
 1677  
 
 1678  
         /**
 1679  
          * {@inheritDoc}
 1680  
          */
 1681  
         public void addObject(final Object key) throws Exception, IllegalStateException, UnsupportedOperationException {
 1682  0
             synchronized (lock) {
 1683  0
                 keyedPool.addObject(key);
 1684  0
             }
 1685  0
         }
 1686  
 
 1687  
         /**
 1688  
          * {@inheritDoc}
 1689  
          */
 1690  
         public int getNumIdle(final Object key) throws UnsupportedOperationException {
 1691  0
             synchronized (lock) {
 1692  0
                 return keyedPool.getNumIdle(key);
 1693  0
             }
 1694  
         }
 1695  
 
 1696  
         /**
 1697  
          * {@inheritDoc}
 1698  
          */
 1699  
         public int getNumActive(final Object key) throws UnsupportedOperationException {
 1700  0
             synchronized (lock) {
 1701  0
                 return keyedPool.getNumActive(key);
 1702  0
             }
 1703  
         }
 1704  
 
 1705  
         /**
 1706  
          * {@inheritDoc}
 1707  
          */
 1708  
         public int getNumIdle() throws UnsupportedOperationException {
 1709  0
             synchronized (lock) {
 1710  0
                 return keyedPool.getNumIdle();
 1711  0
             }
 1712  
         }
 1713  
 
 1714  
         /**
 1715  
          * {@inheritDoc}
 1716  
          */
 1717  
         public int getNumActive() throws UnsupportedOperationException {
 1718  0
             synchronized (lock) {
 1719  0
                 return keyedPool.getNumActive();
 1720  0
             }
 1721  
         }
 1722  
 
 1723  
         /**
 1724  
          * {@inheritDoc}
 1725  
          */
 1726  
         public void clear() throws Exception, UnsupportedOperationException {
 1727  0
             synchronized (lock) {
 1728  0
                 keyedPool.clear();
 1729  0
             }
 1730  0
         }
 1731  
 
 1732  
         /**
 1733  
          * {@inheritDoc}
 1734  
          */
 1735  
         public void clear(final Object key) throws Exception, UnsupportedOperationException {
 1736  0
             synchronized (lock) {
 1737  0
                 keyedPool.clear(key);
 1738  0
             }
 1739  0
         }
 1740  
 
 1741  
         /**
 1742  
          * {@inheritDoc}
 1743  
          */
 1744  
         public void close() {
 1745  
             try {
 1746  0
                 synchronized (lock) {
 1747  0
                     keyedPool.close();
 1748  0
                 }
 1749  0
             } catch (Exception e) {
 1750  
                 // swallowed as of Pool 2
 1751  0
             }
 1752  0
         }
 1753  
 
 1754  
         /**
 1755  
          * Sets the object factory used by the pool.
 1756  
          * 
 1757  
          * @param factory KeyedPoolableObjectFactory used by the pool
 1758  
          * @deprecated to be removed in pool 2.0
 1759  
          */
 1760  
         public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
 1761  0
             synchronized (lock) {
 1762  0
                 keyedPool.setFactory(factory);
 1763  0
             }
 1764  0
         }
 1765  
 
 1766  
         /**
 1767  
          * {@inheritDoc}
 1768  
          */
 1769  
         public String toString() {
 1770  0
             final StringBuffer sb = new StringBuffer();
 1771  0
             sb.append("SynchronizedKeyedObjectPool");
 1772  0
             sb.append("{keyedPool=").append(keyedPool);
 1773  0
             sb.append('}');
 1774  0
             return sb.toString();
 1775  
         }
 1776  
     }
 1777  
 
 1778  
     /**
 1779  
      * A fully synchronized PoolableObjectFactory that wraps a PoolableObjectFactory and synchronizes
 1780  
      * access to the wrapped factory methods.
 1781  
      *
 1782  
      * <p><b>Note:</b>
 1783  
      * This should not be used on pool implementations that already provide proper synchronization
 1784  
      * such as the pools provided in the Commons Pool library. </p>
 1785  
      */
 1786  
     private static class SynchronizedPoolableObjectFactory implements PoolableObjectFactory {
 1787  
         /** Synchronization lock */
 1788  
         private final Object lock;
 1789  
         
 1790  
         /** Wrapped factory */
 1791  
         private final PoolableObjectFactory factory;
 1792  
 
 1793  
         /** 
 1794  
          * Create a SynchronizedPoolableObjectFactory wrapping the given factory.
 1795  
          * 
 1796  
          * @param factory underlying factory to wrap
 1797  
          * @throws IllegalArgumentException if the factory is null
 1798  
          */
 1799  0
         SynchronizedPoolableObjectFactory(final PoolableObjectFactory factory) throws IllegalArgumentException {
 1800  0
             if (factory == null) {
 1801  0
                 throw new IllegalArgumentException("factory must not be null.");
 1802  
             }
 1803  0
             this.factory = factory;
 1804  0
             lock = new Object();
 1805  0
         }
 1806  
 
 1807  
         /**
 1808  
          * {@inheritDoc}
 1809  
          */
 1810  
         public Object makeObject() throws Exception {
 1811  0
             synchronized (lock) {
 1812  0
                 return factory.makeObject();
 1813  0
             }
 1814  
         }
 1815  
 
 1816  
         /**
 1817  
          * {@inheritDoc}
 1818  
          */
 1819  
         public void destroyObject(final Object obj) throws Exception {
 1820  0
             synchronized (lock) {
 1821  0
                 factory.destroyObject(obj);
 1822  0
             }
 1823  0
         }
 1824  
 
 1825  
         /**
 1826  
          * {@inheritDoc}
 1827  
          */
 1828  
         public boolean validateObject(final Object obj) {
 1829  0
             synchronized (lock) {
 1830  0
                 return factory.validateObject(obj);
 1831  0
             }
 1832  
         }
 1833  
 
 1834  
         /**
 1835  
          * {@inheritDoc}
 1836  
          */
 1837  
         public void activateObject(final Object obj) throws Exception {
 1838  0
             synchronized (lock) {
 1839  0
                 factory.activateObject(obj);
 1840  0
             }
 1841  0
         }
 1842  
 
 1843  
         /**
 1844  
          * {@inheritDoc}
 1845  
          */
 1846  
         public void passivateObject(final Object obj) throws Exception {
 1847  0
             synchronized (lock) {
 1848  0
                 factory.passivateObject(obj);
 1849  0
             }
 1850  0
         }
 1851  
 
 1852  
         /**
 1853  
          * {@inheritDoc}
 1854  
          */
 1855  
         public String toString() {
 1856  0
             final StringBuffer sb = new StringBuffer();
 1857  0
             sb.append("SynchronizedPoolableObjectFactory");
 1858  0
             sb.append("{factory=").append(factory);
 1859  0
             sb.append('}');
 1860  0
             return sb.toString();
 1861  
         }
 1862  
     }
 1863  
 
 1864  
     /**
 1865  
      * A fully synchronized KeyedPoolableObjectFactory that wraps a KeyedPoolableObjectFactory and synchronizes
 1866  
      * access to the wrapped factory methods.
 1867  
      *
 1868  
      * <p><b>Note:</b>
 1869  
      * This should not be used on pool implementations that already provide proper synchronization
 1870  
      * such as the pools provided in the Commons Pool library. </p>
 1871  
      */
 1872  
     private static class SynchronizedKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory {
 1873  
         /** Synchronization lock */
 1874  
         private final Object lock;
 1875  
         
 1876  
         /** Wrapped factory */
 1877  
         private final KeyedPoolableObjectFactory keyedFactory;
 1878  
 
 1879  
         /** 
 1880  
          * Create a SynchronizedKeyedPoolableObjectFactory wrapping the given factory.
 1881  
          * 
 1882  
          * @param keyedFactory underlying factory to wrap
 1883  
          * @throws IllegalArgumentException if the factory is null
 1884  
          */
 1885  0
         SynchronizedKeyedPoolableObjectFactory(final KeyedPoolableObjectFactory keyedFactory) throws IllegalArgumentException {
 1886  0
             if (keyedFactory == null) {
 1887  0
                 throw new IllegalArgumentException("keyedFactory must not be null.");
 1888  
             }
 1889  0
             this.keyedFactory = keyedFactory;
 1890  0
             lock = new Object();
 1891  0
         }
 1892  
 
 1893  
         /**
 1894  
          * {@inheritDoc}
 1895  
          */
 1896  
         public Object makeObject(final Object key) throws Exception {
 1897  0
             synchronized (lock) {
 1898  0
                 return keyedFactory.makeObject(key);
 1899  0
             }
 1900  
         }
 1901  
 
 1902  
         /**
 1903  
          * {@inheritDoc}
 1904  
          */
 1905  
         public void destroyObject(final Object key, final Object obj) throws Exception {
 1906  0
             synchronized (lock) {
 1907  0
                 keyedFactory.destroyObject(key, obj);
 1908  0
             }
 1909  0
         }
 1910  
 
 1911  
         /**
 1912  
          * {@inheritDoc}
 1913  
          */
 1914  
         public boolean validateObject(final Object key, final Object obj) {
 1915  0
             synchronized (lock) {
 1916  0
                 return keyedFactory.validateObject(key, obj);
 1917  0
             }
 1918  
         }
 1919  
 
 1920  
         /**
 1921  
          * {@inheritDoc}
 1922  
          */
 1923  
         public void activateObject(final Object key, final Object obj) throws Exception {
 1924  0
             synchronized (lock) {
 1925  0
                 keyedFactory.activateObject(key, obj);
 1926  0
             }
 1927  0
         }
 1928  
 
 1929  
         /**
 1930  
          * {@inheritDoc}
 1931  
          */
 1932  
         public void passivateObject(final Object key, final Object obj) throws Exception {
 1933  0
             synchronized (lock) {
 1934  0
                 keyedFactory.passivateObject(key, obj);
 1935  0
             }
 1936  0
         }
 1937  
 
 1938  
         /**
 1939  
          * {@inheritDoc}
 1940  
          */
 1941  
         public String toString() {
 1942  0
             final StringBuffer sb = new StringBuffer();
 1943  0
             sb.append("SynchronizedKeyedPoolableObjectFactory");
 1944  0
             sb.append("{keyedFactory=").append(keyedFactory);
 1945  0
             sb.append('}');
 1946  0
             return sb.toString();
 1947  
         }
 1948  
     }
 1949  
 
 1950  
     /**
 1951  
      * Encapsulate the logic for when the next poolable object should be discarded.
 1952  
      * Each time update is called, the next time to shrink is recomputed, based on
 1953  
      * the float factor, number of idle instances in the pool and high water mark.
 1954  
      * Float factor is assumed to be between 0 and 1.  Values closer to 1 cause
 1955  
      * less frequent erosion events.  Erosion event timing also depends on numIdle.
 1956  
      * When this value is relatively high (close to previously established high water
 1957  
      * mark), erosion occurs more frequently.
 1958  
      */
 1959  
     private static class ErodingFactor {
 1960  
         /** Determines frequency of "erosion" events */
 1961  
         private final float factor;
 1962  
         
 1963  
         /** Time of next shrink event */
 1964  
         private transient volatile long nextShrink;
 1965  
         
 1966  
         /** High water mark - largest numIdle encountered */
 1967  
         private transient volatile int idleHighWaterMark;
 1968  
 
 1969  
         /**
 1970  
          * Create a new ErodingFactor with the given erosion factor.
 1971  
          * 
 1972  
          * @param factor erosion factor
 1973  
          */
 1974  0
         public ErodingFactor(final float factor) {
 1975  0
             this.factor = factor;
 1976  0
             nextShrink = System.currentTimeMillis() + (long)(900000 * factor); // now + 15 min * factor
 1977  0
             idleHighWaterMark = 1;
 1978  0
         }
 1979  
 
 1980  
         /**
 1981  
          * Updates internal state based on numIdle and the current time.
 1982  
          * 
 1983  
          * @param numIdle number of idle elements in the pool
 1984  
          */
 1985  
         public void update(final int numIdle) {
 1986  0
             update(System.currentTimeMillis(), numIdle);
 1987  0
         }
 1988  
 
 1989  
         /**
 1990  
          * Updates internal state using the supplied time and numIdle.
 1991  
          * 
 1992  
          * @param now current time
 1993  
          * @param numIdle number of idle elements in the pool
 1994  
          */
 1995  
         public void update(final long now, final int numIdle) {
 1996  0
             final int idle = Math.max(0, numIdle);
 1997  0
             idleHighWaterMark = Math.max(idle, idleHighWaterMark);
 1998  0
             final float maxInterval = 15f;
 1999  0
             final float minutes = maxInterval + ((1f-maxInterval)/idleHighWaterMark) * idle;
 2000  0
             nextShrink = now + (long)(minutes * 60000f * factor);
 2001  0
         }
 2002  
 
 2003  
         /**
 2004  
          * Returns the time of the next erosion event.
 2005  
          * 
 2006  
          * @return next shrink time
 2007  
          */
 2008  
         public long getNextShrink() {
 2009  0
             return nextShrink;
 2010  
         }
 2011  
 
 2012  
         /**
 2013  
          * {@inheritDoc}
 2014  
          */
 2015  
         public String toString() {
 2016  0
             return "ErodingFactor{" +
 2017  
                     "factor=" + factor +
 2018  
                     ", idleHighWaterMark=" + idleHighWaterMark +
 2019  
                     '}';
 2020  
         }
 2021  
     }
 2022  
 
 2023  
     /**
 2024  
      * Decorates an object pool, adding "eroding" behavior.  Based on the
 2025  
      * configured {@link #factor erosion factor}, objects returning to the pool
 2026  
      * may be invalidated instead of being added to idle capacity.
 2027  
      *
 2028  
      */
 2029  
     private static class ErodingObjectPool implements ObjectPool {
 2030  
         /** Underlying object pool */
 2031  
         private final ObjectPool pool;
 2032  
         
 2033  
         /** Erosion factor */
 2034  
         private final ErodingFactor factor;
 2035  
 
 2036  
         /** 
 2037  
          * Create an ErodingObjectPool wrapping the given pool using the specified erosion factor.
 2038  
          * 
 2039  
          * @param pool underlying pool
 2040  
          * @param factor erosion factor - determines the frequency of erosion events
 2041  
          * @see #factor
 2042  
          */
 2043  0
         public ErodingObjectPool(final ObjectPool pool, final float factor) {
 2044  0
             this.pool = pool;
 2045  0
             this.factor = new ErodingFactor(factor);
 2046  0
         }
 2047  
 
 2048  
         /**
 2049  
          * {@inheritDoc}
 2050  
          */
 2051  
         public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
 2052  0
             return pool.borrowObject();
 2053  
         }
 2054  
 
 2055  
         /**
 2056  
          * Returns obj to the pool, unless erosion is triggered, in which
 2057  
          * case obj is invalidated.  Erosion is triggered when there are idle instances in 
 2058  
          * the pool and more than the {@link #factor erosion factor}-determined time has elapsed
 2059  
          * since the last returnObject activation. 
 2060  
          * 
 2061  
          * @param obj object to return or invalidate
 2062  
          * @see #factor
 2063  
          */
 2064  
         public void returnObject(final Object obj) {
 2065  0
             boolean discard = false;
 2066  0
             final long now = System.currentTimeMillis();
 2067  0
             synchronized (pool) {
 2068  0
                 if (factor.getNextShrink() < now) { // XXX: Pool 3: move test out of sync block
 2069  0
                     final int numIdle = pool.getNumIdle();
 2070  0
                     if (numIdle > 0) {
 2071  0
                         discard = true;
 2072  
                     }
 2073  
 
 2074  0
                     factor.update(now, numIdle);
 2075  
                 }
 2076  0
             }
 2077  
             try {
 2078  0
                 if (discard) {
 2079  0
                     pool.invalidateObject(obj);
 2080  
                 } else {
 2081  0
                     pool.returnObject(obj);
 2082  
                 }
 2083  0
             } catch (Exception e) {
 2084  
                 // swallowed
 2085  0
             }
 2086  0
         }
 2087  
 
 2088  
         /**
 2089  
          * {@inheritDoc}
 2090  
          */
 2091  
         public void invalidateObject(final Object obj) {
 2092  
             try {
 2093  0
                 pool.invalidateObject(obj);
 2094  0
             } catch (Exception e) {
 2095  
                 // swallowed
 2096  0
             }
 2097  0
         }
 2098  
 
 2099  
         /**
 2100  
          * {@inheritDoc}
 2101  
          */
 2102  
         public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {
 2103  0
             pool.addObject();
 2104  0
         }
 2105  
 
 2106  
         /**
 2107  
          * {@inheritDoc}
 2108  
          */
 2109  
         public int getNumIdle() throws UnsupportedOperationException {
 2110  0
             return pool.getNumIdle();
 2111  
         }
 2112  
 
 2113  
         /**
 2114  
          * {@inheritDoc}
 2115  
          */
 2116  
         public int getNumActive() throws UnsupportedOperationException {
 2117  0
             return pool.getNumActive();
 2118  
         }
 2119  
 
 2120  
         /**
 2121  
          * {@inheritDoc}
 2122  
          */
 2123  
         public void clear() throws Exception, UnsupportedOperationException {
 2124  0
             pool.clear();
 2125  0
         }
 2126  
 
 2127  
         /**
 2128  
          * {@inheritDoc}
 2129  
          */
 2130  
         public void close() {
 2131  
             try {
 2132  0
                 pool.close();
 2133  0
             } catch (Exception e) {
 2134  
                 // swallowed
 2135  0
             }
 2136  0
         }
 2137  
 
 2138  
         /**
 2139  
          * {@inheritDoc}
 2140  
          * @deprecated to be removed in pool 2.0
 2141  
          */
 2142  
         public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
 2143  0
             pool.setFactory(factory);
 2144  0
         }
 2145  
 
 2146  
         /**
 2147  
          * {@inheritDoc}
 2148  
          */
 2149  
         public String toString() {
 2150  0
             return "ErodingObjectPool{" +
 2151  
                     "factor=" + factor +
 2152  
                     ", pool=" + pool +
 2153  
                     '}';
 2154  
         }
 2155  
     }
 2156  
 
 2157  
     /**
 2158  
      * Decorates a keyed object pool, adding "eroding" behavior.  Based on the
 2159  
      * configured {@link #factor erosion factor}, objects returning to the pool
 2160  
      * may be invalidated instead of being added to idle capacity.
 2161  
      *
 2162  
      */
 2163  
     private static class ErodingKeyedObjectPool implements KeyedObjectPool {
 2164  
         /** Underlying pool */
 2165  
         private final KeyedObjectPool keyedPool;
 2166  
         
 2167  
         /** Erosion factor */
 2168  
         private final ErodingFactor erodingFactor;
 2169  
 
 2170  
         /** 
 2171  
          * Create an ErodingObjectPool wrapping the given pool using the specified erosion factor.
 2172  
          * 
 2173  
          * @param keyedPool underlying pool
 2174  
          * @param factor erosion factor - determines the frequency of erosion events
 2175  
          * @see #erodingFactor
 2176  
          */
 2177  
         public ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, final float factor) {
 2178  0
             this(keyedPool, new ErodingFactor(factor));
 2179  0
         }
 2180  
 
 2181  
         /** 
 2182  
          * Create an ErodingObjectPool wrapping the given pool using the specified erosion factor.
 2183  
          * 
 2184  
          * @param keyedPool underlying pool - must not be null
 2185  
          * @param erodingFactor erosion factor - determines the frequency of erosion events
 2186  
          * @see #factor
 2187  
          */
 2188  0
         protected ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, final ErodingFactor erodingFactor) {
 2189  0
             if (keyedPool == null) {
 2190  0
                 throw new IllegalArgumentException("keyedPool must not be null.");
 2191  
             }
 2192  0
             this.keyedPool = keyedPool;
 2193  0
             this.erodingFactor = erodingFactor;
 2194  0
         }
 2195  
 
 2196  
         /**
 2197  
          * {@inheritDoc}
 2198  
          */
 2199  
         public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException {
 2200  0
             return keyedPool.borrowObject(key);
 2201  
         }
 2202  
 
 2203  
         /**
 2204  
          * Returns obj to the pool, unless erosion is triggered, in which
 2205  
          * case obj is invalidated.  Erosion is triggered when there are idle instances in 
 2206  
          * the pool associated with the given key and more than the configured {@link #erodingFactor erosion factor}
 2207  
          * time has elapsed since the last returnObject activation. 
 2208  
          * 
 2209  
          * @param obj object to return or invalidate
 2210  
          * @param key key
 2211  
          * @see #erodingFactor
 2212  
          */
 2213  
         public void returnObject(final Object key, final Object obj) throws Exception {
 2214  0
             boolean discard = false;
 2215  0
             final long now = System.currentTimeMillis();
 2216  0
             final ErodingFactor factor = getErodingFactor(key);
 2217  0
             synchronized (keyedPool) {
 2218  0
                 if (factor.getNextShrink() < now) {
 2219  0
                     final int numIdle = numIdle(key);
 2220  0
                     if (numIdle > 0) {
 2221  0
                         discard = true;
 2222  
                     }
 2223  
 
 2224  0
                     factor.update(now, numIdle);
 2225  
                 }
 2226  0
             }
 2227  
             try {
 2228  0
                 if (discard) {
 2229  0
                     keyedPool.invalidateObject(key, obj);
 2230  
                 } else {
 2231  0
                     keyedPool.returnObject(key, obj);
 2232  
                 }
 2233  0
             } catch (Exception e) {
 2234  
                 // swallowed
 2235  0
             }
 2236  0
         }
 2237  
 
 2238  
         protected int numIdle(final Object key) {
 2239  0
             return getKeyedPool().getNumIdle();
 2240  
         }
 2241  
 
 2242  
         /**
 2243  
          * Returns the eroding factor for the given key
 2244  
          * @param key key
 2245  
          * @return eroding factor for the given keyed pool
 2246  
          */
 2247  
         protected ErodingFactor getErodingFactor(final Object key) {
 2248  0
             return erodingFactor;
 2249  
         }
 2250  
 
 2251  
         /**
 2252  
          * {@inheritDoc}
 2253  
          */
 2254  
         public void invalidateObject(final Object key, final Object obj) {
 2255  
             try {
 2256  0
                 keyedPool.invalidateObject(key, obj);
 2257  0
             } catch (Exception e) {
 2258  
                 // swallowed
 2259  0
             }
 2260  0
         }
 2261  
 
 2262  
         /**
 2263  
          * {@inheritDoc}
 2264  
          */
 2265  
         public void addObject(final Object key) throws Exception, IllegalStateException, UnsupportedOperationException {
 2266  0
             keyedPool.addObject(key);
 2267  0
         }
 2268  
 
 2269  
         /**
 2270  
          * {@inheritDoc}
 2271  
          */
 2272  
         public int getNumIdle() throws UnsupportedOperationException {
 2273  0
             return keyedPool.getNumIdle();
 2274  
         }
 2275  
 
 2276  
         /**
 2277  
          * {@inheritDoc}
 2278  
          */
 2279  
         public int getNumIdle(final Object key) throws UnsupportedOperationException {
 2280  0
             return keyedPool.getNumIdle(key);
 2281  
         }
 2282  
 
 2283  
         /**
 2284  
          * {@inheritDoc}
 2285  
          */
 2286  
         public int getNumActive() throws UnsupportedOperationException {
 2287  0
             return keyedPool.getNumActive();
 2288  
         }
 2289  
 
 2290  
         /**
 2291  
          * {@inheritDoc}
 2292  
          */
 2293  
         public int getNumActive(final Object key) throws UnsupportedOperationException {
 2294  0
             return keyedPool.getNumActive(key);
 2295  
         }
 2296  
 
 2297  
         /**
 2298  
          * {@inheritDoc}
 2299  
          */
 2300  
         public void clear() throws Exception, UnsupportedOperationException {
 2301  0
             keyedPool.clear();
 2302  0
         }
 2303  
 
 2304  
         /**
 2305  
          * {@inheritDoc}
 2306  
          */
 2307  
         public void clear(final Object key) throws Exception, UnsupportedOperationException {
 2308  0
             keyedPool.clear(key);
 2309  0
         }
 2310  
 
 2311  
         /**
 2312  
          * {@inheritDoc}
 2313  
          */
 2314  
         public void close() {
 2315  
             try {
 2316  0
                 keyedPool.close();
 2317  0
             } catch (Exception e) {
 2318  
                 // swallowed
 2319  0
             }
 2320  0
         }
 2321  
 
 2322  
         /**
 2323  
          * {@inheritDoc}
 2324  
          * @deprecated to be removed in pool 2.0
 2325  
          */
 2326  
         public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
 2327  0
             keyedPool.setFactory(factory);
 2328  0
         }
 2329  
 
 2330  
         /**
 2331  
          * Returns the underlying pool
 2332  
          * 
 2333  
          * @return the keyed pool that this ErodingKeyedObjectPool wraps
 2334  
          */
 2335  
         protected KeyedObjectPool getKeyedPool() {
 2336  0
             return keyedPool;
 2337  
         }
 2338  
 
 2339  
         /**
 2340  
          * {@inheritDoc}
 2341  
          */
 2342  
         public String toString() {
 2343  0
             return "ErodingKeyedObjectPool{" +
 2344  
                     "erodingFactor=" + erodingFactor +
 2345  
                     ", keyedPool=" + keyedPool +
 2346  
                     '}';
 2347  
         }
 2348  
     }
 2349  
 
 2350  
     /**
 2351  
      * Extends ErodingKeyedObjectPool to allow erosion to take place on a per-key
 2352  
      * basis.  Timing of erosion events is tracked separately for separate keyed pools.
 2353  
      */
 2354  
     private static class ErodingPerKeyKeyedObjectPool extends ErodingKeyedObjectPool {
 2355  
         /** Erosion factor - same for all pools */
 2356  
         private final float factor;
 2357  
         
 2358  
         /** Map of ErodingFactor instances keyed on pool keys */
 2359  0
         private final Map factors = Collections.synchronizedMap(new HashMap());
 2360  
 
 2361  
         /**
 2362  
          * Create a new ErordingPerKeyKeyedObjectPool decorating the given keyed pool with
 2363  
          * the specified erosion factor.
 2364  
          * @param keyedPool underlying keyed pool
 2365  
          * @param factor erosion factor
 2366  
          */
 2367  
         public ErodingPerKeyKeyedObjectPool(final KeyedObjectPool keyedPool, final float factor) {
 2368  0
             super(keyedPool, null);
 2369  0
             this.factor = factor;
 2370  0
         }
 2371  
 
 2372  
         /**
 2373  
          * {@inheritDoc}
 2374  
          */
 2375  
         protected int numIdle(final Object key) {
 2376  0
             return getKeyedPool().getNumIdle(key);
 2377  
         }
 2378  
 
 2379  
         /**
 2380  
          * {@inheritDoc}
 2381  
          */
 2382  
         protected ErodingFactor getErodingFactor(final Object key) {
 2383  0
             ErodingFactor factor = (ErodingFactor)factors.get(key);
 2384  
             // this may result in two ErodingFactors being created for a key
 2385  
             // since they are small and cheap this is okay.
 2386  0
             if (factor == null) {
 2387  0
                 factor = new ErodingFactor(this.factor);
 2388  0
                 factors.put(key, factor);
 2389  
             }
 2390  0
             return factor;
 2391  
         }
 2392  
 
 2393  
         /**
 2394  
          * {@inheritDoc}
 2395  
          */
 2396  
         public String toString() {
 2397  0
             return "ErodingPerKeyKeyedObjectPool{" +
 2398  
                     "factor=" + factor +
 2399  
                     ", keyedPool=" + getKeyedPool() +
 2400  
                     '}';
 2401  
         }
 2402  
     }
 2403  
 }