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