/* * Copyright 2006 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.frameworkset.commons.pool; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.Timer; import java.util.TimerTask; /** * This class consists exclusively of static methods that operate on or return keyedPool related interfaces. * * @author Sandy McArthur * @version $Revision: 385296 $ $Date: 2006-03-12 10:28:08 -0500 (Sun, 12 Mar 2006) $ * @since Pool 1.3 */ public final class PoolUtils { /** * Timer used to periodically check pools idle object count. * Because a {@link Timer} creates a {@link Thread} this is lazily instantiated. */ private static Timer MIN_IDLE_TIMER; /** * PoolUtils instances should NOT be constructed in standard programming. * Instead, the class should be used procedurally: PoolUtils.adapt(aPool);. * This constructor is public to permit tools that require a JavaBean instance to operate. */ public PoolUtils() { } /** * Adapt a <code>KeyedPoolableObjectFactory</code> instance to work where a <code>PoolableObjectFactory</code> is * needed. This method is the equivalent of calling * {@link #adapt(KeyedPoolableObjectFactory, Object) PoolUtils.adapt(aKeyedPoolableObjectFactory, new Object())}. * * @param keyedFactory the {@link KeyedPoolableObjectFactory} to delegate to. * @return a {@link PoolableObjectFactory} that delegates to <code>keyedFactory</code> with an internal key. * @throws IllegalArgumentException when <code>keyedFactory</code> is <code>null</code>. * @see #adapt(KeyedPoolableObjectFactory, Object) * @since Pool 1.3 */ public static PoolableObjectFactory adapt(final KeyedPoolableObjectFactory keyedFactory) throws IllegalArgumentException { return adapt(keyedFactory, new Object()); } /** * Adapt a <code>KeyedPoolableObjectFactory</code> instance to work where a <code>PoolableObjectFactory</code> is * needed using the specified <code>key</code> when delegating. * * @param keyedFactory the {@link KeyedPoolableObjectFactory} to delegate to. * @param key the key to use when delegating. * @return a {@link PoolableObjectFactory} that delegates to <code>keyedFactory</code> with the specified key. * @throws IllegalArgumentException when <code>keyedFactory</code> or <code>key</code> is <code>null</code>. * @see #adapt(KeyedPoolableObjectFactory) * @since Pool 1.3 */ public static PoolableObjectFactory adapt(final KeyedPoolableObjectFactory keyedFactory, final Object key) throws IllegalArgumentException { return new PoolableObjectFactoryAdaptor(keyedFactory, key); } /** * Adapt a <code>PoolableObjectFactory</code> instance to work where a <code>KeyedPoolableObjectFactory</code> is * needed. The key is ignored. * * @param factory the {@link PoolableObjectFactory} to delegate to. * @return a {@link KeyedPoolableObjectFactory} that delegates to <code>factory</code> ignoring the key. * @throws IllegalArgumentException when <code>factory</code> is <code>null</code>. * @since Pool 1.3 */ public static KeyedPoolableObjectFactory adapt(final PoolableObjectFactory factory) throws IllegalArgumentException { return new KeyedPoolableObjectFactoryAdaptor(factory); } /** * Adapt a <code>KeyedObjectPool</code> instance to work where an <code>ObjectPool</code> is needed. This is the * equivalent of calling {@link #adapt(KeyedObjectPool, Object) PoolUtils.adapt(aKeyedObjectPool, new Object())}. * * @param keyedPool the {@link KeyedObjectPool} to delegate to. * @return an {@link ObjectPool} that delegates to <code>keyedPool</code> with an internal key. * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code>. * @see #adapt(KeyedObjectPool, Object) * @since Pool 1.3 */ public static ObjectPool adapt(final KeyedObjectPool keyedPool) throws IllegalArgumentException { return adapt(keyedPool, new Object()); } /** * Adapt a <code>KeyedObjectPool</code> instance to work where an <code>ObjectPool</code> is needed using the * specified <code>key</code> when delegating. * * @param keyedPool the {@link KeyedObjectPool} to delegate to. * @param key the key to use when delegating. * @return an {@link ObjectPool} that delegates to <code>keyedPool</code> with the specified key. * @throws IllegalArgumentException when <code>keyedPool</code> or <code>key</code> is <code>null</code>. * @see #adapt(KeyedObjectPool) * @since Pool 1.3 */ public static ObjectPool adapt(final KeyedObjectPool keyedPool, final Object key) throws IllegalArgumentException { return new ObjectPoolAdaptor(keyedPool, key); } /** * Adapt an <code>ObjectPool</code> to work where an <code>KeyedObjectPool</code> is needed. * The key is ignored. * * @param pool the {@link ObjectPool} to delegate to. * @return a {@link KeyedObjectPool} that delegates to <code>keyedPool</code> ignoring the key. * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code>. * @since Pool 1.3 */ public static KeyedObjectPool adapt(final ObjectPool pool) throws IllegalArgumentException { return new KeyedObjectPoolAdaptor(pool); } /** * Wraps an <code>ObjectPool</code> and dynamically checks the type of objects borrowed and returned to the keyedPool. * If an object is passed to the keyedPool that isn't of type <code>type</code> a {@link ClassCastException} will be thrown. * * @param pool the keyedPool to enforce type safety on * @return an <code>ObjectPool</code> that will only allow objects of <code>type</code> * @since Pool 1.3 */ public static ObjectPool checkedPool(final ObjectPool pool, final Class type) { if (pool == null) { throw new IllegalArgumentException("pool must not be null."); } if (type == null) { throw new IllegalArgumentException("type must not be null."); } return new CheckedObjectPool(pool, type); } /** * Wraps an <code>KeyedObjectPool</code> and dynamically checks the type of objects borrowed and returned to the keyedPool. * If an object is passed to the keyedPool that isn't of type <code>type</code> a {@link ClassCastException} will be thrown. * * @param keyedPool the keyedPool to enforce type safety on * @return an <code>KeyedObjectPool</code> that will only allow objects of <code>type</code> * @since Pool 1.3 */ public static KeyedObjectPool checkedPool(final KeyedObjectPool keyedPool, final Class type) { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (type == null) { throw new IllegalArgumentException("type must not be null."); } return new CheckedKeyedObjectPool(keyedPool, type); } /** * Periodically check the idle object count for the keyedPool. At most one idle object will be added per period. * If there is an exception when calling {@link ObjectPool#addObject()} then no more checks will be performed. * * @param pool the keyedPool to check periodically. * @param minIdle if the {@link ObjectPool#getNumIdle()} is less than this then add an idle object. * @param period the frequency to check the number of idle objects in a keyedPool, see * {@link Timer#schedule(TimerTask, long, long)}. * @return the {@link TimerTask} that will periodically check the pools idle object count. * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code> or * when <code>minIdle</code> is negative or when <code>period</code> isn't * valid for {@link Timer#schedule(TimerTask, long, long)}. * @since Pool 1.3 */ public static TimerTask checkMinIdle(final ObjectPool pool, final int minIdle, final long period) throws IllegalArgumentException { if (pool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (minIdle < 0) { throw new IllegalArgumentException("minIdle must be non-negative."); } final TimerTask task = new ObjectPoolMinIdleTimerTask(pool, minIdle); getMinIdleTimer().schedule(task, 0L, period); return task; } /** * Periodically check the idle object count for the key in the keyedPool. At most one idle object will be added per period. * If there is an exception when calling {@link KeyedObjectPool#addObject(Object)} then no more checks for that key * will be performed. * * @param keyedPool the keyedPool to check periodically. * @param key the key to check the idle count of. * @param minIdle if the {@link KeyedObjectPool#getNumIdle(Object)} is less than this then add an idle object. * @param period the frequency to check the number of idle objects in a keyedPool, see * {@link Timer#schedule(TimerTask, long, long)}. * @return the {@link TimerTask} that will periodically check the pools idle object count. * @throws IllegalArgumentException when <code>keyedPool</code>, <code>key</code> is <code>null</code> or * when <code>minIdle</code> is negative or when <code>period</code> isn't * valid for {@link Timer#schedule(TimerTask, long, long)}. * @since Pool 1.3 */ public static TimerTask checkMinIdle(final KeyedObjectPool keyedPool, final Object key, final int minIdle, final long period) throws IllegalArgumentException { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (key == null) { throw new IllegalArgumentException("key must not be null."); } if (minIdle < 0) { throw new IllegalArgumentException("minIdle must be non-negative."); } final TimerTask task = new KeyedObjectPoolMinIdleTimerTask(keyedPool, key, minIdle); getMinIdleTimer().schedule(task, 0L, period); return task; } /** * Periodically check the idle object count for each key in the <code>Collection</code> <code>keys</code> in the keyedPool. * At most one idle object will be added per period. * * @param keyedPool the keyedPool to check periodically. * @param keys a collection of keys to check the idle object count. * @param minIdle if the {@link KeyedObjectPool#getNumIdle(Object)} is less than this then add an idle object. * @param period the frequency to check the number of idle objects in a keyedPool, see * {@link Timer#schedule(TimerTask, long, long)}. * @return a {@link Map} of key and {@link TimerTask} pairs that will periodically check the pools idle object count. * @throws IllegalArgumentException when <code>keyedPool</code>, <code>keys</code>, or any of the values in the * collection is <code>null</code> or when <code>minIdle</code> is negative or when <code>period</code> isn't * valid for {@link Timer#schedule(TimerTask, long, long)}. * @see #checkMinIdle(KeyedObjectPool, Object, int, long) * @since Pool 1.3 */ public static Map checkMinIdle(final KeyedObjectPool keyedPool, final Collection keys, final int minIdle, final long period) throws IllegalArgumentException { if (keys == null) { throw new IllegalArgumentException("keys must not be null."); } final Map tasks = new HashMap(keys.size()); final Iterator iter = keys.iterator(); while (iter.hasNext()) { final Object key = iter.next(); final TimerTask task = checkMinIdle(keyedPool, key, minIdle, period); tasks.put(key, task); } return tasks; } /** * Call <code>addObject()</code> on <code>keyedPool</code> <code>count</code> number of times. * * @param pool the keyedPool to prefill. * @param count the number of idle objects to add. * @throws Exception when {@link ObjectPool#addObject()} fails. * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code>. * @since Pool 1.3 */ public static void prefill(final ObjectPool pool, final int count) throws Exception, IllegalArgumentException { if (pool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } for (int i = 0; i < count; i++) { pool.addObject(); } } /** * Call <code>addObject(Object)</code> on <code>keyedPool</code> with <code>key</code> <code>count</code> * number of times. * * @param keyedPool the keyedPool to prefill. * @param key the key to add objects for. * @param count the number of idle objects to add for <code>key</code>. * @throws Exception when {@link KeyedObjectPool#addObject(Object)} fails. * @throws IllegalArgumentException when <code>keyedPool</code> or <code>key</code> is <code>null</code>. * @since Pool 1.3 */ public static void prefill(final KeyedObjectPool keyedPool, final Object key, final int count) throws Exception, IllegalArgumentException { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (key == null) { throw new IllegalArgumentException("key must not be null."); } for (int i = 0; i < count; i++) { keyedPool.addObject(key); } } /** * Call <code>addObject(Object)</code> on <code>keyedPool</code> with each key in <code>keys</code> for * <code>count</code> number of times. This has the same effect as calling * {@link #prefill(KeyedObjectPool, Object, int)} for each key in the <code>keys</code> collection. * * @param keyedPool the keyedPool to prefill. * @param keys {@link Collection} of keys to add objects for. * @param count the number of idle objects to add for each <code>key</code>. * @throws Exception when {@link KeyedObjectPool#addObject(Object)} fails. * @throws IllegalArgumentException when <code>keyedPool</code>, <code>keys</code>, or * any value in <code>keys</code> is <code>null</code>. * @see #prefill(KeyedObjectPool, Object, int) * @since Pool 1.3 */ public static void prefill(final KeyedObjectPool keyedPool, final Collection keys, final int count) throws Exception, IllegalArgumentException { if (keys == null) { throw new IllegalArgumentException("keys must not be null."); } final Iterator iter = keys.iterator(); while (iter.hasNext()) { prefill(keyedPool, iter.next(), count); } } /** * Returns a synchronized (thread-safe) ObjectPool backed by the specified ObjectPool. * * @param pool the ObjectPool to be "wrapped" in a synchronized ObjectPool. * @return a synchronized view of the specified ObjectPool. * @since Pool 1.3 */ public static ObjectPool synchronizedPool(final ObjectPool pool) { return new SynchronizedObjectPool(pool); } /** * Returns a synchronized (thread-safe) KeyedObjectPool backed by the specified KeyedObjectPool. * * @param keyedPool the KeyedObjectPool to be "wrapped" in a synchronized KeyedObjectPool. * @return a synchronized view of the specified KeyedObjectPool. * @since Pool 1.3 */ public static KeyedObjectPool synchronizedPool(final KeyedObjectPool keyedPool) { return new SynchronizedKeyedObjectPool(keyedPool); } /** * Returns a synchronized (thread-safe) PoolableObjectFactory backed by the specified PoolableObjectFactory. * * @param factory the PoolableObjectFactory to be "wrapped" in a synchronized PoolableObjectFactory. * @return a synchronized view of the specified PoolableObjectFactory. * @since Pool 1.3 */ public static PoolableObjectFactory synchronizedPoolableFactory(final PoolableObjectFactory factory) { return new SynchronizedPoolableObjectFactory(factory); } /** * Returns a synchronized (thread-safe) KeyedPoolableObjectFactory backed by the specified KeyedPoolableObjectFactory. * * @param keyedFactory the KeyedPoolableObjectFactory to be "wrapped" in a synchronized KeyedPoolableObjectFactory. * @return a synchronized view of the specified KeyedPoolableObjectFactory. * @since Pool 1.3 */ public static KeyedPoolableObjectFactory synchronizedPoolableFactory(final KeyedPoolableObjectFactory keyedFactory) { return new SynchronizedKeyedPoolableObjectFactory(keyedFactory); } /** * Get the <code>Timer</code> for checking keyedPool's idle count. Lazily create the {@link Timer} as needed. * * @return the {@link Timer} for checking keyedPool's idle count. * @since Pool 1.3 */ private static synchronized Timer getMinIdleTimer() { if (MIN_IDLE_TIMER == null) { MIN_IDLE_TIMER = new Timer(true); } return MIN_IDLE_TIMER; } private static class PoolableObjectFactoryAdaptor implements PoolableObjectFactory { private final Object key; private final KeyedPoolableObjectFactory keyedFactory; PoolableObjectFactoryAdaptor(final KeyedPoolableObjectFactory keyedFactory, final Object key) throws IllegalArgumentException { if (keyedFactory == null) { throw new IllegalArgumentException("keyedFactory must not be null."); } if (key == null) { throw new IllegalArgumentException("key must not be null."); } this.keyedFactory = keyedFactory; this.key = key; } public Object makeObject() throws Exception { return keyedFactory.makeObject(key); } public void destroyObject(final Object obj) throws Exception { keyedFactory.destroyObject(key, obj); } public boolean validateObject(final Object obj) { return keyedFactory.validateObject(key, obj); } public void activateObject(final Object obj) throws Exception { keyedFactory.activateObject(key, obj); } public void passivateObject(final Object obj) throws Exception { keyedFactory.passivateObject(key, obj); } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("PoolableObjectFactoryAdaptor"); sb.append("{key=").append(key); sb.append(", keyedFactory=").append(keyedFactory); sb.append('}'); return sb.toString(); } } private static class KeyedPoolableObjectFactoryAdaptor implements KeyedPoolableObjectFactory { private final PoolableObjectFactory factory; KeyedPoolableObjectFactoryAdaptor(final PoolableObjectFactory factory) throws IllegalArgumentException { if (factory == null) { throw new IllegalArgumentException("factory must not be null."); } this.factory = factory; } public Object makeObject(final Object key) throws Exception { return factory.makeObject(); } public void destroyObject(final Object key, final Object obj) throws Exception { factory.destroyObject(obj); } public boolean validateObject(final Object key, final Object obj) { return factory.validateObject(obj); } public void activateObject(final Object key, final Object obj) throws Exception { factory.activateObject(obj); } public void passivateObject(final Object key, final Object obj) throws Exception { factory.passivateObject(obj); } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("KeyedPoolableObjectFactoryAdaptor"); sb.append("{factory=").append(factory); sb.append('}'); return sb.toString(); } } private static class ObjectPoolAdaptor implements ObjectPool { private final Object key; private final KeyedObjectPool keyedPool; ObjectPoolAdaptor(final KeyedObjectPool keyedPool, final Object key) throws IllegalArgumentException { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (key == null) { throw new IllegalArgumentException("key must not be null."); } this.keyedPool = keyedPool; this.key = key; } public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException { return keyedPool.borrowObject(key); } public void returnObject(final Object obj) throws Exception { keyedPool.returnObject(key, obj); } public void invalidateObject(final Object obj) throws Exception { keyedPool.invalidateObject(key, obj); } public void addObject() throws Exception, IllegalStateException { keyedPool.addObject(key); } public int getNumIdle() throws UnsupportedOperationException { return keyedPool.getNumIdle(key); } public int getNumActive() throws UnsupportedOperationException { return keyedPool.getNumActive(key); } public void clear() throws Exception, UnsupportedOperationException { keyedPool.clear(); } public void close() throws Exception { keyedPool.close(); } public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { keyedPool.setFactory(adapt(factory)); } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("ObjectPoolAdaptor"); sb.append("{key=").append(key); sb.append(", keyedPool=").append(keyedPool); sb.append('}'); return sb.toString(); } } private static class KeyedObjectPoolAdaptor implements KeyedObjectPool { private final ObjectPool pool; KeyedObjectPoolAdaptor(final ObjectPool pool) throws IllegalArgumentException { if (pool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } this.pool = pool; } public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException { return pool.borrowObject(); } public void returnObject(final Object key, final Object obj) throws Exception { pool.returnObject(obj); } public void invalidateObject(final Object key, final Object obj) throws Exception { pool.invalidateObject(obj); } public void addObject(final Object key) throws Exception, IllegalStateException { pool.addObject(); } public int getNumIdle(final Object key) throws UnsupportedOperationException { return pool.getNumIdle(); } public int getNumActive(final Object key) throws UnsupportedOperationException { return pool.getNumActive(); } public int getNumIdle() throws UnsupportedOperationException { return pool.getNumIdle(); } public int getNumActive() throws UnsupportedOperationException { return pool.getNumActive(); } public void clear() throws Exception, UnsupportedOperationException { pool.clear(); } public void clear(final Object key) throws Exception, UnsupportedOperationException { pool.clear(); } public void close() throws Exception { pool.close(); } public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { pool.setFactory(adapt(factory)); } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("KeyedObjectPoolAdaptor"); sb.append("{keyedPool=").append(pool); sb.append('}'); return sb.toString(); } } private static class CheckedObjectPool implements ObjectPool { private final Class type; private final ObjectPool pool; CheckedObjectPool(final ObjectPool pool, final Class type) { if (pool == null) { throw new IllegalArgumentException("pool must not be null."); } if (type == null) { throw new IllegalArgumentException("type must not be null."); } this.pool = pool; this.type = type; } public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException { final Object obj = pool.borrowObject(); if (type.isInstance(obj)) { return obj; } else { throw new ClassCastException("Borrowed object is not of type: " + type.getName() + " was: " + obj); } } public void returnObject(final Object obj) throws Exception { if (type.isInstance(obj)) { pool.returnObject(obj); } else { throw new ClassCastException("Returned object is not of type: " + type.getName() + " was: " + obj); } } public void invalidateObject(final Object obj) throws Exception { if (type.isInstance(obj)) { pool.invalidateObject(obj); } else { throw new ClassCastException("Invalidated object is not of type: " + type.getName() + " was: " + obj); } } public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException { pool.addObject(); } public int getNumIdle() throws UnsupportedOperationException { return pool.getNumIdle(); } public int getNumActive() throws UnsupportedOperationException { return pool.getNumActive(); } public void clear() throws Exception, UnsupportedOperationException { pool.clear(); } public void close() throws Exception { pool.close(); } public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { pool.setFactory(factory); } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("CheckedObjectPool"); sb.append("{type=").append(type); sb.append(", keyedPool=").append(pool); sb.append('}'); return sb.toString(); } } private static class CheckedKeyedObjectPool implements KeyedObjectPool { private final Class type; private final KeyedObjectPool keyedPool; CheckedKeyedObjectPool(final KeyedObjectPool keyedPool, final Class type) { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } if (type == null) { throw new IllegalArgumentException("type must not be null."); } this.keyedPool = keyedPool; this.type = type; } public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException { Object obj = keyedPool.borrowObject(key); if (type.isInstance(obj)) { return obj; } else { throw new ClassCastException("Borrowed object for key: " + key + " is not of type: " + type.getName() + " was: " + obj); } } public void returnObject(final Object key, final Object obj) throws Exception { if (type.isInstance(obj)) { keyedPool.returnObject(key, obj); } else { throw new ClassCastException("Returned object for key: " + key + " is not of type: " + type.getName() + " was: " + obj); } } public void invalidateObject(final Object key, final Object obj) throws Exception { if (type.isInstance(obj)) { keyedPool.invalidateObject(key, obj); } else { throw new ClassCastException("Invalidated object for key: " + key + " is not of type: " + type.getName() + " was: " + obj); } } public void addObject(final Object key) throws Exception, IllegalStateException, UnsupportedOperationException { keyedPool.addObject(key); } public int getNumIdle(final Object key) throws UnsupportedOperationException { return keyedPool.getNumIdle(key); } public int getNumActive(final Object key) throws UnsupportedOperationException { return keyedPool.getNumActive(key); } public int getNumIdle() throws UnsupportedOperationException { return keyedPool.getNumIdle(); } public int getNumActive() throws UnsupportedOperationException { return keyedPool.getNumActive(); } public void clear() throws Exception, UnsupportedOperationException { keyedPool.clear(); } public void clear(final Object key) throws Exception, UnsupportedOperationException { keyedPool.clear(key); } public void close() throws Exception { keyedPool.close(); } public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { keyedPool.setFactory(factory); } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("CheckedKeyedObjectPool"); sb.append("{type=").append(type); sb.append(", keyedPool=").append(keyedPool); sb.append('}'); return sb.toString(); } } private static class ObjectPoolMinIdleTimerTask extends TimerTask { private final int minIdle; private final ObjectPool pool; ObjectPoolMinIdleTimerTask(final ObjectPool pool, final int minIdle) throws IllegalArgumentException { if (pool == null) { throw new IllegalArgumentException("poll must not be null."); } this.pool = pool; this.minIdle = minIdle; } public void run() { boolean success = false; try { if (pool.getNumIdle() < minIdle) { pool.addObject(); } success = true; } catch (Exception e) { cancel(); } finally { // detect other types of Throwable and cancel this Timer if (!success) { cancel(); } } } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("ObjectPoolMinIdleTimerTask"); sb.append("{minIdle=").append(minIdle); sb.append(", keyedPool=").append(pool); sb.append('}'); return sb.toString(); } } private static class KeyedObjectPoolMinIdleTimerTask extends TimerTask { private final int minIdle; private final Object key; private final KeyedObjectPool pool; KeyedObjectPoolMinIdleTimerTask(final KeyedObjectPool pool, final Object key, final int minIdle) throws IllegalArgumentException { if (pool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } this.pool = pool; this.key = key; this.minIdle = minIdle; } public void run() { boolean success = false; try { if (pool.getNumIdle(key) < minIdle) { pool.addObject(key); } success = true; } catch (Exception e) { cancel(); } finally { // detect other types of Throwable and cancel this Timer if (!success) { cancel(); } } } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("KeyedObjectPoolMinIdleTimerTask"); sb.append("{minIdle=").append(minIdle); sb.append(", key=").append(key); sb.append(", keyedPool=").append(pool); sb.append('}'); return sb.toString(); } } private static class SynchronizedObjectPool implements ObjectPool { private final Object lock; private final ObjectPool pool; SynchronizedObjectPool(final ObjectPool pool) throws IllegalArgumentException { if (pool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } this.pool = pool; lock = new Object(); } public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException { synchronized (lock) { return pool.borrowObject(); } } public void returnObject(final Object obj) throws Exception { synchronized (lock) { pool.returnObject(obj); } } public void invalidateObject(final Object obj) throws Exception { synchronized (lock) { pool.invalidateObject(obj); } } public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException { synchronized (lock) { pool.addObject(); } } public int getNumIdle() throws UnsupportedOperationException { synchronized (lock) { return pool.getNumIdle(); } } public int getNumActive() throws UnsupportedOperationException { synchronized (lock) { return pool.getNumActive(); } } public void clear() throws Exception, UnsupportedOperationException { synchronized (lock) { pool.clear(); } } public void close() throws Exception { synchronized (lock) { pool.close(); } } public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { synchronized (lock) { pool.setFactory(factory); } } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("SynchronizedObjectPool"); sb.append("{keyedPool=").append(pool); sb.append('}'); return sb.toString(); } } private static class SynchronizedKeyedObjectPool implements KeyedObjectPool { private final Object lock; private final KeyedObjectPool keyedPool; SynchronizedKeyedObjectPool(final KeyedObjectPool keyedPool) throws IllegalArgumentException { if (keyedPool == null) { throw new IllegalArgumentException("keyedPool must not be null."); } this.keyedPool = keyedPool; lock = new Object(); } public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException { synchronized (lock) { return keyedPool.borrowObject(key); } } public void returnObject(final Object key, final Object obj) throws Exception { synchronized (lock) { keyedPool.returnObject(key, obj); } } public void invalidateObject(final Object key, final Object obj) throws Exception { synchronized (lock) { keyedPool.invalidateObject(key, obj); } } public void addObject(final Object key) throws Exception, IllegalStateException, UnsupportedOperationException { synchronized (lock) { keyedPool.addObject(key); } } public int getNumIdle(final Object key) throws UnsupportedOperationException { synchronized (lock) { return keyedPool.getNumIdle(key); } } public int getNumActive(final Object key) throws UnsupportedOperationException { synchronized (lock) { return keyedPool.getNumActive(key); } } public int getNumIdle() throws UnsupportedOperationException { synchronized (lock) { return keyedPool.getNumIdle(); } } public int getNumActive() throws UnsupportedOperationException { synchronized (lock) { return keyedPool.getNumActive(); } } public void clear() throws Exception, UnsupportedOperationException { synchronized (lock) { keyedPool.clear(); } } public void clear(final Object key) throws Exception, UnsupportedOperationException { synchronized (lock) { keyedPool.clear(key); } } public void close() throws Exception { synchronized (lock) { keyedPool.close(); } } public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { synchronized (lock) { keyedPool.setFactory(factory); } } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("SynchronizedKeyedObjectPool"); sb.append("{keyedPool=").append(keyedPool); sb.append('}'); return sb.toString(); } } private static class SynchronizedPoolableObjectFactory implements PoolableObjectFactory { private final Object lock; private final PoolableObjectFactory factory; SynchronizedPoolableObjectFactory(final PoolableObjectFactory factory) throws IllegalArgumentException { if (factory == null) { throw new IllegalArgumentException("factory must not be null."); } this.factory = factory; lock = new Object(); } public Object makeObject() throws Exception { synchronized (lock) { return factory.makeObject(); } } public void destroyObject(final Object obj) throws Exception { synchronized (lock) { factory.destroyObject(obj); } } public boolean validateObject(final Object obj) { synchronized (lock) { return factory.validateObject(obj); } } public void activateObject(final Object obj) throws Exception { synchronized (lock) { factory.activateObject(obj); } } public void passivateObject(final Object obj) throws Exception { synchronized (lock) { factory.passivateObject(obj); } } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("SynchronizedPoolableObjectFactory"); sb.append("{factory=").append(factory); sb.append('}'); return sb.toString(); } } private static class SynchronizedKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory { private final Object lock; private final KeyedPoolableObjectFactory keyedFactory; SynchronizedKeyedPoolableObjectFactory(final KeyedPoolableObjectFactory keyedFactory) throws IllegalArgumentException { if (keyedFactory == null) { throw new IllegalArgumentException("keyedFactory must not be null."); } this.keyedFactory = keyedFactory; lock = new Object(); } public Object makeObject(final Object key) throws Exception { synchronized (lock) { return keyedFactory.makeObject(key); } } public void destroyObject(final Object key, final Object obj) throws Exception { synchronized (lock) { keyedFactory.destroyObject(key, obj); } } public boolean validateObject(final Object key, final Object obj) { synchronized (lock) { return keyedFactory.validateObject(key, obj); } } public void activateObject(final Object key, final Object obj) throws Exception { synchronized (lock) { keyedFactory.activateObject(key, obj); } } public void passivateObject(final Object key, final Object obj) throws Exception { synchronized (lock) { keyedFactory.passivateObject(key, obj); } } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("SynchronizedKeyedPoolableObjectFactory"); sb.append("{keyedFactory=").append(keyedFactory); sb.append('}'); return sb.toString(); } } }