Author: sandymac
Date: Fri Mar  3 21:42:18 2006
New Revision: 383042

URL: http://svn.apache.org/viewcvs?rev=383042&view=rev
Log:
A collection of utility methods for pool, à la java.util.Collections.

Added:
    
jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/Pools.java
    
jakarta/commons/proper/pool/trunk/src/test/org/apache/commons/pool/TestPools.java

Added: 
jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/Pools.java
URL: 
http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/Pools.java?rev=383042&view=auto
==============================================================================
--- 
jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/Pools.java 
(added)
+++ 
jakarta/commons/proper/pool/trunk/src/java/org/apache/commons/pool/Pools.java 
Fri Mar  3 21:42:18 2006
@@ -0,0 +1,885 @@
+/*
+ * 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 org.apache.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 
pool related interfaces.
+ *
+ * @author Sandy McArthur
+ * @version $Revision$ $Date$
+ */
+public final class Pools {
+
+    /**
+     * Timer used to periodically check pools idle object count.
+     * Because a [EMAIL PROTECTED] Timer} creates a [EMAIL PROTECTED] Thread} 
this is lazily instantiated.
+     */
+    private static Timer MIN_IDLE_TIMER;
+
+    /**
+     * Prevent instantiation.
+     */
+    private Pools() {
+    }
+
+    /**
+     * Adapt a <code>KeyedPoolableObjectFactory</code> instance to work where 
a <code>PoolableObjectFactory</code> is
+     * needed. This method is the equivalent of calling
+     * [EMAIL PROTECTED] #adapt(KeyedPoolableObjectFactory, Object) 
Pools.adapt(aKeyedPoolableObjectFactory, new Object())}.
+     *
+     * @param keyedFactory the [EMAIL PROTECTED] KeyedPoolableObjectFactory} 
to delegate to.
+     * @return a [EMAIL PROTECTED] 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)
+     */
+    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 [EMAIL PROTECTED] KeyedPoolableObjectFactory} 
to delegate to.
+     * @param key the key to use when delegating.
+     * @return a [EMAIL PROTECTED] 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)
+     */
+    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 [EMAIL PROTECTED] PoolableObjectFactory} to delegate 
to.
+     * @return a [EMAIL PROTECTED] KeyedPoolableObjectFactory} that delegates 
to <code>factory</code> ignoring the key.
+     * @throws IllegalArgumentException when <code>factory</code> is 
<code>null</code>.
+     */
+    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 [EMAIL PROTECTED] #adapt(KeyedObjectPool, Object) 
Pools.adapt(aKeyedObjectPool, new Object())}.
+     *
+     * @param keyedPool the [EMAIL PROTECTED] KeyedObjectPool} to delegate to.
+     * @return an [EMAIL PROTECTED] 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)
+     */
+    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 [EMAIL PROTECTED] KeyedObjectPool} to delegate to.
+     * @param key the key to use when delegating.
+     * @return an [EMAIL PROTECTED] 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)
+     */
+    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 [EMAIL PROTECTED] ObjectPool} to delegate to.
+     * @return a [EMAIL PROTECTED] KeyedObjectPool} that delegates to 
<code>pool</code> ignoring the key.
+     * @throws IllegalArgumentException when <code>pool</code> is 
<code>null</code>.
+     */
+    public static KeyedObjectPool adapt(final ObjectPool pool) throws 
IllegalArgumentException {
+        return new KeyedObjectPoolAdaptor(pool);
+    }
+
+    /**
+     * Periodically check the idle object count for the pool. At most one idle 
object will be added per period.
+     * If there is an exception when calling [EMAIL PROTECTED] 
ObjectPool#addObject()} then no more checks will be performed.
+     *
+     * @param pool the pool to check periodically.
+     * @param minIdle if the [EMAIL PROTECTED] ObjectPool#getNumIdle()} is 
less than this then add an idle object.
+     * @param period the frequency to check the number of idle objects in a 
pool, see
+     *      [EMAIL PROTECTED] Timer#schedule(TimerTask, long, long)}.
+     * @return the [EMAIL PROTECTED] TimerTask} that will periodically check 
the pools idle object count.
+     * @throws IllegalArgumentException when <code>pool</code> is 
<code>null</code> or
+     *      when <code>minIdle</code> is negative or when <code>period</code> 
isn't
+     *      valid for [EMAIL PROTECTED] Timer#schedule(TimerTask, long, long)}.
+     */
+    public static TimerTask checkMinIdle(final ObjectPool pool, final int 
minIdle, final long period) throws IllegalArgumentException {
+        if (pool == null) {
+            throw new IllegalArgumentException("pool 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 pool. At 
most one idle object will be added per period.
+     * If there is an exception when calling [EMAIL PROTECTED] 
KeyedObjectPool#addObject(Object)} then no more checks for that key
+     * will be performed.
+     *
+     * @param keyedPool the pool to check periodically.
+     * @param key the key to check the idle count of.
+     * @param minIdle if the [EMAIL PROTECTED] 
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 
pool, see
+     *      [EMAIL PROTECTED] Timer#schedule(TimerTask, long, long)}.
+     * @return the [EMAIL PROTECTED] 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 [EMAIL PROTECTED] Timer#schedule(TimerTask, long, long)}.
+     */
+    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 pool.
+     * At most one idle object will be added per period.
+     *
+     * @param keyedPool the pool to check periodically.
+     * @param keys a collection of keys to check the idle object count.
+     * @param minIdle if the [EMAIL PROTECTED] 
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 
pool, see
+     *      [EMAIL PROTECTED] Timer#schedule(TimerTask, long, long)}.
+     * @return a [EMAIL PROTECTED] Map} of key and [EMAIL PROTECTED] 
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 [EMAIL PROTECTED] Timer#schedule(TimerTask, long, long)}.
+     * @see #checkMinIdle(KeyedObjectPool, Object, int, long)
+     */
+    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>pool</code> <code>count</code> 
number of times.
+     *
+     * @param pool the pool to prefill.
+     * @param count the number of idle objects to add.
+     * @throws Exception when [EMAIL PROTECTED] ObjectPool#addObject()} fails.
+     * @throws IllegalArgumentException when <code>pool</code> is 
<code>null</code>.
+     */
+    public static void prefill(final ObjectPool pool, final int count) throws 
Exception, IllegalArgumentException {
+        if (pool == null) {
+            throw new IllegalArgumentException("pool 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 pool 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 [EMAIL PROTECTED] 
KeyedObjectPool#addObject(Object)} fails.
+     * @throws IllegalArgumentException when <code>keyedPool</code> or 
<code>key</code> is <code>null</code>.
+     */
+    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
+     * [EMAIL PROTECTED] #prefill(KeyedObjectPool, Object, int)} for each key 
in the <code>keys</code> collection.
+     *
+     * @param keyedPool the pool to prefill.
+     * @param keys [EMAIL PROTECTED] Collection} of keys to add objects for.
+     * @param count the number of idle objects to add for each 
<code>key</code>.
+     * @throws Exception when [EMAIL PROTECTED] 
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)
+     */
+    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.
+     */
+    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.
+     */
+    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.
+     */
+    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.
+     */
+    public static KeyedPoolableObjectFactory synchronizedPoolableFactory(final 
KeyedPoolableObjectFactory keyedFactory) {
+        return new SynchronizedKeyedPoolableObjectFactory(keyedFactory);
+    }
+
+    /**
+     * Get the <code>Timer</code> for checking pool's idle count. Lazily 
create the [EMAIL PROTECTED] Timer} as needed.
+     * @return the [EMAIL PROTECTED] Timer} for checking pool's idle count.
+     */
+    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("pool 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("{pool=").append(pool);
+            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(", pool=").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("pool 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(", pool=").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("pool 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("{pool=").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();
+        }
+    }
+}
\ No newline at end of file

Added: 
jakarta/commons/proper/pool/trunk/src/test/org/apache/commons/pool/TestPools.java
URL: 
http://svn.apache.org/viewcvs/jakarta/commons/proper/pool/trunk/src/test/org/apache/commons/pool/TestPools.java?rev=383042&view=auto
==============================================================================
--- 
jakarta/commons/proper/pool/trunk/src/test/org/apache/commons/pool/TestPools.java
 (added)
+++ 
jakarta/commons/proper/pool/trunk/src/test/org/apache/commons/pool/TestPools.java
 Fri Mar  3 21:42:18 2006
@@ -0,0 +1,391 @@
+/*
+ * 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 org.apache.commons.pool;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.Proxy;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.TimerTask;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Iterator;
+
+/**
+ * Unit tests for [EMAIL PROTECTED] Pools}.
+ *
+ * @author Sandy McArthur
+ * @version $Revision$ $Date$
+ */
+public class TestPools extends TestCase {
+    
+    /** Period between checks for minIdle tests. Increase this if you happen 
to get too many false failures. */
+    private static final int CHECK_PERIOD = 300;
+
+    /** Times to let the minIdle check run. */
+    private static final int CHECK_COUNT = 4;
+
+    /** Sleep time to let the minIdle tests run CHECK_COUNT times. */
+    private static final int CHECK_SLEEP_PERIOD = CHECK_PERIOD * (CHECK_COUNT 
- 1) + CHECK_PERIOD / 2;
+
+    public void testAdaptKeyedPoolableObjectFactory() throws Exception {
+        try {
+            Pools.adapt((KeyedPoolableObjectFactory)null);
+            fail("Pools.adapt(KeyedPoolableObjectFactory) must not allow null 
factory.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+    }
+
+    public void testAdaptKeyedPoolableObjectFactoryKey() throws Exception {
+        try {
+            Pools.adapt((KeyedPoolableObjectFactory)null, new Object());
+            fail("Pools.adapt(KeyedPoolableObjectFactory, key) must not allow 
null factory.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+        try {
+            
Pools.adapt((KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class,
 null), null);
+            fail("Pools.adapt(KeyedPoolableObjectFactory, key) must not allow 
null key.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final KeyedPoolableObjectFactory kpof =
+                
(KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, 
calledMethods);
+
+        final PoolableObjectFactory pof = Pools.adapt(kpof);
+        pof.activateObject(null);
+        pof.destroyObject(null);
+        pof.makeObject();
+        pof.passivateObject(null);
+        pof.validateObject(null);
+
+        final List expectedMethods = new ArrayList();
+        expectedMethods.add("activateObject");
+        expectedMethods.add("destroyObject");
+        expectedMethods.add("makeObject");
+        expectedMethods.add("passivateObject");
+        expectedMethods.add("validateObject");
+
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testAdaptPoolableObjectFactory() throws Exception {
+        try {
+            Pools.adapt((PoolableObjectFactory)null);
+            fail("Pools.adapt(PoolableObjectFactory) must not allow null 
factory.");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final PoolableObjectFactory pof =
+                
(PoolableObjectFactory)createProxy(PoolableObjectFactory.class, calledMethods);
+
+        final KeyedPoolableObjectFactory kpof = Pools.adapt(pof);
+        kpof.activateObject(null, null);
+        kpof.destroyObject(null, null);
+        kpof.makeObject(null);
+        kpof.passivateObject(null, null);
+        kpof.validateObject(null, null);
+
+        final List expectedMethods = new ArrayList();
+        expectedMethods.add("activateObject");
+        expectedMethods.add("destroyObject");
+        expectedMethods.add("makeObject");
+        expectedMethods.add("passivateObject");
+        expectedMethods.add("validateObject");
+
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testAdaptKeyedObjectPool() throws Exception {
+        try {
+            Pools.adapt((KeyedObjectPool)null);
+            fail("Pools.adapt(KeyedObjectPool) must not allow a null pool.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+    }
+
+    public void testAdaptKeyedObjectPoolKey() throws Exception {
+        try {
+            Pools.adapt((KeyedObjectPool)null, new Object());
+            fail("Pools.adapt(KeyedObjectPool, key) must not allow a null 
pool.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+        try {
+            Pools.adapt((KeyedObjectPool)createProxy(KeyedObjectPool.class, 
null), null);
+            fail("Pools.adapt(KeyedObjectPool, key) must not allow a null 
key.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final KeyedObjectPool kop = 
(KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
+
+        final ObjectPool op = Pools.adapt(kop);
+        op.addObject();
+        op.borrowObject();
+        op.clear();
+        op.close();
+        op.getNumActive();
+        op.getNumIdle();
+        op.invalidateObject(null);
+        op.returnObject(null);
+        
op.setFactory((PoolableObjectFactory)createProxy(PoolableObjectFactory.class, 
null));
+
+        final List expectedMethods = new ArrayList();
+        expectedMethods.add("addObject");
+        expectedMethods.add("borrowObject");
+        expectedMethods.add("clear");
+        expectedMethods.add("close");
+        expectedMethods.add("getNumActive");
+        expectedMethods.add("getNumIdle");
+        expectedMethods.add("invalidateObject");
+        expectedMethods.add("returnObject");
+        expectedMethods.add("setFactory");
+
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testAdaptObjectPool() throws Exception {
+        try {
+            Pools.adapt((ObjectPool)null);
+            fail("Pools.adapt(ObjectPool) must not allow a null pool.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+
+        final List calledMethods = new ArrayList();
+        final ObjectPool op = (ObjectPool)createProxy(ObjectPool.class, 
calledMethods);
+
+        final KeyedObjectPool kop = Pools.adapt(op);
+        kop.addObject(null);
+        kop.borrowObject(null);
+        kop.clear();
+        kop.clear(null);
+        kop.close();
+        kop.getNumActive();
+        kop.getNumActive(null);
+        kop.getNumIdle();
+        kop.getNumIdle(null);
+        kop.invalidateObject(null, null);
+        kop.returnObject(null, null);
+        
kop.setFactory((KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class,
 null));
+
+        final List expectedMethods = new ArrayList();
+        expectedMethods.add("addObject");
+        expectedMethods.add("borrowObject");
+        expectedMethods.add("clear");
+        expectedMethods.add("clear");
+        expectedMethods.add("close");
+        expectedMethods.add("getNumActive");
+        expectedMethods.add("getNumActive");
+        expectedMethods.add("getNumIdle");
+        expectedMethods.add("getNumIdle");
+        expectedMethods.add("invalidateObject");
+        expectedMethods.add("returnObject");
+        expectedMethods.add("setFactory");
+
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testCheckMinIdleObjectPool() throws Exception {
+        final List calledMethods = new ArrayList();
+        final ObjectPool pool = (ObjectPool)createProxy(ObjectPool.class, 
calledMethods);
+        final TimerTask task = Pools.checkMinIdle(pool, 1, CHECK_PERIOD); // 
checks minIdle immediately
+
+        Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times.
+        task.cancel();
+
+        final List expectedMethods = new ArrayList();
+        for (int i=0; i < CHECK_COUNT; i++) {
+            expectedMethods.add("getNumIdle");
+            expectedMethods.add("addObject");
+        }
+        assertEquals(expectedMethods, calledMethods); // may fail because of 
the thread scheduler
+    }
+
+    public void testCheckMinIdleKeyedObjectPool() throws Exception {
+        final List calledMethods = new ArrayList();
+        final KeyedObjectPool pool = 
(KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
+        final Object key = new Object();
+        final TimerTask task = Pools.checkMinIdle(pool, key, 1, CHECK_PERIOD); 
// checks minIdle immediately
+
+        Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times.
+        task.cancel();
+
+        final List expectedMethods = new ArrayList();
+        for (int i=0; i < CHECK_COUNT; i++) {
+            expectedMethods.add("getNumIdle");
+            expectedMethods.add("addObject");
+        }
+        assertEquals(expectedMethods, calledMethods); // may fail because of 
the thread scheduler
+    }
+
+    public void testCheckMinIdleKeyedObjectPoolKeys() throws Exception {
+        final List calledMethods = new ArrayList();
+        final KeyedObjectPool pool = 
(KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
+        final Collection keys = new ArrayList(2);
+        keys.add("one");
+        keys.add("two");
+        final Map tasks = Pools.checkMinIdle(pool, keys, 1, CHECK_PERIOD); // 
checks minIdle immediately
+
+        Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times.
+        final Iterator iter = tasks.values().iterator();
+        while (iter.hasNext()) {
+            final TimerTask task = (TimerTask)iter.next();
+            task.cancel();
+        }
+
+        final List expectedMethods = new ArrayList();
+        for (int i=0; i < CHECK_COUNT * keys.size(); i++) {
+            expectedMethods.add("getNumIdle");
+            expectedMethods.add("addObject");
+        }
+        assertEquals(expectedMethods, calledMethods); // may fail because of 
the thread scheduler
+    }
+
+    public void testPrefillObjectPool() throws Exception {
+        final List calledMethods = new ArrayList();
+        final ObjectPool pool = (ObjectPool)createProxy(ObjectPool.class, 
calledMethods);
+
+        Pools.prefill(pool, 0);
+        final List expectedMethods = new ArrayList();
+        assertEquals(expectedMethods, calledMethods);
+
+        calledMethods.clear();
+        Pools.prefill(pool, 3);
+        for (int i=0; i < 3; i++) {
+            expectedMethods.add("addObject");
+        }
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testPrefillKeyedObjectPool() throws Exception {
+        final List calledMethods = new ArrayList();
+        final KeyedObjectPool pool = 
(KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
+
+        Pools.prefill(pool, new Object(), 0);
+        final List expectedMethods = new ArrayList();
+        assertEquals(expectedMethods, calledMethods);
+
+        calledMethods.clear();
+        Pools.prefill(pool, new Object(), 3);
+        for (int i=0; i < 3; i++) {
+            expectedMethods.add("addObject");
+        }
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testPrefillKeyedObjectPoolCollection() throws Exception {
+        final List calledMethods = new ArrayList();
+        final KeyedObjectPool pool = 
(KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
+
+        final Set keys = new HashSet();
+        Pools.prefill(pool, keys, 0);
+        final List expectedMethods = new ArrayList();
+        assertEquals(expectedMethods, calledMethods);
+
+        calledMethods.clear();
+        keys.add(new Integer(1));
+        keys.add("two");
+        keys.add(new Double(3.1415926));
+        Pools.prefill(pool, keys, 3);
+        for (int i=0; i < keys.size() * 3; i++) {
+            expectedMethods.add("addObject");
+        }
+        assertEquals(expectedMethods, calledMethods);
+    }
+
+    public void testSynchronizedPoolObjectPool() throws Exception {
+        try {
+            Pools.synchronizedPool((ObjectPool)null);
+            fail("Pools.synchronizedPool(ObjectPool) must not allow a null 
pool.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+        // TODO: Anyone feel motivated to construct a test that verifies 
proper synchronization?
+    }
+
+    public void testSynchronizedPoolKeyedObjectPool() throws Exception {
+        try {
+            Pools.synchronizedPool((KeyedObjectPool)null);
+            fail("Pools.synchronizedPool(KeyedObjectPool) must not allow a 
null pool.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+        // TODO: Anyone feel motivated to construct a test that verifies 
proper synchronization?
+    }
+
+    public void testSynchronizedPoolableFactoryPoolableObjectFactory() throws 
Exception {
+        try {
+            Pools.synchronizedPoolableFactory((PoolableObjectFactory)null);
+            fail("Pools.synchronizedPoolableFactory(PoolableObjectFactory) 
must not allow a null factory.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+        // TODO: Anyone feel motivated to construct a test that verifies 
proper synchronization?
+    }
+
+    public void testSynchronizedPoolableFactoryKeyedPoolableObjectFactory() 
throws Exception {
+        try {
+            
Pools.synchronizedPoolableFactory((KeyedPoolableObjectFactory)null);
+            
fail("Pools.synchronizedPoolableFactory(KeyedPoolableObjectFactory) must not 
allow a null factory.");
+        } catch(IllegalArgumentException iae) {
+            // expected
+        }
+        // TODO: Anyone feel motivated to construct a test that verifies 
proper synchronization?
+    }
+
+    private static Object createProxy(final Class clazz, final List logger) {
+        return Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { 
clazz },
+                new MethodCallLogger(logger));
+    }
+
+    private static class MethodCallLogger implements InvocationHandler {
+        private final List calledMethods;
+
+        MethodCallLogger(final List calledMethods) {
+            this.calledMethods = calledMethods;
+        }
+
+        public Object invoke(final Object proxy, final Method method, final 
Object[] args) throws Throwable {
+            calledMethods.add(method.getName());
+            if (boolean.class.equals(method.getReturnType())) {
+                return Boolean.FALSE;
+            } else if (int.class.equals(method.getReturnType())) {
+                return new Integer(0);
+            } else if (long.class.equals(method.getReturnType())) {
+                return new Long(0);
+            } else if (Object.class.equals(method.getReturnType())) {
+                return new Object();
+            } else {
+                return null;
+            }
+        }
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to