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