View Javadoc
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  package org.apache.commons.pool2;
18  
19  import java.util.Collection;
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Timer;
25  import java.util.TimerTask;
26  import java.util.concurrent.locks.ReentrantReadWriteLock;
27  import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
28  import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
29  
30  /**
31   * This class consists exclusively of static methods that operate on or return
32   * ObjectPool or KeyedObjectPool related interfaces.
33   *
34   * @since 2.0
35   */
36  public final class PoolUtils {
37  
38      /**
39       * Encapsulate the logic for when the next poolable object should be
40       * discarded. Each time update is called, the next time to shrink is
41       * recomputed, based on the float factor, number of idle instances in the
42       * pool and high water mark. Float factor is assumed to be between 0 and 1.
43       * Values closer to 1 cause less frequent erosion events. Erosion event
44       * timing also depends on numIdle. When this value is relatively high (close
45       * to previously established high water mark), erosion occurs more
46       * frequently.
47       */
48      private static final class ErodingFactor {
49          /** Determines frequency of "erosion" events */
50          private final float factor;
51  
52          /** Time of next shrink event */
53          private transient volatile long nextShrinkMillis;
54  
55          /** High water mark - largest numIdle encountered */
56          private transient volatile int idleHighWaterMark;
57  
58          /**
59           * Creates a new ErodingFactor with the given erosion factor.
60           *
61           * @param factor
62           *            erosion factor
63           */
64          public ErodingFactor(final float factor) {
65              this.factor = factor;
66              nextShrinkMillis = System.currentTimeMillis() + (long) (900000 * factor); // now + 15 min * factor
67              idleHighWaterMark = 1;
68          }
69  
70          /**
71           * Gets the time of the next erosion event.
72           *
73           * @return next shrink time
74           */
75          public long getNextShrink() {
76              return nextShrinkMillis;
77          }
78  
79          /**
80           * {@inheritDoc}
81           */
82          @Override
83          public String toString() {
84              return "ErodingFactor{" + "factor=" + factor +
85                      ", idleHighWaterMark=" + idleHighWaterMark + '}';
86          }
87  
88          /**
89           * Updates internal state using the supplied time and numIdle.
90           *
91           * @param nowMillis
92           *            current time
93           * @param numIdle
94           *            number of idle elements in the pool
95           */
96          public void update(final long nowMillis, final int numIdle) {
97              final int idle = Math.max(0, numIdle);
98              idleHighWaterMark = Math.max(idle, idleHighWaterMark);
99              final float maxInterval = 15f;
100             final float minutes = maxInterval +
101                     (1f - maxInterval) / idleHighWaterMark * idle;
102             nextShrinkMillis = nowMillis + (long) (minutes * 60000f * factor);
103         }
104     }
105     /**
106      * Decorates a keyed object pool, adding "eroding" behavior. Based on the
107      * configured erosion factor, objects returning to the pool
108      * may be invalidated instead of being added to idle capacity.
109      *
110      * @param <K> object pool key type
111      * @param <V> object pool value type
112      */
113     private static class ErodingKeyedObjectPool<K, V> implements KeyedObjectPool<K, V> {
114 
115         /** Underlying pool */
116         private final KeyedObjectPool<K, V> keyedPool;
117 
118         /** Erosion factor */
119         private final ErodingFactor erodingFactor;
120 
121         /**
122          * Creates an ErodingObjectPool wrapping the given pool using the
123          * specified erosion factor.
124          *
125          * @param keyedPool
126          *            underlying pool - must not be null
127          * @param erodingFactor
128          *            erosion factor - determines the frequency of erosion
129          *            events
130          * @see #erodingFactor
131          */
132         protected ErodingKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool,
133                 final ErodingFactor erodingFactor) {
134             if (keyedPool == null) {
135                 throw new IllegalArgumentException(
136                         MSG_NULL_KEYED_POOL);
137             }
138             this.keyedPool = keyedPool;
139             this.erodingFactor = erodingFactor;
140         }
141 
142         /**
143          * Creates an ErodingObjectPool wrapping the given pool using the
144          * specified erosion factor.
145          *
146          * @param keyedPool
147          *            underlying pool
148          * @param factor
149          *            erosion factor - determines the frequency of erosion
150          *            events
151          * @see #erodingFactor
152          */
153         public ErodingKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool,
154                 final float factor) {
155             this(keyedPool, new ErodingFactor(factor));
156         }
157 
158         /**
159          * {@inheritDoc}
160          */
161         @Override
162         public void addObject(final K key) throws Exception {
163             keyedPool.addObject(key);
164         }
165 
166         /**
167          * {@inheritDoc}
168          */
169         @Override
170         public V borrowObject(final K key) throws Exception {
171             return keyedPool.borrowObject(key);
172         }
173 
174         /**
175          * {@inheritDoc}
176          */
177         @Override
178         public void clear() throws Exception {
179             keyedPool.clear();
180         }
181 
182         /**
183          * {@inheritDoc}
184          */
185         @Override
186         public void clear(final K key) throws Exception {
187             keyedPool.clear(key);
188         }
189 
190         /**
191          * {@inheritDoc}
192          */
193         @Override
194         public void close() {
195             try {
196                 keyedPool.close();
197             } catch (final Exception ignored) {
198                 // ignored
199             }
200         }
201 
202         /**
203          * Gets the eroding factor for the given key
204          *
205          * @param key
206          *            key
207          * @return eroding factor for the given keyed pool
208          */
209         protected ErodingFactor getErodingFactor(final K key) {
210             return erodingFactor;
211         }
212 
213         /**
214          * Gets the underlying pool
215          *
216          * @return the keyed pool that this ErodingKeyedObjectPool wraps
217          */
218         protected KeyedObjectPool<K, V> getKeyedPool() {
219             return keyedPool;
220         }
221 
222         /**
223          * {@inheritDoc}
224          */
225         @Override
226         public List<K> getKeys() {
227             return keyedPool.getKeys();
228         }
229 
230         /**
231          * {@inheritDoc}
232          */
233         @Override
234         public int getNumActive() {
235             return keyedPool.getNumActive();
236         }
237 
238         /**
239          * {@inheritDoc}
240          */
241         @Override
242         public int getNumActive(final K key) {
243             return keyedPool.getNumActive(key);
244         }
245 
246         /**
247          * {@inheritDoc}
248          */
249         @Override
250         public int getNumIdle() {
251             return keyedPool.getNumIdle();
252         }
253 
254         /**
255          * {@inheritDoc}
256          */
257         @Override
258         public int getNumIdle(final K key) {
259             return keyedPool.getNumIdle(key);
260         }
261 
262         /**
263          * {@inheritDoc}
264          */
265         @Override
266         public void invalidateObject(final K key, final V obj) {
267             try {
268                 keyedPool.invalidateObject(key, obj);
269             } catch (final Exception ignored) {
270                 // ignored
271             }
272         }
273 
274         /**
275          * Returns obj to the pool, unless erosion is triggered, in which case
276          * obj is invalidated. Erosion is triggered when there are idle
277          * instances in the pool associated with the given key and more than the
278          * configured {@link #erodingFactor erosion factor} time has elapsed
279          * since the last returnObject activation.
280          *
281          * @param obj
282          *            object to return or invalidate
283          * @param key
284          *            key
285          * @see #erodingFactor
286          */
287         @Override
288         public void returnObject(final K key, final V obj) throws Exception {
289             boolean discard = false;
290             final long nowMillis = System.currentTimeMillis();
291             final ErodingFactor factor = getErodingFactor(key);
292             synchronized (keyedPool) {
293                 if (factor.getNextShrink() < nowMillis) {
294                     final int numIdle = getNumIdle(key);
295                     if (numIdle > 0) {
296                         discard = true;
297                     }
298 
299                     factor.update(nowMillis, numIdle);
300                 }
301             }
302             try {
303                 if (discard) {
304                     keyedPool.invalidateObject(key, obj);
305                 } else {
306                     keyedPool.returnObject(key, obj);
307                 }
308             } catch (final Exception ignored) {
309                 // ignored
310             }
311         }
312 
313         /**
314          * {@inheritDoc}
315          */
316         @Override
317         public String toString() {
318             return "ErodingKeyedObjectPool{" + "factor=" +
319                     erodingFactor + ", keyedPool=" + keyedPool + '}';
320         }
321     }
322 
323     /**
324      * Decorates an object pool, adding "eroding" behavior. Based on the
325      * configured {@link #factor erosion factor}, objects returning to the pool
326      * may be invalidated instead of being added to idle capacity.
327      *
328      * @param <T> type of objects in the pool
329      */
330     private static final class ErodingObjectPool<T> implements ObjectPool<T> {
331 
332         /** Underlying object pool */
333         private final ObjectPool<T> pool;
334 
335         /** Erosion factor */
336         private final ErodingFactor factor;
337 
338         /**
339          * Creates an ErodingObjectPool wrapping the given pool using the
340          * specified erosion factor.
341          *
342          * @param pool
343          *            underlying pool
344          * @param factor
345          *            erosion factor - determines the frequency of erosion
346          *            events
347          * @see #factor
348          */
349         public ErodingObjectPool(final ObjectPool<T> pool, final float factor) {
350             this.pool = pool;
351             this.factor = new ErodingFactor(factor);
352         }
353 
354         /**
355          * {@inheritDoc}
356          */
357         @Override
358         public void addObject() throws Exception{
359             pool.addObject();
360         }
361 
362         /**
363          * {@inheritDoc}
364          */
365         @Override
366         public T borrowObject() throws Exception {
367             return pool.borrowObject();
368         }
369 
370         /**
371          * {@inheritDoc}
372          */
373         @Override
374         public void clear() throws Exception {
375             pool.clear();
376         }
377 
378         /**
379          * {@inheritDoc}
380          */
381         @Override
382         public void close() {
383             try {
384                 pool.close();
385             } catch (final Exception ignored) {
386                 // ignored
387             }
388         }
389 
390         /**
391          * {@inheritDoc}
392          */
393         @Override
394         public int getNumActive() {
395             return pool.getNumActive();
396         }
397 
398         /**
399          * {@inheritDoc}
400          */
401         @Override
402         public int getNumIdle() {
403             return pool.getNumIdle();
404         }
405 
406         /**
407          * {@inheritDoc}
408          */
409         @Override
410         public void invalidateObject(final T obj) {
411             try {
412                 pool.invalidateObject(obj);
413             } catch (final Exception ignored) {
414                 // ignored
415             }
416         }
417 
418         /**
419          * Returns * Gets obj to the pool, unless erosion is triggered, in which case
420          * obj is invalidated. Erosion is triggered when there are idle
421          * instances in the pool and more than the {@link #factor erosion
422          * factor}-determined time has elapsed since the last returnObject
423          * activation.
424          *
425          * @param obj
426          *            object to return or invalidate
427          * @see #factor
428          */
429         @Override
430         public void returnObject(final T obj) {
431             boolean discard = false;
432             final long nowMillis = System.currentTimeMillis();
433             synchronized (pool) {
434                 if (factor.getNextShrink() < nowMillis) { // XXX: Pool 3: move test
435                                                     // out of sync block
436                     final int numIdle = pool.getNumIdle();
437                     if (numIdle > 0) {
438                         discard = true;
439                     }
440 
441                     factor.update(nowMillis, numIdle);
442                 }
443             }
444             try {
445                 if (discard) {
446                     pool.invalidateObject(obj);
447                 } else {
448                     pool.returnObject(obj);
449                 }
450             } catch (final Exception ignored) {
451                 // ignored
452             }
453         }
454 
455         /**
456          * {@inheritDoc}
457          */
458         @Override
459         public String toString() {
460             return "ErodingObjectPool{" + "factor=" + factor + ", pool=" +
461                     pool + '}';
462         }
463     }
464     /**
465      * Extends ErodingKeyedObjectPool to allow erosion to take place on a
466      * per-key basis. Timing of erosion events is tracked separately for
467      * separate keyed pools.
468      *
469      * @param <K> object pool key type
470      * @param <V> object pool value type
471      */
472     private static final class ErodingPerKeyKeyedObjectPool<K, V> extends ErodingKeyedObjectPool<K, V> {
473 
474         /** Erosion factor - same for all pools */
475         private final float factor;
476 
477         /** Map of ErodingFactor instances keyed on pool keys */
478         private final Map<K, ErodingFactor> factors = Collections.synchronizedMap(new HashMap<>());
479 
480         /**
481          * Creates a new ErordingPerKeyKeyedObjectPool decorating the given keyed
482          * pool with the specified erosion factor.
483          *
484          * @param keyedPool
485          *            underlying keyed pool
486          * @param factor
487          *            erosion factor
488          */
489         public ErodingPerKeyKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool, final float factor) {
490             super(keyedPool, null);
491             this.factor = factor;
492         }
493 
494         /**
495          * {@inheritDoc}
496          */
497         @Override
498         protected ErodingFactor getErodingFactor(final K key) {
499             // This may result in two ErodingFactors being created for a key
500             // since they are small and cheap this is okay.
501             return factors.computeIfAbsent(key, k -> new ErodingFactor(this.factor));
502         }
503 
504         /**
505          * {@inheritDoc}
506          */
507         @SuppressWarnings("resource") // getKeyedPool(): ivar access
508         @Override
509         public String toString() {
510             return "ErodingPerKeyKeyedObjectPool{" + "factor=" + factor +
511                     ", keyedPool=" + getKeyedPool() + '}';
512         }
513     }
514     /**
515      * Timer task that adds objects to the pool until the number of idle
516      * instances for the given key reaches the configured minIdle. Note that
517      * this is not the same as the pool's minIdle setting.
518      *
519      * @param <K> object pool key type
520      * @param <V> object pool value type
521      */
522     private static final class KeyedObjectPoolMinIdleTimerTask<K, V> extends TimerTask {
523 
524         /** Minimum number of idle instances. Not the same as pool.getMinIdle(). */
525         private final int minIdle;
526 
527         /** Key to ensure minIdle for */
528         private final K key;
529 
530         /** Keyed object pool */
531         private final KeyedObjectPool<K, V> keyedPool;
532 
533         /**
534          * Creates a new KeyedObjecPoolMinIdleTimerTask.
535          *
536          * @param keyedPool
537          *            keyed object pool
538          * @param key
539          *            key to ensure minimum number of idle instances
540          * @param minIdle
541          *            minimum number of idle instances
542          * @throws IllegalArgumentException
543          *             if the key is null
544          */
545         KeyedObjectPoolMinIdleTimerTask(final KeyedObjectPool<K, V> keyedPool,
546                 final K key, final int minIdle) throws IllegalArgumentException {
547             if (keyedPool == null) {
548                 throw new IllegalArgumentException(
549                         MSG_NULL_KEYED_POOL);
550             }
551             this.keyedPool = keyedPool;
552             this.key = key;
553             this.minIdle = minIdle;
554         }
555 
556         /**
557          * {@inheritDoc}
558          */
559         @Override
560         public void run() {
561             boolean success = false;
562             try {
563                 if (keyedPool.getNumIdle(key) < minIdle) {
564                     keyedPool.addObject(key);
565                 }
566                 success = true;
567 
568             } catch (final Exception e) {
569                 cancel();
570 
571             } finally {
572                 // detect other types of Throwable and cancel this Timer
573                 if (!success) {
574                     cancel();
575                 }
576             }
577         }
578 
579         /**
580          * {@inheritDoc}
581          */
582         @Override
583         public String toString() {
584             final StringBuilder sb = new StringBuilder();
585             sb.append("KeyedObjectPoolMinIdleTimerTask");
586             sb.append("{minIdle=").append(minIdle);
587             sb.append(", key=").append(key);
588             sb.append(", keyedPool=").append(keyedPool);
589             sb.append('}');
590             return sb.toString();
591         }
592     }
593     /**
594      * Timer task that adds objects to the pool until the number of idle
595      * instances reaches the configured minIdle. Note that this is not the same
596      * as the pool's minIdle setting.
597      *
598      * @param <T> type of objects in the pool
599      */
600     private static final class ObjectPoolMinIdleTimerTask<T> extends TimerTask {
601 
602         /** Minimum number of idle instances. Not the same as pool.getMinIdle(). */
603         private final int minIdle;
604 
605         /** Object pool */
606         private final ObjectPool<T> pool;
607 
608         /**
609          * Constructs a new ObjectPoolMinIdleTimerTask for the given pool with the
610          * given minIdle setting.
611          *
612          * @param pool
613          *            object pool
614          * @param minIdle
615          *            number of idle instances to maintain
616          * @throws IllegalArgumentException
617          *             if the pool is null
618          */
619         ObjectPoolMinIdleTimerTask(final ObjectPool<T> pool, final int minIdle)
620                 throws IllegalArgumentException {
621             if (pool == null) {
622                 throw new IllegalArgumentException(MSG_NULL_POOL);
623             }
624             this.pool = pool;
625             this.minIdle = minIdle;
626         }
627 
628         /**
629          * {@inheritDoc}
630          */
631         @Override
632         public void run() {
633             boolean success = false;
634             try {
635                 if (pool.getNumIdle() < minIdle) {
636                     pool.addObject();
637                 }
638                 success = true;
639 
640             } catch (final Exception e) {
641                 cancel();
642             } finally {
643                 // detect other types of Throwable and cancel this Timer
644                 if (!success) {
645                     cancel();
646                 }
647             }
648         }
649 
650         /**
651          * {@inheritDoc}
652          */
653         @Override
654         public String toString() {
655             final StringBuilder sb = new StringBuilder();
656             sb.append("ObjectPoolMinIdleTimerTask");
657             sb.append("{minIdle=").append(minIdle);
658             sb.append(", pool=").append(pool);
659             sb.append('}');
660             return sb.toString();
661         }
662     }
663 
664     /**
665      * A synchronized (thread-safe) KeyedObjectPool backed by the specified
666      * KeyedObjectPool.
667      * <p>
668      * <strong>Note:</strong> This should not be used on pool implementations that already
669      * provide proper synchronization such as the pools provided in the Commons
670      * Pool library. Wrapping a pool that {@link #wait() waits} for poolable
671      * objects to be returned before allowing another one to be borrowed with
672      * another layer of synchronization will cause liveliness issues or a
673      * deadlock.
674      * </p>
675      *
676      * @param <K> object pool key type
677      * @param <V> object pool value type
678      */
679     static final class SynchronizedKeyedObjectPool<K, V> implements KeyedObjectPool<K, V> {
680 
681         /**
682          * Object whose monitor is used to synchronize methods on the wrapped
683          * pool.
684          */
685         private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
686 
687         /** Underlying object pool */
688         private final KeyedObjectPool<K, V> keyedPool;
689 
690         /**
691          * Creates a new SynchronizedKeyedObjectPool wrapping the given pool
692          *
693          * @param keyedPool
694          *            KeyedObjectPool to wrap
695          * @throws IllegalArgumentException
696          *             if keyedPool is null
697          */
698         SynchronizedKeyedObjectPool(final KeyedObjectPool<K, V> keyedPool)
699                 throws IllegalArgumentException {
700             if (keyedPool == null) {
701                 throw new IllegalArgumentException(
702                         MSG_NULL_KEYED_POOL);
703             }
704             this.keyedPool = keyedPool;
705         }
706 
707         /**
708          * {@inheritDoc}
709          */
710         @Override
711         public void addObject(final K key) throws Exception {
712             final WriteLock writeLock = readWriteLock.writeLock();
713             writeLock.lock();
714             try {
715                 keyedPool.addObject(key);
716             } finally {
717                 writeLock.unlock();
718             }
719         }
720 
721         /**
722          * {@inheritDoc}
723          */
724         @Override
725         public V borrowObject(final K key) throws Exception {
726             final WriteLock writeLock = readWriteLock.writeLock();
727             writeLock.lock();
728             try {
729                 return keyedPool.borrowObject(key);
730             } finally {
731                 writeLock.unlock();
732             }
733         }
734 
735         /**
736          * {@inheritDoc}
737          */
738         @Override
739         public void clear() throws Exception {
740             final WriteLock writeLock = readWriteLock.writeLock();
741             writeLock.lock();
742             try {
743                 keyedPool.clear();
744             } finally {
745                 writeLock.unlock();
746             }
747         }
748 
749         /**
750          * {@inheritDoc}
751          */
752         @Override
753         public void clear(final K key) throws Exception {
754             final WriteLock writeLock = readWriteLock.writeLock();
755             writeLock.lock();
756             try {
757                 keyedPool.clear(key);
758             } finally {
759                 writeLock.unlock();
760             }
761         }
762 
763         /**
764          * {@inheritDoc}
765          */
766         @Override
767         public void close() {
768             final WriteLock writeLock = readWriteLock.writeLock();
769             writeLock.lock();
770             try {
771                 keyedPool.close();
772             } catch (final Exception ignored) {
773                 // ignored as of Pool 2
774             } finally {
775                 writeLock.unlock();
776             }
777         }
778 
779         /**
780          * {@inheritDoc}
781          */
782         @Override
783         public List<K> getKeys() {
784             final ReadLock readLock = readWriteLock.readLock();
785             readLock.lock();
786             try {
787                 return keyedPool.getKeys();
788             } finally {
789                 readLock.unlock();
790             }
791         }
792 
793         /**
794          * {@inheritDoc}
795          */
796         @Override
797         public int getNumActive() {
798             final ReadLock readLock = readWriteLock.readLock();
799             readLock.lock();
800             try {
801                 return keyedPool.getNumActive();
802             } finally {
803                 readLock.unlock();
804             }
805         }
806 
807         /**
808          * {@inheritDoc}
809          */
810         @Override
811         public int getNumActive(final K key) {
812             final ReadLock readLock = readWriteLock.readLock();
813             readLock.lock();
814             try {
815                 return keyedPool.getNumActive(key);
816             } finally {
817                 readLock.unlock();
818             }
819         }
820 
821         /**
822          * {@inheritDoc}
823          */
824         @Override
825         public int getNumIdle() {
826             final ReadLock readLock = readWriteLock.readLock();
827             readLock.lock();
828             try {
829                 return keyedPool.getNumIdle();
830             } finally {
831                 readLock.unlock();
832             }
833         }
834 
835         /**
836          * {@inheritDoc}
837          */
838         @Override
839         public int getNumIdle(final K key) {
840             final ReadLock readLock = readWriteLock.readLock();
841             readLock.lock();
842             try {
843                 return keyedPool.getNumIdle(key);
844             } finally {
845                 readLock.unlock();
846             }
847         }
848 
849         /**
850          * {@inheritDoc}
851          */
852         @Override
853         public void invalidateObject(final K key, final V obj) {
854             final WriteLock writeLock = readWriteLock.writeLock();
855             writeLock.lock();
856             try {
857                 keyedPool.invalidateObject(key, obj);
858             } catch (final Exception ignored) {
859                 // ignored as of Pool 2
860             } finally {
861                 writeLock.unlock();
862             }
863         }
864 
865         /**
866          * {@inheritDoc}
867          */
868         @Override
869         public void returnObject(final K key, final V obj) {
870             final WriteLock writeLock = readWriteLock.writeLock();
871             writeLock.lock();
872             try {
873                 keyedPool.returnObject(key, obj);
874             } catch (final Exception ignored) {
875                 // ignored
876             } finally {
877                 writeLock.unlock();
878             }
879         }
880 
881         /**
882          * {@inheritDoc}
883          */
884         @Override
885         public String toString() {
886             final StringBuilder sb = new StringBuilder();
887             sb.append("SynchronizedKeyedObjectPool");
888             sb.append("{keyedPool=").append(keyedPool);
889             sb.append('}');
890             return sb.toString();
891         }
892     }
893 
894     /**
895      * A fully synchronized KeyedPooledObjectFactory that wraps a
896      * KeyedPooledObjectFactory and synchronizes access to the wrapped factory
897      * methods.
898      * <p>
899      * <strong>Note:</strong> This should not be used on pool implementations that already
900      * provide proper synchronization such as the pools provided in the Commons
901      * Pool library.
902      * </p>
903      *
904      * @param <K> pooled object factory key type
905      * @param <V> pooled object factory value type
906      */
907     private static final class SynchronizedKeyedPooledObjectFactory<K, V> implements KeyedPooledObjectFactory<K, V> {
908 
909         /** Synchronization lock */
910         private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock();
911 
912         /** Wrapped factory */
913         private final KeyedPooledObjectFactory<K, V> keyedFactory;
914 
915         /**
916          * Creates a SynchronizedKeyedPooledObjectFactory wrapping the given
917          * factory.
918          *
919          * @param keyedFactory
920          *            underlying factory to wrap
921          * @throws IllegalArgumentException
922          *             if the factory is null
923          */
924         SynchronizedKeyedPooledObjectFactory(final KeyedPooledObjectFactory<K, V> keyedFactory) throws IllegalArgumentException {
925             if (keyedFactory == null) {
926                 throw new IllegalArgumentException(
927                         "keyedFactory must not be null.");
928             }
929             this.keyedFactory = keyedFactory;
930         }
931 
932         /**
933          * {@inheritDoc}
934          */
935         @Override
936         public void activateObject(final K key, final PooledObject<V> p) throws Exception {
937             writeLock.lock();
938             try {
939                 keyedFactory.activateObject(key, p);
940             } finally {
941                 writeLock.unlock();
942             }
943         }
944 
945         /**
946          * {@inheritDoc}
947          */
948         @Override
949         public void destroyObject(final K key, final PooledObject<V> p) throws Exception {
950             writeLock.lock();
951             try {
952                 keyedFactory.destroyObject(key, p);
953             } finally {
954                 writeLock.unlock();
955             }
956         }
957 
958         /**
959          * {@inheritDoc}
960          */
961         @Override
962         public PooledObject<V> makeObject(final K key) throws Exception {
963             writeLock.lock();
964             try {
965                 return keyedFactory.makeObject(key);
966             } finally {
967                 writeLock.unlock();
968             }
969         }
970 
971         /**
972          * {@inheritDoc}
973          */
974         @Override
975         public void passivateObject(final K key, final PooledObject<V> p) throws Exception {
976             writeLock.lock();
977             try {
978                 keyedFactory.passivateObject(key, p);
979             } finally {
980                 writeLock.unlock();
981             }
982         }
983 
984         /**
985          * {@inheritDoc}
986          */
987         @Override
988         public String toString() {
989             final StringBuilder sb = new StringBuilder();
990             sb.append("SynchronizedKeyedPooledObjectFactory");
991             sb.append("{keyedFactory=").append(keyedFactory);
992             sb.append('}');
993             return sb.toString();
994         }
995 
996         /**
997          * {@inheritDoc}
998          */
999         @Override
1000         public boolean validateObject(final K key, final PooledObject<V> p) {
1001             writeLock.lock();
1002             try {
1003                 return keyedFactory.validateObject(key, p);
1004             } finally {
1005                 writeLock.unlock();
1006             }
1007         }
1008     }
1009 
1010     /**
1011      * A synchronized (thread-safe) ObjectPool backed by the specified
1012      * ObjectPool.
1013      * <p>
1014      * <strong>Note:</strong> This should not be used on pool implementations that already
1015      * provide proper synchronization such as the pools provided in the Commons
1016      * Pool library. Wrapping a pool that {@link #wait() waits} for poolable
1017      * objects to be returned before allowing another one to be borrowed with
1018      * another layer of synchronization will cause liveliness issues or a
1019      * deadlock.
1020      * </p>
1021      *
1022      * @param <T> type of objects in the pool
1023      */
1024     private static final class SynchronizedObjectPool<T> implements ObjectPool<T> {
1025 
1026         /**
1027          * Object whose monitor is used to synchronize methods on the wrapped
1028          * pool.
1029          */
1030         private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
1031 
1032         /** The underlying object pool */
1033         private final ObjectPool<T> pool;
1034 
1035         /**
1036          * Creates a new SynchronizedObjectPool wrapping the given pool.
1037          *
1038          * @param pool
1039          *            the ObjectPool to be "wrapped" in a synchronized
1040          *            ObjectPool.
1041          * @throws IllegalArgumentException
1042          *             if the pool is null
1043          */
1044         SynchronizedObjectPool(final ObjectPool<T> pool)
1045                 throws IllegalArgumentException {
1046             if (pool == null) {
1047                 throw new IllegalArgumentException(MSG_NULL_POOL);
1048             }
1049             this.pool = pool;
1050         }
1051 
1052         /**
1053          * {@inheritDoc}
1054          */
1055         @Override
1056         public void addObject() throws Exception {
1057             final WriteLock writeLock = readWriteLock.writeLock();
1058             writeLock.lock();
1059             try {
1060                 pool.addObject();
1061             } finally {
1062                 writeLock.unlock();
1063             }
1064         }
1065 
1066         /**
1067          * {@inheritDoc}
1068          */
1069         @Override
1070         public T borrowObject() throws Exception {
1071             final WriteLock writeLock = readWriteLock.writeLock();
1072             writeLock.lock();
1073             try {
1074                 return pool.borrowObject();
1075             } finally {
1076                 writeLock.unlock();
1077             }
1078         }
1079 
1080         /**
1081          * {@inheritDoc}
1082          */
1083         @Override
1084         public void clear() throws Exception {
1085             final WriteLock writeLock = readWriteLock.writeLock();
1086             writeLock.lock();
1087             try {
1088                 pool.clear();
1089             } finally {
1090                 writeLock.unlock();
1091             }
1092         }
1093 
1094         /**
1095          * {@inheritDoc}
1096          */
1097         @Override
1098         public void close() {
1099             final WriteLock writeLock = readWriteLock.writeLock();
1100             writeLock.lock();
1101             try {
1102                 pool.close();
1103             } catch (final Exception ignored) {
1104                 // ignored as of Pool 2
1105             } finally {
1106                 writeLock.unlock();
1107             }
1108         }
1109 
1110         /**
1111          * {@inheritDoc}
1112          */
1113         @Override
1114         public int getNumActive() {
1115             final ReadLock readLock = readWriteLock.readLock();
1116             readLock.lock();
1117             try {
1118                 return pool.getNumActive();
1119             } finally {
1120                 readLock.unlock();
1121             }
1122         }
1123 
1124         /**
1125          * {@inheritDoc}
1126          */
1127         @Override
1128         public int getNumIdle() {
1129             final ReadLock readLock = readWriteLock.readLock();
1130             readLock.lock();
1131             try {
1132                 return pool.getNumIdle();
1133             } finally {
1134                 readLock.unlock();
1135             }
1136         }
1137 
1138         /**
1139          * {@inheritDoc}
1140          */
1141         @Override
1142         public void invalidateObject(final T obj) {
1143             final WriteLock writeLock = readWriteLock.writeLock();
1144             writeLock.lock();
1145             try {
1146                 pool.invalidateObject(obj);
1147             } catch (final Exception ignored) {
1148                 // ignored as of Pool 2
1149             } finally {
1150                 writeLock.unlock();
1151             }
1152         }
1153 
1154         /**
1155          * {@inheritDoc}
1156          */
1157         @Override
1158         public void returnObject(final T obj) {
1159             final WriteLock writeLock = readWriteLock.writeLock();
1160             writeLock.lock();
1161             try {
1162                 pool.returnObject(obj);
1163             } catch (final Exception ignored) {
1164                 // ignored as of Pool 2
1165             } finally {
1166                 writeLock.unlock();
1167             }
1168         }
1169 
1170         /**
1171          * {@inheritDoc}
1172          */
1173         @Override
1174         public String toString() {
1175             final StringBuilder sb = new StringBuilder();
1176             sb.append("SynchronizedObjectPool");
1177             sb.append("{pool=").append(pool);
1178             sb.append('}');
1179             return sb.toString();
1180         }
1181     }
1182 
1183     /**
1184      * A fully synchronized PooledObjectFactory that wraps a
1185      * PooledObjectFactory and synchronizes access to the wrapped factory
1186      * methods.
1187      * <p>
1188      * <strong>Note:</strong> This should not be used on pool implementations that already
1189      * provide proper synchronization such as the pools provided in the Commons
1190      * Pool library.
1191      * </p>
1192      *
1193      * @param <T> pooled object factory type
1194      */
1195     private static final class SynchronizedPooledObjectFactory<T> implements
1196             PooledObjectFactory<T> {
1197 
1198         /** Synchronization lock */
1199         private final WriteLock writeLock = new ReentrantReadWriteLock().writeLock();
1200 
1201         /** Wrapped factory */
1202         private final PooledObjectFactory<T> factory;
1203 
1204         /**
1205          * Creates a SynchronizedPoolableObjectFactory wrapping the given
1206          * factory.
1207          *
1208          * @param factory
1209          *            underlying factory to wrap
1210          * @throws IllegalArgumentException
1211          *             if the factory is null
1212          */
1213         SynchronizedPooledObjectFactory(final PooledObjectFactory<T> factory)
1214                 throws IllegalArgumentException {
1215             if (factory == null) {
1216                 throw new IllegalArgumentException("factory must not be null.");
1217             }
1218             this.factory = factory;
1219         }
1220 
1221         /**
1222          * {@inheritDoc}
1223          */
1224         @Override
1225         public void activateObject(final PooledObject<T> p) throws Exception {
1226             writeLock.lock();
1227             try {
1228                 factory.activateObject(p);
1229             } finally {
1230                 writeLock.unlock();
1231             }
1232         }
1233 
1234         /**
1235          * {@inheritDoc}
1236          */
1237         @Override
1238         public void destroyObject(final PooledObject<T> p) throws Exception {
1239             writeLock.lock();
1240             try {
1241                 factory.destroyObject(p);
1242             } finally {
1243                 writeLock.unlock();
1244             }
1245         }
1246 
1247         /**
1248          * {@inheritDoc}
1249          */
1250         @Override
1251         public PooledObject<T> makeObject() throws Exception {
1252             writeLock.lock();
1253             try {
1254                 return factory.makeObject();
1255             } finally {
1256                 writeLock.unlock();
1257             }
1258         }
1259 
1260         /**
1261          * {@inheritDoc}
1262          */
1263         @Override
1264         public void passivateObject(final PooledObject<T> p) throws Exception {
1265             writeLock.lock();
1266             try {
1267                 factory.passivateObject(p);
1268             } finally {
1269                 writeLock.unlock();
1270             }
1271         }
1272 
1273         /**
1274          * {@inheritDoc}
1275          */
1276         @Override
1277         public String toString() {
1278             final StringBuilder sb = new StringBuilder();
1279             sb.append("SynchronizedPoolableObjectFactory");
1280             sb.append("{factory=").append(factory);
1281             sb.append('}');
1282             return sb.toString();
1283         }
1284 
1285         /**
1286          * {@inheritDoc}
1287          */
1288         @Override
1289         public boolean validateObject(final PooledObject<T> p) {
1290             writeLock.lock();
1291             try {
1292                 return factory.validateObject(p);
1293             } finally {
1294                 writeLock.unlock();
1295             }
1296         }
1297     }
1298 
1299     /**
1300      * Timer used to periodically check pools idle object count. Because a
1301      * {@link Timer} creates a {@link Thread}, an IODH is used.
1302      */
1303     static class TimerHolder {
1304         static final Timer MIN_IDLE_TIMER = new Timer(true);
1305     }
1306 
1307     private static final String MSG_FACTOR_NEGATIVE = "factor must be positive.";
1308 
1309     private static final String MSG_MIN_IDLE = "minIdle must be non-negative.";
1310 
1311     static final String MSG_NULL_KEY = "key must not be null.";
1312 
1313     private static final String MSG_NULL_KEYED_POOL = "keyedPool must not be null.";
1314 
1315     static final String MSG_NULL_KEYS = "keys must not be null.";
1316 
1317     private static final String MSG_NULL_POOL = "pool must not be null.";
1318 
1319     /**
1320      * Periodically check the idle object count for each key in the
1321      * {@code Collection keys} in the keyedPool. At most one idle object will be
1322      * added per period.
1323      *
1324      * @param keyedPool
1325      *            the keyedPool to check periodically.
1326      * @param keys
1327      *            a collection of keys to check the idle object count.
1328      * @param minIdle
1329      *            if the {@link KeyedObjectPool#getNumIdle(Object)} is less than
1330      *            this then add an idle object.
1331      * @param periodMillis
1332      *            the frequency in milliseconds to check the number of idle objects in a
1333      *            keyedPool, see {@link Timer#schedule(TimerTask, long, long)}.
1334      * @param <K> the type of the pool key
1335      * @param <V> the type of pool entries
1336      * @return a {@link Map} of key and {@link TimerTask} pairs that will
1337      *         periodically check the pools idle object count.
1338      * @throws IllegalArgumentException
1339      *             when {@code keyedPool}, {@code keys}, or any of the values in
1340      *             the collection is {@code null} or when {@code minIdle} is
1341      *             negative or when {@code period} isn't valid for
1342      *             {@link Timer#schedule(TimerTask, long, long)}.
1343      * @see #checkMinIdle(KeyedObjectPool, Object, int, long)
1344      */
1345     public static <K, V> Map<K, TimerTask> checkMinIdle(
1346             final KeyedObjectPool<K, V> keyedPool, final Collection<K> keys,
1347             final int minIdle, final long periodMillis)
1348             throws IllegalArgumentException {
1349         if (keys == null) {
1350             throw new IllegalArgumentException(MSG_NULL_KEYS);
1351         }
1352         final Map<K, TimerTask> tasks = new HashMap<>(keys.size());
1353         keys.forEach(key -> tasks.put(key, checkMinIdle(keyedPool, key, minIdle, periodMillis)));
1354         return tasks;
1355     }
1356 
1357     /**
1358      * Periodically check the idle object count for the key in the keyedPool. At
1359      * most one idle object will be added per period. If there is an exception
1360      * when calling {@link KeyedObjectPool#addObject(Object)} then no more
1361      * checks for that key will be performed.
1362      *
1363      * @param keyedPool
1364      *            the keyedPool to check periodically.
1365      * @param key
1366      *            the key to check the idle count of.
1367      * @param minIdle
1368      *            if the {@link KeyedObjectPool#getNumIdle(Object)} is less than
1369      *            this then add an idle object.
1370      * @param periodMillis
1371      *            the frequency in milliseconds to check the number of idle objects in a
1372      *            keyedPool, see {@link Timer#schedule(TimerTask, long, long)}.
1373      * @param <K> the type of the pool key
1374      * @param <V> the type of pool entries
1375      * @return the {@link TimerTask} that will periodically check the pools idle
1376      *         object count.
1377      * @throws IllegalArgumentException
1378      *             when {@code keyedPool}, {@code key} is {@code null} or
1379      *             when {@code minIdle} is negative or when {@code period} isn't
1380      *             valid for {@link Timer#schedule(TimerTask, long, long)}.
1381      */
1382     public static <K, V> TimerTask checkMinIdle(
1383             final KeyedObjectPool<K, V> keyedPool, final K key,
1384             final int minIdle, final long periodMillis)
1385             throws IllegalArgumentException {
1386         if (keyedPool == null) {
1387             throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
1388         }
1389         if (key == null) {
1390             throw new IllegalArgumentException(MSG_NULL_KEY);
1391         }
1392         if (minIdle < 0) {
1393             throw new IllegalArgumentException(MSG_MIN_IDLE);
1394         }
1395         final TimerTask task = new KeyedObjectPoolMinIdleTimerTask<>(
1396                 keyedPool, key, minIdle);
1397         getMinIdleTimer().schedule(task, 0L, periodMillis);
1398         return task;
1399     }
1400 
1401     /**
1402      * Periodically check the idle object count for the pool. At most one idle
1403      * object will be added per period. If there is an exception when calling
1404      * {@link ObjectPool#addObject()} then no more checks will be performed.
1405      *
1406      * @param pool
1407      *            the pool to check periodically.
1408      * @param minIdle
1409      *            if the {@link ObjectPool#getNumIdle()} is less than this then
1410      *            add an idle object.
1411      * @param periodMillis
1412      *            the frequency in milliseconds to check the number of idle objects in a pool,
1413      *            see {@link Timer#schedule(TimerTask, long, long)}.
1414      * @param <T> the type of objects in the pool
1415      * @return the {@link TimerTask} that will periodically check the pools idle
1416      *         object count.
1417      * @throws IllegalArgumentException
1418      *             when {@code pool} is {@code null} or when {@code minIdle} is
1419      *             negative or when {@code period} isn't valid for
1420      *             {@link Timer#schedule(TimerTask, long, long)}
1421      */
1422     public static <T> TimerTask checkMinIdle(final ObjectPool<T> pool,
1423             final int minIdle, final long periodMillis)
1424             throws IllegalArgumentException {
1425         if (pool == null) {
1426             throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
1427         }
1428         if (minIdle < 0) {
1429             throw new IllegalArgumentException(MSG_MIN_IDLE);
1430         }
1431         final TimerTask task = new ObjectPoolMinIdleTimerTask<>(pool, minIdle);
1432         getMinIdleTimer().schedule(task, 0L, periodMillis);
1433         return task;
1434     }
1435 
1436     /**
1437      * Should the supplied Throwable be re-thrown (eg if it is an instance of
1438      * one of the Throwables that should never be swallowed). Used by the pool
1439      * error handling for operations that throw exceptions that normally need to
1440      * be ignored.
1441      *
1442      * @param t
1443      *            The Throwable to check
1444      * @throws ThreadDeath
1445      *             if that is passed in
1446      * @throws VirtualMachineError
1447      *             if that is passed in
1448      */
1449     public static void checkRethrow(final Throwable t) {
1450         if (t instanceof ThreadDeath) {
1451             throw (ThreadDeath) t;
1452         }
1453         if (t instanceof VirtualMachineError) {
1454             throw (VirtualMachineError) t;
1455         }
1456         // All other instances of Throwable will be silently swallowed
1457     }
1458 
1459     /**
1460      * Returns a pool that adaptively decreases its size when idle objects are
1461      * no longer needed. This is intended as an always thread-safe alternative
1462      * to using an idle object evictor provided by many pool implementations.
1463      * This is also an effective way to shrink FIFO ordered pools that
1464      * experience load spikes.
1465      *
1466      * @param keyedPool
1467      *            the KeyedObjectPool to be decorated so it shrinks its idle
1468      *            count when possible.
1469      * @param <K> the type of the pool key
1470      * @param <V> the type of pool entries
1471      * @throws IllegalArgumentException
1472      *             when {@code keyedPool} is {@code null}.
1473      * @return a pool that adaptively decreases its size when idle objects are
1474      *         no longer needed.
1475      * @see #erodingPool(KeyedObjectPool, float)
1476      * @see #erodingPool(KeyedObjectPool, float, boolean)
1477      */
1478     public static <K, V> KeyedObjectPool<K, V> erodingPool(final KeyedObjectPool<K, V> keyedPool) {
1479         return erodingPool(keyedPool, 1f);
1480     }
1481 
1482     /**
1483      * Returns a pool that adaptively decreases its size when idle objects are
1484      * no longer needed. This is intended as an always thread-safe alternative
1485      * to using an idle object evictor provided by many pool implementations.
1486      * This is also an effective way to shrink FIFO ordered pools that
1487      * experience load spikes.
1488      * <p>
1489      * The factor parameter provides a mechanism to tweak the rate at which the
1490      * pool tries to shrink its size. Values between 0 and 1 cause the pool to
1491      * try to shrink its size more often. Values greater than 1 cause the pool
1492      * to less frequently try to shrink its size.
1493      * </p>
1494      *
1495      * @param keyedPool
1496      *            the KeyedObjectPool to be decorated so it shrinks its idle
1497      *            count when possible.
1498      * @param factor
1499      *            a positive value to scale the rate at which the pool tries to
1500      *            reduce its size. If 0 &lt; factor &lt; 1 then the pool
1501      *            shrinks more aggressively. If 1 &lt; factor then the pool
1502      *            shrinks less aggressively.
1503      * @param <K> the type of the pool key
1504      * @param <V> the type of pool entries
1505      * @throws IllegalArgumentException
1506      *             when {@code keyedPool} is {@code null} or when {@code factor}
1507      *             is not positive.
1508      * @return a pool that adaptively decreases its size when idle objects are
1509      *         no longer needed.
1510      * @see #erodingPool(KeyedObjectPool, float, boolean)
1511      */
1512     public static <K, V> KeyedObjectPool<K, V> erodingPool(final KeyedObjectPool<K, V> keyedPool, final float factor) {
1513         return erodingPool(keyedPool, factor, false);
1514     }
1515 
1516     /**
1517      * Returns a pool that adaptively decreases its size when idle objects are
1518      * no longer needed. This is intended as an always thread-safe alternative
1519      * to using an idle object evictor provided by many pool implementations.
1520      * This is also an effective way to shrink FIFO ordered pools that
1521      * experience load spikes.
1522      * <p>
1523      * The factor parameter provides a mechanism to tweak the rate at which the
1524      * pool tries to shrink its size. Values between 0 and 1 cause the pool to
1525      * try to shrink its size more often. Values greater than 1 cause the pool
1526      * to less frequently try to shrink its size.
1527      * </p>
1528      * <p>
1529      * The perKey parameter determines if the pool shrinks on a whole pool basis
1530      * or a per key basis. When perKey is false, the keys do not have an effect
1531      * on the rate at which the pool tries to shrink its size. When perKey is
1532      * true, each key is shrunk independently.
1533      * </p>
1534      *
1535      * @param keyedPool
1536      *            the KeyedObjectPool to be decorated so it shrinks its idle
1537      *            count when possible.
1538      * @param factor
1539      *            a positive value to scale the rate at which the pool tries to
1540      *            reduce its size. If 0 &lt; factor &lt; 1 then the pool
1541      *            shrinks more aggressively. If 1 &lt; factor then the pool
1542      *            shrinks less aggressively.
1543      * @param perKey
1544      *            when true, each key is treated independently.
1545      * @param <K> the type of the pool key
1546      * @param <V> the type of pool entries
1547      * @throws IllegalArgumentException
1548      *             when {@code keyedPool} is {@code null} or when {@code factor}
1549      *             is not positive.
1550      * @return a pool that adaptively decreases its size when idle objects are
1551      *         no longer needed.
1552      * @see #erodingPool(KeyedObjectPool)
1553      * @see #erodingPool(KeyedObjectPool, float)
1554      */
1555     public static <K, V> KeyedObjectPool<K, V> erodingPool(
1556             final KeyedObjectPool<K, V> keyedPool, final float factor,
1557             final boolean perKey) {
1558         if (keyedPool == null) {
1559             throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
1560         }
1561         if (factor <= 0f) {
1562             throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE);
1563         }
1564         if (perKey) {
1565             return new ErodingPerKeyKeyedObjectPool<>(keyedPool, factor);
1566         }
1567         return new ErodingKeyedObjectPool<>(keyedPool, factor);
1568     }
1569 
1570     /**
1571      * Returns a pool that adaptively decreases its size when idle objects are
1572      * no longer needed. This is intended as an always thread-safe alternative
1573      * to using an idle object evictor provided by many pool implementations.
1574      * This is also an effective way to shrink FIFO ordered pools that
1575      * experience load spikes.
1576      *
1577      * @param pool
1578      *            the ObjectPool to be decorated so it shrinks its idle count
1579      *            when possible.
1580      * @param <T> the type of objects in the pool
1581      * @throws IllegalArgumentException
1582      *             when {@code pool} is {@code null}.
1583      * @return a pool that adaptively decreases its size when idle objects are
1584      *         no longer needed.
1585      * @see #erodingPool(ObjectPool, float)
1586      */
1587     public static <T> ObjectPool<T> erodingPool(final ObjectPool<T> pool) {
1588         return erodingPool(pool, 1f);
1589     }
1590 
1591     /**
1592      * Returns a pool that adaptively decreases its size when idle objects are
1593      * no longer needed. This is intended as an always thread-safe alternative
1594      * to using an idle object evictor provided by many pool implementations.
1595      * This is also an effective way to shrink FIFO ordered pools that
1596      * experience load spikes.
1597      * <p>
1598      * The factor parameter provides a mechanism to tweak the rate at which the
1599      * pool tries to shrink its size. Values between 0 and 1 cause the pool to
1600      * try to shrink its size more often. Values greater than 1 cause the pool
1601      * to less frequently try to shrink its size.
1602      * </p>
1603      *
1604      * @param pool
1605      *            the ObjectPool to be decorated so it shrinks its idle count
1606      *            when possible.
1607      * @param factor
1608      *            a positive value to scale the rate at which the pool tries to
1609      *            reduce its size. If 0 &lt; factor &lt; 1 then the pool
1610      *            shrinks more aggressively. If 1 &lt; factor then the pool
1611      *            shrinks less aggressively.
1612      * @param <T> the type of objects in the pool
1613      * @throws IllegalArgumentException
1614      *             when {@code pool} is {@code null} or when {@code factor} is
1615      *             not positive.
1616      * @return a pool that adaptively decreases its size when idle objects are
1617      *         no longer needed.
1618      * @see #erodingPool(ObjectPool)
1619      */
1620     public static <T> ObjectPool<T> erodingPool(final ObjectPool<T> pool, final float factor) {
1621         if (pool == null) {
1622             throw new IllegalArgumentException(MSG_NULL_POOL);
1623         }
1624         if (factor <= 0f) {
1625             throw new IllegalArgumentException(MSG_FACTOR_NEGATIVE);
1626         }
1627         return new ErodingObjectPool<>(pool, factor);
1628     }
1629 
1630     /**
1631      * Gets the {@code Timer} for checking keyedPool's idle count.
1632      *
1633      * @return the {@link Timer} for checking keyedPool's idle count.
1634      */
1635     private static Timer getMinIdleTimer() {
1636         return TimerHolder.MIN_IDLE_TIMER;
1637     }
1638 
1639     /**
1640      * Calls {@link KeyedObjectPool#addObject(Object)} on {@code keyedPool} with
1641      * each key in {@code keys} for {@code count} number of times. This has
1642      * the same effect as calling {@link #prefill(KeyedObjectPool, Object, int)}
1643      * for each key in the {@code keys} collection.
1644      *
1645      * @param keyedPool
1646      *            the keyedPool to prefill.
1647      * @param keys
1648      *            {@link Collection} of keys to add objects for.
1649      * @param count
1650      *            the number of idle objects to add for each {@code key}.
1651      * @param <K> the type of the pool key
1652      * @param <V> the type of pool entries
1653      * @throws Exception
1654      *             when {@link KeyedObjectPool#addObject(Object)} fails.
1655      * @throws IllegalArgumentException
1656      *             when {@code keyedPool}, {@code keys}, or any value in
1657      *             {@code keys} is {@code null}.
1658      * @see #prefill(KeyedObjectPool, Object, int)
1659      * @deprecated Use {@link KeyedObjectPool#addObjects(Collection, int)}.
1660      */
1661     @Deprecated
1662     public static <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool,
1663             final Collection<K> keys, final int count) throws Exception,
1664             IllegalArgumentException {
1665         if (keys == null) {
1666             throw new IllegalArgumentException(MSG_NULL_KEYS);
1667         }
1668         keyedPool.addObjects(keys, count);
1669     }
1670 
1671     /**
1672      * Calls {@link KeyedObjectPool#addObject(Object)} on {@code keyedPool} with
1673      * {@code key} {@code count} number of times.
1674      *
1675      * @param keyedPool
1676      *            the keyedPool to prefill.
1677      * @param key
1678      *            the key to add objects for.
1679      * @param count
1680      *            the number of idle objects to add for {@code key}.
1681      * @param <K> the type of the pool key
1682      * @param <V> the type of pool entries
1683      * @throws Exception
1684      *             when {@link KeyedObjectPool#addObject(Object)} fails.
1685      * @throws IllegalArgumentException
1686      *             when {@code keyedPool} or {@code key} is {@code null}.
1687      * @deprecated Use {@link KeyedObjectPool#addObjects(Object, int)}.
1688      */
1689     @Deprecated
1690     public static <K, V> void prefill(final KeyedObjectPool<K, V> keyedPool,
1691             final K key, final int count) throws Exception,
1692             IllegalArgumentException {
1693         if (keyedPool == null) {
1694             throw new IllegalArgumentException(MSG_NULL_KEYED_POOL);
1695         }
1696         keyedPool.addObjects(key, count);
1697     }
1698 
1699     /**
1700      * Calls {@link ObjectPool#addObject()} on {@code pool} {@code count} number
1701      * of times.
1702      *
1703      * @param pool
1704      *            the pool to prefill.
1705      * @param count
1706      *            the number of idle objects to add.
1707      * @param <T> the type of objects in the pool
1708      * @throws Exception
1709      *             when {@link ObjectPool#addObject()} fails.
1710      * @throws IllegalArgumentException
1711      *             when {@code pool} is {@code null}.
1712      * @deprecated Use {@link ObjectPool#addObjects(int)}.
1713      */
1714     @Deprecated
1715     public static <T> void prefill(final ObjectPool<T> pool, final int count)
1716             throws Exception {
1717         if (pool == null) {
1718             throw new IllegalArgumentException(MSG_NULL_POOL);
1719         }
1720         pool.addObjects(count);
1721     }
1722 
1723     /**
1724      * Returns a synchronized (thread-safe) KeyedPooledObjectFactory backed by
1725      * the specified KeyedPooledObjectFactory.
1726      *
1727      * @param keyedFactory
1728      *            the KeyedPooledObjectFactory to be "wrapped" in a
1729      *            synchronized KeyedPooledObjectFactory.
1730      * @param <K> the type of the pool key
1731      * @param <V> the type of pool entries
1732      * @return a synchronized view of the specified KeyedPooledObjectFactory.
1733      */
1734     public static <K, V> KeyedPooledObjectFactory<K, V> synchronizedKeyedPooledFactory(
1735         final KeyedPooledObjectFactory<K, V> keyedFactory) {
1736         return new SynchronizedKeyedPooledObjectFactory<>(keyedFactory);
1737     }
1738 
1739     /**
1740      * Returns a synchronized (thread-safe) KeyedObjectPool backed by the
1741      * specified KeyedObjectPool.
1742      * <p>
1743      * <strong>Note:</strong> This should not be used on pool implementations that already
1744      * provide proper synchronization such as the pools provided in the Commons
1745      * Pool library. Wrapping a pool that {@link #wait() waits} for poolable
1746      * objects to be returned before allowing another one to be borrowed with
1747      * another layer of synchronization will cause liveliness issues or a
1748      * deadlock.
1749      * </p>
1750      *
1751      * @param keyedPool
1752      *            the KeyedObjectPool to be "wrapped" in a synchronized
1753      *            KeyedObjectPool.
1754      * @param <K> the type of the pool key
1755      * @param <V> the type of pool entries
1756      * @return a synchronized view of the specified KeyedObjectPool.
1757      */
1758     public static <K, V> KeyedObjectPool<K, V> synchronizedPool(final KeyedObjectPool<K, V> keyedPool) {
1759         /*
1760          * assert !(keyedPool instanceof GenericKeyedObjectPool) :
1761          * "GenericKeyedObjectPool is already thread-safe"; assert !(keyedPool
1762          * instanceof StackKeyedObjectPool) :
1763          * "StackKeyedObjectPool is already thread-safe"; assert
1764          * !"org.apache.commons.pool.composite.CompositeKeyedObjectPool"
1765          * .equals(keyedPool.getClass().getName()) :
1766          * "CompositeKeyedObjectPools are already thread-safe";
1767          */
1768         return new SynchronizedKeyedObjectPool<>(keyedPool);
1769     }
1770 
1771     /**
1772      * Returns a synchronized (thread-safe) ObjectPool backed by the specified
1773      * ObjectPool.
1774      * <p>
1775      * <strong>Note:</strong> This should not be used on pool implementations that already
1776      * provide proper synchronization such as the pools provided in the Commons
1777      * Pool library. Wrapping a pool that {@link #wait() waits} for poolable
1778      * objects to be returned before allowing another one to be borrowed with
1779      * another layer of synchronization will cause liveliness issues or a
1780      * deadlock.
1781      * </p>
1782      *
1783      * @param <T> the type of objects in the pool
1784      * @param pool
1785      *            the ObjectPool to be "wrapped" in a synchronized ObjectPool.
1786      * @throws IllegalArgumentException
1787      *             when {@code pool} is {@code null}.
1788      * @return a synchronized view of the specified ObjectPool.
1789      */
1790     public static <T> ObjectPool<T> synchronizedPool(final ObjectPool<T> pool) {
1791         if (pool == null) {
1792             throw new IllegalArgumentException(MSG_NULL_POOL);
1793         }
1794 
1795         /*
1796          * assert !(pool instanceof GenericObjectPool) :
1797          * "GenericObjectPool is already thread-safe"; assert !(pool instanceof
1798          * SoftReferenceObjectPool) :
1799          * "SoftReferenceObjectPool is already thread-safe"; assert !(pool
1800          * instanceof StackObjectPool) :
1801          * "StackObjectPool is already thread-safe"; assert
1802          * !"org.apache.commons.pool.composite.CompositeObjectPool"
1803          * .equals(pool.getClass().getName()) :
1804          * "CompositeObjectPools are already thread-safe";
1805          */
1806         return new SynchronizedObjectPool<>(pool);
1807     }
1808 
1809     /**
1810      * Returns a synchronized (thread-safe) PooledObjectFactory backed by the
1811      * specified PooledObjectFactory.
1812      *
1813      * @param factory
1814      *            the PooledObjectFactory to be "wrapped" in a synchronized
1815      *            PooledObjectFactory.
1816      * @param <T> the type of objects in the pool
1817      * @return a synchronized view of the specified PooledObjectFactory.
1818      */
1819     public static <T> PooledObjectFactory<T> synchronizedPooledFactory(final PooledObjectFactory<T> factory) {
1820         return new SynchronizedPooledObjectFactory<>(factory);
1821     }
1822 
1823     /**
1824      * PoolUtils instances should NOT be constructed in standard programming.
1825      * Instead, the class should be used procedurally: PoolUtils.adapt(aPool);.
1826      * This constructor is public to permit tools that require a JavaBean
1827      * instance to operate.
1828      */
1829     public PoolUtils() {
1830     }
1831 }