commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sandy...@apache.org
Subject svn commit: r383042 - in /jakarta/commons/proper/pool/trunk/src: java/org/apache/commons/pool/Pools.java test/org/apache/commons/pool/TestPools.java
Date Sat, 04 Mar 2006 05:42:19 GMT
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 {@link Timer} creates a {@link 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
+     * {@link #adapt(KeyedPoolableObjectFactory, Object) Pools.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)
+     */
+    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)
+     */
+    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>.
+     */
+    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) Pools.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)
+     */
+    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)
+     */
+    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>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 {@link ObjectPool#addObject()} then no more checks will be performed.
+     *
+     * @param pool the pool 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 pool, see
+     *      {@link Timer#schedule(TimerTask, long, long)}.
+     * @return the {@link 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 {@link 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 {@link 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 {@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 pool, 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)}.
+     */
+    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 {@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 pool, 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)
+     */
+    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 {@link 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 {@link 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
+     * {@link #prefill(KeyedObjectPool, Object, int)} for each key in the <code>keys</code> collection.
+     *
+     * @param keyedPool the pool 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)
+     */
+    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 {@link Timer} as needed.
+     * @return the {@link 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 {@link 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: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message