KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > pool > impl > GenericObjectPool


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.commons.pool.impl;
18
19 import java.util.Iterator JavaDoc;
20 import java.util.NoSuchElementException JavaDoc;
21
22 import org.apache.commons.collections.CursorableLinkedList;
23 import org.apache.commons.pool.BaseObjectPool;
24 import org.apache.commons.pool.ObjectPool;
25 import org.apache.commons.pool.PoolableObjectFactory;
26
27 /**
28  * A configurable {@link ObjectPool} implementation.
29  * <p>
30  * When coupled with the appropriate {@link PoolableObjectFactory},
31  * <tt>GenericObjectPool</tt> provides robust pooling functionality for
32  * arbitrary objects.
33  * <p>
34  * A <tt>GenericObjectPool</tt> provides a number of configurable parameters:
35  * <ul>
36  * <li>
37  * {@link #setMaxActive <i>maxActive</i>} controls the maximum number of objects that can
38  * be borrowed from the pool at one time. When non-positive, there
39  * is no limit to the number of objects that may be active at one time.
40  * When {@link #setMaxActive <i>maxActive</i>} is exceeded, the pool is said to be exhausted.
41  * </li>
42  * <li>
43  * {@link #setMaxIdle <i>maxIdle</i>} controls the maximum number of objects that can
44  * sit idle in the pool at any time. When negative, there
45  * is no limit to the number of objects that may be idle at one time.
46  * </li>
47  * <li>
48  * {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} specifies the
49  * behaviour of the {@link #borrowObject} method when the pool is exhausted:
50  * <ul>
51  * <li>
52  * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
53  * {@link #WHEN_EXHAUSTED_FAIL}, {@link #borrowObject} will throw
54  * a {@link NoSuchElementException}
55  * </li>
56  * <li>
57  * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>} is
58  * {@link #WHEN_EXHAUSTED_GROW}, {@link #borrowObject} will create a new
59  * object and return it(essentially making {@link #setMaxActive <i>maxActive</i>}
60  * meaningless.)
61  * </li>
62  * <li>
63  * When {@link #setWhenExhaustedAction <i>whenExhaustedAction</i>}
64  * is {@link #WHEN_EXHAUSTED_BLOCK}, {@link #borrowObject} will block
65  * (invoke {@link Object#wait} until a new or idle object is available.
66  * If a positive {@link #setMaxWait <i>maxWait</i>}
67  * value is supplied, the {@link #borrowObject} will block for at
68  * most that many milliseconds, after which a {@link NoSuchElementException}
69  * will be thrown. If {@link #setMaxWait <i>maxWait</i>} is non-positive,
70  * the {@link #borrowObject} method will block indefinitely.
71  * </li>
72  * </ul>
73  * </li>
74  * <li>
75  * When {@link #setTestOnBorrow <i>testOnBorrow</i>} is set, the pool will
76  * attempt to validate each object before it is returned from the
77  * {@link #borrowObject} method. (Using the provided factory's
78  * {@link PoolableObjectFactory#validateObject} method.) Objects that fail
79  * to validate will be dropped from the pool, and a different object will
80  * be borrowed.
81  * </li>
82  * <li>
83  * When {@link #setTestOnReturn <i>testOnReturn</i>} is set, the pool will
84  * attempt to validate each object before it is returned to the pool in the
85  * {@link #returnObject} method. (Using the provided factory's
86  * {@link PoolableObjectFactory#validateObject}
87  * method.) Objects that fail to validate will be dropped from the pool.
88  * </li>
89  * </ul>
90  * <p>
91  * Optionally, one may configure the pool to examine and possibly evict objects as they
92  * sit idle in the pool. This is performed by an "idle object eviction" thread, which
93  * runs asychronously. The idle object eviction thread may be configured using the
94  * following attributes:
95  * <ul>
96  * <li>
97  * {@link #setTimeBetweenEvictionRunsMillis <i>timeBetweenEvictionRunsMillis</i>}
98  * indicates how long the eviction thread should sleep before "runs" of examining
99  * idle objects. When non-positive, no eviction thread will be launched.
100  * </li>
101  * <li>
102  * {@link #setMinEvictableIdleTimeMillis <i>minEvictableIdleTimeMillis</i>}
103  * specifies the minimum amount of time that an object may sit idle in the pool
104  * before it is eligable for eviction due to idle time. When non-positive, no object
105  * will be dropped from the pool due to idle time alone.
106  * </li>
107  * <li>
108  * {@link #setTestWhileIdle <i>testWhileIdle</i>} indicates whether or not idle
109  * objects should be validated using the factory's
110  * {@link PoolableObjectFactory#validateObject} method. Objects
111  * that fail to validate will be dropped from the pool.
112  * </li>
113  * </ul>
114  * <p>
115  * GenericObjectPool is not usable without a {@link PoolableObjectFactory}. A
116  * non-<code>null</code> factory must be provided either as a constructor argument
117  * or via a call to {@link #setFactory} before the pool is used.
118  *
119  * @see GenericKeyedObjectPool
120  * @author Rodney Waldhoff
121  * @author Dirk Verbeeck
122  * @version $Revision$ $Date: 2005-05-16 04:34:06 -0700 (Mon, 16 May 2005) $
123  */

124 public class GenericObjectPool extends BaseObjectPool implements ObjectPool {
125
126     //--- public constants -------------------------------------------
127

128     /**
129      * A "when exhausted action" type indicating that when the pool is
130      * exhausted (i.e., the maximum number of active objects has
131      * been reached), the {@link #borrowObject}
132      * method should fail, throwing a {@link NoSuchElementException}.
133      * @see #WHEN_EXHAUSTED_BLOCK
134      * @see #WHEN_EXHAUSTED_GROW
135      * @see #setWhenExhaustedAction
136      */

137     public static final byte WHEN_EXHAUSTED_FAIL = 0;
138
139     /**
140      * A "when exhausted action" type indicating that when the pool
141      * is exhausted (i.e., the maximum number
142      * of active objects has been reached), the {@link #borrowObject}
143      * method should block until a new object is available, or the
144      * {@link #getMaxWait maximum wait time} has been reached.
145      * @see #WHEN_EXHAUSTED_FAIL
146      * @see #WHEN_EXHAUSTED_GROW
147      * @see #setMaxWait
148      * @see #getMaxWait
149      * @see #setWhenExhaustedAction
150      */

151     public static final byte WHEN_EXHAUSTED_BLOCK = 1;
152
153     /**
154      * A "when exhausted action" type indicating that when the pool is
155      * exhausted (i.e., the maximum number
156      * of active objects has been reached), the {@link #borrowObject}
157      * method should simply create a new object anyway.
158      * @see #WHEN_EXHAUSTED_FAIL
159      * @see #WHEN_EXHAUSTED_GROW
160      * @see #setWhenExhaustedAction
161      */

162     public static final byte WHEN_EXHAUSTED_GROW = 2;
163
164     /**
165      * The default cap on the number of "sleeping" instances in the pool.
166      * @see #getMaxIdle
167      * @see #setMaxIdle
168      */

169     public static final int DEFAULT_MAX_IDLE = 8;
170
171     /**
172      * The default minimum number of "sleeping" instances in the pool
173      * before before the evictor thread (if active) spawns new objects.
174      * @see #getMinIdle
175      * @see #setMinIdle
176      */

177     public static final int DEFAULT_MIN_IDLE = 0;
178
179     /**
180      * The default cap on the total number of active instances from the pool.
181      * @see #getMaxActive
182      */

183     public static final int DEFAULT_MAX_ACTIVE = 8;
184
185     /**
186      * The default "when exhausted action" for the pool.
187      * @see #WHEN_EXHAUSTED_BLOCK
188      * @see #WHEN_EXHAUSTED_FAIL
189      * @see #WHEN_EXHAUSTED_GROW
190      * @see #setWhenExhaustedAction
191      */

192     public static final byte DEFAULT_WHEN_EXHAUSTED_ACTION = WHEN_EXHAUSTED_BLOCK;
193
194     /**
195      * The default maximum amount of time (in millis) the
196      * {@link #borrowObject} method should block before throwing
197      * an exception when the pool is exhausted and the
198      * {@link #getWhenExhaustedAction "when exhausted" action} is
199      * {@link #WHEN_EXHAUSTED_BLOCK}.
200      * @see #getMaxWait
201      * @see #setMaxWait
202      */

203     public static final long DEFAULT_MAX_WAIT = -1L;
204
205     /**
206      * The default "test on borrow" value.
207      * @see #getTestOnBorrow
208      * @see #setTestOnBorrow
209      */

210     public static final boolean DEFAULT_TEST_ON_BORROW = false;
211
212     /**
213      * The default "test on return" value.
214      * @see #getTestOnReturn
215      * @see #setTestOnReturn
216      */

217     public static final boolean DEFAULT_TEST_ON_RETURN = false;
218
219     /**
220      * The default "test while idle" value.
221      * @see #getTestWhileIdle
222      * @see #setTestWhileIdle
223      * @see #getTimeBetweenEvictionRunsMillis
224      * @see #setTimeBetweenEvictionRunsMillis
225      */

226     public static final boolean DEFAULT_TEST_WHILE_IDLE = false;
227
228     /**
229      * The default "time between eviction runs" value.
230      * @see #getTimeBetweenEvictionRunsMillis
231      * @see #setTimeBetweenEvictionRunsMillis
232      */

233     public static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = -1L;
234
235     /**
236      * The default number of objects to examine per run in the
237      * idle object evictor.
238      * @see #getNumTestsPerEvictionRun
239      * @see #setNumTestsPerEvictionRun
240      * @see #getTimeBetweenEvictionRunsMillis
241      * @see #setTimeBetweenEvictionRunsMillis
242      */

243     public static final int DEFAULT_NUM_TESTS_PER_EVICTION_RUN = 3;
244
245     /**
246      * The default value for {@link #getMinEvictableIdleTimeMillis}.
247      * @see #getMinEvictableIdleTimeMillis
248      * @see #setMinEvictableIdleTimeMillis
249      */

250     public static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 1000L * 60L * 30L;
251
252     /**
253      * The default value for {@link #getSoftMinEvictableIdleTimeMillis}.
254      * @see #getSoftMinEvictableIdleTimeMillis
255      * @see #setSoftMinEvictableIdleTimeMillis
256      */

257     public static final long DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1;
258
259     //--- constructors -----------------------------------------------
260

261     /**
262      * Create a new <tt>GenericObjectPool</tt>.
263      */

264     public GenericObjectPool() {
265         this(null,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_MIN_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
266     }
267
268     /**
269      * Create a new <tt>GenericObjectPool</tt> using the specified values.
270      * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
271      */

272     public GenericObjectPool(PoolableObjectFactory factory) {
273         this(factory,DEFAULT_MAX_ACTIVE,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_MIN_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
274     }
275
276     /**
277      * Create a new <tt>GenericObjectPool</tt> using the specified values.
278      * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
279      * @param config a non-<tt>null</tt> {@link GenericObjectPool.Config} describing my configuration
280      */

281     public GenericObjectPool(PoolableObjectFactory factory, GenericObjectPool.Config config) {
282         this(factory,config.maxActive,config.whenExhaustedAction,config.maxWait,config.maxIdle,config.minIdle,config.testOnBorrow,config.testOnReturn,config.timeBetweenEvictionRunsMillis,config.numTestsPerEvictionRun,config.minEvictableIdleTimeMillis,config.testWhileIdle);
283     }
284
285     /**
286      * Create a new <tt>GenericObjectPool</tt> using the specified values.
287      * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
288      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
289      */

290     public GenericObjectPool(PoolableObjectFactory factory, int maxActive) {
291         this(factory,maxActive,DEFAULT_WHEN_EXHAUSTED_ACTION,DEFAULT_MAX_WAIT,DEFAULT_MAX_IDLE,DEFAULT_MIN_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
292     }
293
294     /**
295      * Create a new <tt>GenericObjectPool</tt> using the specified values.
296      * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
297      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
298      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})
299      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})
300      */

301     public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait) {
302         this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,DEFAULT_MIN_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
303     }
304
305     /**
306      * Create a new <tt>GenericObjectPool</tt> using the specified values.
307      * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
308      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
309      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})
310      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})
311      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #getTestOnBorrow})
312      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #getTestOnReturn})
313      */

314     public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, boolean testOnBorrow, boolean testOnReturn) {
315         this(factory,maxActive,whenExhaustedAction,maxWait,DEFAULT_MAX_IDLE,DEFAULT_MIN_IDLE,testOnBorrow,testOnReturn,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
316     }
317
318     /**
319      * Create a new <tt>GenericObjectPool</tt> using the specified values.
320      * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
321      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
322      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})
323      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})
324      * @param maxIdle the maximum number of idle objects in my pool (see {@link #getMaxIdle})
325      */

326     public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle) {
327         this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,DEFAULT_MIN_IDLE,DEFAULT_TEST_ON_BORROW,DEFAULT_TEST_ON_RETURN,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
328     }
329
330     /**
331      * Create a new <tt>GenericObjectPool</tt> using the specified values.
332      * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
333      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
334      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #getWhenExhaustedAction})
335      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #getMaxWait})
336      * @param maxIdle the maximum number of idle objects in my pool (see {@link #getMaxIdle})
337      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #getTestOnBorrow})
338      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #getTestOnReturn})
339      */

340     public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn) {
341         this(factory,maxActive,whenExhaustedAction,maxWait,maxIdle,DEFAULT_MIN_IDLE,testOnBorrow,testOnReturn,DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS,DEFAULT_NUM_TESTS_PER_EVICTION_RUN,DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS,DEFAULT_TEST_WHILE_IDLE);
342     }
343
344     /**
345      * Create a new <tt>GenericObjectPool</tt> using the specified values.
346      * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
347      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
348      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
349      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
350      * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
351      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
352      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
353      * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
354      * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
355      * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
356      * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
357      */

358     public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
359         this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle);
360     }
361
362     /**
363      * Create a new <tt>GenericObjectPool</tt> using the specified values.
364      * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
365      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
366      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
367      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
368      * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
369      * @param minIdle the minimum number of idle objects in my pool (see {@link #setMinIdle})
370      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
371      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
372      * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
373      * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
374      * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
375      * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
376      */

377     public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle) {
378         this(factory, maxActive, whenExhaustedAction, maxWait, maxIdle, DEFAULT_MIN_IDLE, testOnBorrow, testOnReturn, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minEvictableIdleTimeMillis, testWhileIdle, DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
379     }
380
381     /**
382      * Create a new <tt>GenericObjectPool</tt> using the specified values.
383      * @param factory the (possibly <tt>null</tt>)PoolableObjectFactory to use to create, validate and destroy objects
384      * @param maxActive the maximum number of objects that can be borrowed from me at one time (see {@link #setMaxActive})
385      * @param whenExhaustedAction the action to take when the pool is exhausted (see {@link #setWhenExhaustedAction})
386      * @param maxWait the maximum amount of time to wait for an idle object when the pool is exhausted an and <i>whenExhaustedAction</i> is {@link #WHEN_EXHAUSTED_BLOCK} (otherwise ignored) (see {@link #setMaxWait})
387      * @param maxIdle the maximum number of idle objects in my pool (see {@link #setMaxIdle})
388      * @param minIdle the minimum number of idle objects in my pool (see {@link #setMinIdle})
389      * @param testOnBorrow whether or not to validate objects before they are returned by the {@link #borrowObject} method (see {@link #setTestOnBorrow})
390      * @param testOnReturn whether or not to validate objects after they are returned to the {@link #returnObject} method (see {@link #setTestOnReturn})
391      * @param timeBetweenEvictionRunsMillis the amount of time (in milliseconds) to sleep between examining idle objects for eviction (see {@link #setTimeBetweenEvictionRunsMillis})
392      * @param numTestsPerEvictionRun the number of idle objects to examine per run within the idle object eviction thread (if any) (see {@link #setNumTestsPerEvictionRun})
393      * @param minEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition (see {@link #setMinEvictableIdleTimeMillis})
394      * @param testWhileIdle whether or not to validate objects in the idle object eviction thread, if any (see {@link #setTestWhileIdle})
395      * @param softMinEvictableIdleTimeMillis the minimum number of milliseconds an object can sit idle in the pool before it is eligable for evcition with the extra condition that at least "minIdle" amount of object remain in the pool. (see {@link #setSoftMinEvictableIdleTimeMillis})
396      */

397     public GenericObjectPool(PoolableObjectFactory factory, int maxActive, byte whenExhaustedAction, long maxWait, int maxIdle, int minIdle, boolean testOnBorrow, boolean testOnReturn, long timeBetweenEvictionRunsMillis, int numTestsPerEvictionRun, long minEvictableIdleTimeMillis, boolean testWhileIdle, long softMinEvictableIdleTimeMillis) {
398         _factory = factory;
399         _maxActive = maxActive;
400         switch(whenExhaustedAction) {
401             case WHEN_EXHAUSTED_BLOCK:
402             case WHEN_EXHAUSTED_FAIL:
403             case WHEN_EXHAUSTED_GROW:
404                 _whenExhaustedAction = whenExhaustedAction;
405                 break;
406             default:
407                 throw new IllegalArgumentException JavaDoc("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
408         }
409         _maxWait = maxWait;
410         _maxIdle = maxIdle;
411         _minIdle = minIdle;
412         _testOnBorrow = testOnBorrow;
413         _testOnReturn = testOnReturn;
414         _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
415         _numTestsPerEvictionRun = numTestsPerEvictionRun;
416         _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
417         _softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
418         _testWhileIdle = testWhileIdle;
419
420         _pool = new CursorableLinkedList();
421         startEvictor(_timeBetweenEvictionRunsMillis);
422     }
423
424     //--- public methods ---------------------------------------------
425

426     //--- configuration methods --------------------------------------
427

428     /**
429      * Returns the cap on the total number of active instances from my pool.
430      * @return the cap on the total number of active instances from my pool.
431      * @see #setMaxActive
432      */

433     public synchronized int getMaxActive() {
434         return _maxActive;
435     }
436
437     /**
438      * Sets the cap on the total number of active instances from my pool.
439      * @param maxActive The cap on the total number of active instances from my pool.
440      * Use a negative value for an infinite number of instances.
441      * @see #getMaxActive
442      */

443     public synchronized void setMaxActive(int maxActive) {
444         _maxActive = maxActive;
445         notifyAll();
446     }
447
448     /**
449      * Returns the action to take when the {@link #borrowObject} method
450      * is invoked when the pool is exhausted (the maximum number
451      * of "active" objects has been reached).
452      *
453      * @return one of {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL} or {@link #WHEN_EXHAUSTED_GROW}
454      * @see #setWhenExhaustedAction
455      */

456     public synchronized byte getWhenExhaustedAction() {
457         return _whenExhaustedAction;
458     }
459
460     /**
461      * Sets the action to take when the {@link #borrowObject} method
462      * is invoked when the pool is exhausted (the maximum number
463      * of "active" objects has been reached).
464      *
465      * @param whenExhaustedAction the action code, which must be one of
466      * {@link #WHEN_EXHAUSTED_BLOCK}, {@link #WHEN_EXHAUSTED_FAIL},
467      * or {@link #WHEN_EXHAUSTED_GROW}
468      * @see #getWhenExhaustedAction
469      */

470     public synchronized void setWhenExhaustedAction(byte whenExhaustedAction) {
471         switch(whenExhaustedAction) {
472             case WHEN_EXHAUSTED_BLOCK:
473             case WHEN_EXHAUSTED_FAIL:
474             case WHEN_EXHAUSTED_GROW:
475                 _whenExhaustedAction = whenExhaustedAction;
476                 notifyAll();
477                 break;
478             default:
479                 throw new IllegalArgumentException JavaDoc("whenExhaustedAction " + whenExhaustedAction + " not recognized.");
480         }
481     }
482
483
484     /**
485      * Returns the maximum amount of time (in milliseconds) the
486      * {@link #borrowObject} method should block before throwing
487      * an exception when the pool is exhausted and the
488      * {@link #setWhenExhaustedAction "when exhausted" action} is
489      * {@link #WHEN_EXHAUSTED_BLOCK}.
490      *
491      * When less than 0, the {@link #borrowObject} method
492      * may block indefinitely.
493      *
494      * @see #setMaxWait
495      * @see #setWhenExhaustedAction
496      * @see #WHEN_EXHAUSTED_BLOCK
497      */

498     public synchronized long getMaxWait() {
499         return _maxWait;
500     }
501
502     /**
503      * Sets the maximum amount of time (in milliseconds) the
504      * {@link #borrowObject} method should block before throwing
505      * an exception when the pool is exhausted and the
506      * {@link #setWhenExhaustedAction "when exhausted" action} is
507      * {@link #WHEN_EXHAUSTED_BLOCK}.
508      *
509      * When less than 0, the {@link #borrowObject} method
510      * may block indefinitely.
511      *
512      * @see #getMaxWait
513      * @see #setWhenExhaustedAction
514      * @see #WHEN_EXHAUSTED_BLOCK
515      */

516     public synchronized void setMaxWait(long maxWait) {
517         _maxWait = maxWait;
518         notifyAll();
519     }
520
521     /**
522      * Returns the cap on the number of "idle" instances in the pool.
523      * @return the cap on the number of "idle" instances in the pool.
524      * @see #setMaxIdle
525      */

526     public synchronized int getMaxIdle() {
527         return _maxIdle;
528     }
529
530     /**
531      * Sets the cap on the number of "idle" instances in the pool.
532      * @param maxIdle The cap on the number of "idle" instances in the pool.
533      * Use a negative value to indicate an unlimited number
534      * of idle instances.
535      * @see #getMaxIdle
536      */

537     public synchronized void setMaxIdle(int maxIdle) {
538         _maxIdle = maxIdle;
539         notifyAll();
540     }
541
542     /**
543      * Sets the minimum number of objects allowed in the pool
544      * before the evictor thread (if active) spawns new objects.
545      * (Note no objects are created when: numActive + numIdle >= maxActive)
546      *
547      * @param minIdle The minimum number of objects.
548      * @see #getMinIdle
549      */

550     public synchronized void setMinIdle(int minIdle) {
551         _minIdle = minIdle;
552         notifyAll();
553     }
554
555     /**
556      * Returns the minimum number of objects allowed in the pool
557      * before the evictor thread (if active) spawns new objects.
558      * (Note no objects are created when: numActive + numIdle >= maxActive)
559      *
560      * @return The minimum number of objects.
561      * @see #setMinIdle
562      */

563     public synchronized int getMinIdle() {
564         return _minIdle;
565     }
566
567     /**
568      * When <tt>true</tt>, objects will be
569      * {@link PoolableObjectFactory#validateObject validated}
570      * before being returned by the {@link #borrowObject}
571      * method. If the object fails to validate,
572      * it will be dropped from the pool, and we will attempt
573      * to borrow another.
574      *
575      * @see #setTestOnBorrow
576      */

577     public synchronized boolean getTestOnBorrow() {
578         return _testOnBorrow;
579     }
580
581     /**
582      * When <tt>true</tt>, objects will be
583      * {@link PoolableObjectFactory#validateObject validated}
584      * before being returned by the {@link #borrowObject}
585      * method. If the object fails to validate,
586      * it will be dropped from the pool, and we will attempt
587      * to borrow another.
588      *
589      * @see #getTestOnBorrow
590      */

591     public synchronized void setTestOnBorrow(boolean testOnBorrow) {
592         _testOnBorrow = testOnBorrow;
593     }
594
595     /**
596      * When <tt>true</tt>, objects will be
597      * {@link PoolableObjectFactory#validateObject validated}
598      * before being returned to the pool within the
599      * {@link #returnObject}.
600      *
601      * @see #setTestOnReturn
602      */

603     public synchronized boolean getTestOnReturn() {
604         return _testOnReturn;
605     }
606
607     /**
608      * When <tt>true</tt>, objects will be
609      * {@link PoolableObjectFactory#validateObject validated}
610      * before being returned to the pool within the
611      * {@link #returnObject}.
612      *
613      * @see #getTestOnReturn
614      */

615     public synchronized void setTestOnReturn(boolean testOnReturn) {
616         _testOnReturn = testOnReturn;
617     }
618
619     /**
620      * Returns the number of milliseconds to sleep between runs of the
621      * idle object evictor thread.
622      * When non-positive, no idle object evictor thread will be
623      * run.
624      *
625      * @see #setTimeBetweenEvictionRunsMillis
626      */

627     public synchronized long getTimeBetweenEvictionRunsMillis() {
628         return _timeBetweenEvictionRunsMillis;
629     }
630
631     /**
632      * Sets the number of milliseconds to sleep between runs of the
633      * idle object evictor thread.
634      * When non-positive, no idle object evictor thread will be
635      * run.
636      *
637      * @see #getTimeBetweenEvictionRunsMillis
638      */

639     public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
640         _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
641         startEvictor(_timeBetweenEvictionRunsMillis);
642     }
643
644     /**
645      * Returns the number of objects to examine during each run of the
646      * idle object evictor thread (if any).
647      *
648      * @see #setNumTestsPerEvictionRun
649      * @see #setTimeBetweenEvictionRunsMillis
650      */

651     public synchronized int getNumTestsPerEvictionRun() {
652         return _numTestsPerEvictionRun;
653     }
654
655     /**
656      * Sets the number of objects to examine during each run of the
657      * idle object evictor thread (if any).
658      * <p>
659      * When a negative value is supplied, <tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
660      * tests will be run. I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
661      * idle objects will be tested per run.
662      *
663      * @see #getNumTestsPerEvictionRun
664      * @see #setTimeBetweenEvictionRunsMillis
665      */

666     public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
667         _numTestsPerEvictionRun = numTestsPerEvictionRun;
668     }
669
670     /**
671      * Returns the minimum amount of time an object may sit idle in the pool
672      * before it is eligable for eviction by the idle object evictor
673      * (if any).
674      *
675      * @see #setMinEvictableIdleTimeMillis
676      * @see #setTimeBetweenEvictionRunsMillis
677      */

678     public synchronized long getMinEvictableIdleTimeMillis() {
679         return _minEvictableIdleTimeMillis;
680     }
681
682     /**
683      * Sets the minimum amount of time an object may sit idle in the pool
684      * before it is eligable for eviction by the idle object evictor
685      * (if any).
686      * When non-positive, no objects will be evicted from the pool
687      * due to idle time alone.
688      *
689      * @see #getMinEvictableIdleTimeMillis
690      * @see #setTimeBetweenEvictionRunsMillis
691      */

692     public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
693         _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
694     }
695
696     /**
697      * Returns the minimum amount of time an object may sit idle in the pool
698      * before it is eligable for eviction by the idle object evictor
699      * (if any), with the extra condition that at least
700      * "minIdle" amount of object remain in the pool.
701      *
702      * @see #setSoftMinEvictableIdleTimeMillis
703      */

704     public synchronized long getSoftMinEvictableIdleTimeMillis() {
705         return _softMinEvictableIdleTimeMillis;
706     }
707
708     /**
709      * Sets the minimum amount of time an object may sit idle in the pool
710      * before it is eligable for eviction by the idle object evictor
711      * (if any), with the extra condition that at least
712      * "minIdle" amount of object remain in the pool.
713      * When non-positive, no objects will be evicted from the pool
714      * due to idle time alone.
715      *
716      * @see #getSoftMinEvictableIdleTimeMillis
717      */

718     public synchronized void setSoftMinEvictableIdleTimeMillis(long softMinEvictableIdleTimeMillis) {
719         _softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
720     }
721
722     /**
723      * When <tt>true</tt>, objects will be
724      * {@link PoolableObjectFactory#validateObject validated}
725      * by the idle object evictor (if any). If an object
726      * fails to validate, it will be dropped from the pool.
727      *
728      * @see #setTestWhileIdle
729      * @see #setTimeBetweenEvictionRunsMillis
730      */

731     public synchronized boolean getTestWhileIdle() {
732         return _testWhileIdle;
733     }
734
735     /**
736      * When <tt>true</tt>, objects will be
737      * {@link PoolableObjectFactory#validateObject validated}
738      * by the idle object evictor (if any). If an object
739      * fails to validate, it will be dropped from the pool.
740      *
741      * @see #getTestWhileIdle
742      * @see #setTimeBetweenEvictionRunsMillis
743      */

744     public synchronized void setTestWhileIdle(boolean testWhileIdle) {
745         _testWhileIdle = testWhileIdle;
746     }
747
748     /**
749      * Sets my configuration.
750      * @see GenericObjectPool.Config
751      */

752     public synchronized void setConfig(GenericObjectPool.Config conf) {
753         setMaxIdle(conf.maxIdle);
754         setMinIdle(conf.minIdle);
755         setMaxActive(conf.maxActive);
756         setMaxWait(conf.maxWait);
757         setWhenExhaustedAction(conf.whenExhaustedAction);
758         setTestOnBorrow(conf.testOnBorrow);
759         setTestOnReturn(conf.testOnReturn);
760         setTestWhileIdle(conf.testWhileIdle);
761         setNumTestsPerEvictionRun(conf.numTestsPerEvictionRun);
762         setMinEvictableIdleTimeMillis(conf.minEvictableIdleTimeMillis);
763         setTimeBetweenEvictionRunsMillis(conf.timeBetweenEvictionRunsMillis);
764         notifyAll();
765     }
766
767     //-- ObjectPool methods ------------------------------------------
768

769     public Object JavaDoc borrowObject() throws Exception JavaDoc {
770         long starttime = System.currentTimeMillis();
771         boolean newlyCreated = false;
772         for(;;) {
773             ObjectTimestampPair pair = null;
774
775             synchronized(this) {
776                 assertOpen();
777
778                 // if there are any sleeping, just grab one of those
779
try {
780                     pair = (ObjectTimestampPair)(_pool.removeFirst());
781                 } catch(NoSuchElementException JavaDoc e) {
782                     ; /* ignored */
783                 }
784
785                 // otherwise
786
if(null == pair) {
787                     // check if we can create one
788
// (note we know that the num sleeping is 0, else we wouldn't be here)
789
if(_maxActive < 0 || _numActive < _maxActive) {
790                         // allow new object to be created
791
} else {
792                         // the pool is exhausted
793
switch(_whenExhaustedAction) {
794                             case WHEN_EXHAUSTED_GROW:
795                                 // allow new object to be created
796
break;
797                             case WHEN_EXHAUSTED_FAIL:
798                                 throw new NoSuchElementException JavaDoc("Pool exhausted");
799                             case WHEN_EXHAUSTED_BLOCK:
800                                     try {
801                                         if(_maxWait <= 0) {
802                                             wait();
803                                         } else {
804                                             wait(_maxWait);
805                                         }
806                                     } catch(InterruptedException JavaDoc e) {
807                                         // ignored
808
}
809                                     if(_maxWait > 0 && ((System.currentTimeMillis() - starttime) >= _maxWait)) {
810                                         throw new NoSuchElementException JavaDoc("Timeout waiting for idle object");
811                                     } else {
812                                         continue; // keep looping
813
}
814                             default:
815                                 throw new IllegalArgumentException JavaDoc("WhenExhaustedAction property " + _whenExhaustedAction + " not recognized.");
816                         }
817                     }
818                 }
819                 _numActive++;
820             } // end synchronized
821

822             // create new object when needed
823
if(null == pair) {
824                 try {
825                     Object JavaDoc obj = _factory.makeObject();
826                     pair = new ObjectTimestampPair(obj);
827                     newlyCreated = true;
828                 }
829                 catch (Throwable JavaDoc e) {
830                     // object cannot be created
831
synchronized(this) {
832                         _numActive--;
833                         notifyAll();
834                     }
835                     if (e instanceof Exception JavaDoc) {
836                         throw (Exception JavaDoc) e;
837                     } else if (e instanceof Error JavaDoc) {
838                         throw (Error JavaDoc) e;
839                     } else {
840                         throw new Exception JavaDoc(e);
841                     }
842                 }
843             }
844
845             // activate & validate the object
846
try {
847                 _factory.activateObject(pair.value);
848                 if(_testOnBorrow && !_factory.validateObject(pair.value)) {
849                     throw new Exception JavaDoc("ValidateObject failed");
850                 }
851                 return pair.value;
852             }
853             catch (Throwable JavaDoc e) {
854                 // object cannot be activated or is invalid
855
synchronized(this) {
856                     _numActive--;
857                     notifyAll();
858                 }
859                 try {
860                     _factory.destroyObject(pair.value);
861                 }
862                 catch (Throwable JavaDoc e2) {
863                     // cannot destroy broken object
864
}
865                 if(newlyCreated) {
866                     throw new NoSuchElementException JavaDoc("Could not create a validated object, cause: " + e.getMessage());
867                 }
868                 else {
869                     continue; // keep looping
870
}
871             }
872         }
873     }
874
875     public void invalidateObject(Object JavaDoc obj) throws Exception JavaDoc {
876         assertOpen();
877         try {
878             _factory.destroyObject(obj);
879         }
880         finally {
881             synchronized(this) {
882                 _numActive--;
883                 notifyAll(); // _numActive has changed
884
}
885         }
886     }
887
888     public synchronized void clear() {
889         assertOpen();
890         for(Iterator JavaDoc it = _pool.iterator(); it.hasNext(); ) {
891             try {
892                 _factory.destroyObject(((ObjectTimestampPair)(it.next())).value);
893             } catch(Exception JavaDoc e) {
894                 // ignore error, keep destroying the rest
895
}
896             it.remove();
897         }
898         _pool.clear();
899         notifyAll(); // num sleeping has changed
900
}
901
902     public synchronized int getNumActive() {
903         assertOpen();
904         return _numActive;
905     }
906
907     public synchronized int getNumIdle() {
908         assertOpen();
909         return _pool.size();
910     }
911
912     public void returnObject(Object JavaDoc obj) throws Exception JavaDoc {
913         assertOpen();
914         addObjectToPool(obj, true);
915     }
916         
917     private void addObjectToPool(Object JavaDoc obj, boolean decrementNumActive) throws Exception JavaDoc {
918         boolean success = true;
919         if(_testOnReturn && !(_factory.validateObject(obj))) {
920             success = false;
921         } else {
922             try {
923                 _factory.passivateObject(obj);
924             } catch(Exception JavaDoc e) {
925                 success = false;
926             }
927         }
928
929         boolean shouldDestroy = !success;
930
931         synchronized(this) {
932             if (decrementNumActive) {
933                 _numActive--;
934             }
935             if((_maxIdle >= 0) && (_pool.size() >= _maxIdle)) {
936                 shouldDestroy = true;
937             } else if(success) {
938                 _pool.addFirst(new ObjectTimestampPair(obj));
939             }
940             notifyAll(); // _numActive has changed
941
}
942
943         if(shouldDestroy) {
944             try {
945                 _factory.destroyObject(obj);
946             } catch(Exception JavaDoc e) {
947                 // ignored
948
}
949         }
950     }
951
952     public synchronized void close() throws Exception JavaDoc {
953         clear();
954         _pool = null;
955         _factory = null;
956         if(null != _evictionCursor) {
957             _evictionCursor.close();
958             _evictionCursor = null;
959         }
960         startEvictor(-1L);
961         super.close();
962     }
963
964     public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException JavaDoc {
965         assertOpen();
966         if(0 < getNumActive()) {
967             throw new IllegalStateException JavaDoc("Objects are already active");
968         } else {
969             clear();
970             _factory = factory;
971         }
972     }
973
974     public synchronized void evict() throws Exception JavaDoc {
975         assertOpen();
976         if(!_pool.isEmpty()) {
977             if(null == _evictionCursor) {
978                 _evictionCursor = (_pool.cursor(_pool.size()));
979             } else if(!_evictionCursor.hasPrevious()) {
980                 _evictionCursor.close();
981                 _evictionCursor = (_pool.cursor(_pool.size()));
982             }
983             for(int i=0,m=getNumTests();i<m;i++) {
984                 if(!_evictionCursor.hasPrevious()) {
985                     _evictionCursor.close();
986                     _evictionCursor = (_pool.cursor(_pool.size()));
987                 } else {
988                     boolean removeObject = false;
989                     ObjectTimestampPair pair = (ObjectTimestampPair)(_evictionCursor.previous());
990                     long idleTimeMilis = System.currentTimeMillis() - pair.tstamp;
991                     if ((_minEvictableIdleTimeMillis > 0)
992                         && (idleTimeMilis > _minEvictableIdleTimeMillis)) {
993                         removeObject = true;
994                     } else if ((_softMinEvictableIdleTimeMillis > 0)
995                         && (idleTimeMilis > _softMinEvictableIdleTimeMillis)
996                         && (getNumIdle() > getMinIdle())) {
997                         removeObject = true;
998                     } else if(_testWhileIdle) {
999                         boolean active = false;
1000                        try {
1001                            _factory.activateObject(pair.value);
1002                            active = true;
1003                        } catch(Exception JavaDoc e) {
1004                            removeObject=true;
1005                        }
1006                        if(active) {
1007                            if(!_factory.validateObject(pair.value)) {
1008                                removeObject=true;
1009                            } else {
1010                                try {
1011                                    _factory.passivateObject(pair.value);
1012                                } catch(Exception JavaDoc e) {
1013                                    removeObject=true;
1014                                }
1015                            }
1016                        }
1017                    }
1018                    if(removeObject) {
1019                        try {
1020                            _evictionCursor.remove();
1021                            _factory.destroyObject(pair.value);
1022                        } catch(Exception JavaDoc e) {
1023                            ; // ignored
1024
}
1025                    }
1026                }
1027            }
1028        } // if !empty
1029
}
1030    
1031    /**
1032     * Check to see if we are below our minimum number of objects
1033     * if so enough to bring us back to our minimum.
1034     */

1035    private void ensureMinIdle() throws Exception JavaDoc {
1036        // this method isn't synchronized so the
1037
// calculateDeficit is done at the beginning
1038
// as a loop limit and a second time inside the loop
1039
// to stop when another thread already returned the
1040
// needed objects
1041
int objectDeficit = calculateDeficit();
1042        for ( int j = 0 ; j < objectDeficit && calculateDeficit() > 0 ; j++ ) {
1043            addObject();
1044        }
1045    }
1046
1047    private synchronized int calculateDeficit() {
1048        int objectDeficit = getMinIdle() - getNumIdle();
1049        if (_maxActive > 0) {
1050            int growLimit = Math.max(0, getMaxActive() - getNumActive() - getNumIdle());
1051            objectDeficit = Math.min(objectDeficit, growLimit);
1052        }
1053        return objectDeficit;
1054    }
1055
1056    /**
1057     * Create an object, and place it into the pool.
1058     * addObject() is useful for "pre-loading" a pool with idle objects.
1059     */

1060    public void addObject() throws Exception JavaDoc {
1061        Object JavaDoc obj = _factory.makeObject();
1062        addObjectToPool(obj, false);
1063    }
1064    
1065    //--- non-public methods ----------------------------------------
1066

1067    /**
1068     * Start the eviction thread or service, or when
1069     * <i>delay</i> is non-positive, stop it
1070     * if it is already running.
1071     */

1072    protected synchronized void startEvictor(long delay) {
1073        if(null != _evictor) {
1074            _evictor.cancel();
1075            _evictor = null;
1076        }
1077        if(delay > 0) {
1078            _evictor = new Evictor(delay);
1079            Thread JavaDoc t = new Thread JavaDoc(_evictor);
1080            t.setDaemon(true);
1081            t.start();
1082        }
1083    }
1084
1085    synchronized String JavaDoc debugInfo() {
1086        StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
1087        buf.append("Active: ").append(getNumActive()).append("\n");
1088        buf.append("Idle: ").append(getNumIdle()).append("\n");
1089        buf.append("Idle Objects:\n");
1090        Iterator JavaDoc it = _pool.iterator();
1091        long time = System.currentTimeMillis();
1092        while(it.hasNext()) {
1093            ObjectTimestampPair pair = (ObjectTimestampPair)(it.next());
1094            buf.append("\t").append(pair.value).append("\t").append(time - pair.tstamp).append("\n");
1095        }
1096        return buf.toString();
1097    }
1098
1099    private int getNumTests() {
1100        if(_numTestsPerEvictionRun >= 0) {
1101            return _numTestsPerEvictionRun;
1102        } else {
1103            return(int)(Math.ceil((double)_pool.size()/Math.abs((double)_numTestsPerEvictionRun)));
1104        }
1105    }
1106
1107    //--- inner classes ----------------------------------------------
1108

1109    /**
1110     * A simple "struct" encapsulating an object instance and a timestamp.
1111     */

1112    class ObjectTimestampPair {
1113        Object JavaDoc value;
1114        long tstamp;
1115
1116        ObjectTimestampPair(Object JavaDoc val) {
1117            this(val,System.currentTimeMillis());
1118        }
1119
1120        ObjectTimestampPair(Object JavaDoc val, long time) {
1121            value = val;
1122            tstamp = time;
1123        }
1124    }
1125
1126    /**
1127     * The idle object evictor thread.
1128     * @see #setTimeBetweenEvictionRunsMillis
1129     */

1130    class Evictor implements Runnable JavaDoc {
1131        private boolean _cancelled = false;
1132        private long _delay = 0L;
1133
1134        public Evictor(long delay) {
1135            _delay = delay;
1136        }
1137
1138        void cancel() {
1139            _cancelled = true;
1140        }
1141
1142        public void run() {
1143            while(!_cancelled) {
1144                try {
1145                    Thread.sleep(_delay);
1146                } catch(Exception JavaDoc e) {
1147                    // ignored
1148
}
1149                try {
1150                    evict();
1151                } catch(Exception JavaDoc e) {
1152                    // ignored
1153
}
1154                try {
1155                    ensureMinIdle();
1156                } catch(Exception JavaDoc e) {
1157                    // ignored
1158
}
1159            }
1160            synchronized(GenericObjectPool.this) {
1161                if(null != _evictionCursor) {
1162                    _evictionCursor.close();
1163                    _evictionCursor = null;
1164                }
1165            }
1166        }
1167
1168    }
1169
1170    /**
1171     * A simple "struct" encapsulating the
1172     * configuration information for a {@link GenericObjectPool}.
1173     * @see GenericObjectPool#GenericObjectPool(org.apache.commons.pool.PoolableObjectFactory,org.apache.commons.pool.impl.GenericObjectPool.Config)
1174     * @see GenericObjectPool#setConfig
1175     */

1176    public static class Config {
1177        public int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
1178        public int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE;
1179        public int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
1180        public long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;
1181        public byte whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
1182        public boolean testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW;
1183        public boolean testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN;
1184        public boolean testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE;
1185        public long timeBetweenEvictionRunsMillis = GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
1186        public int numTestsPerEvictionRun = GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
1187        public long minEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
1188        public long softMinEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
1189    }
1190
1191    //--- private attributes ---------------------------------------
1192

1193    /**
1194     * The cap on the number of idle instances in the pool.
1195     * @see #setMaxIdle
1196     * @see #getMaxIdle
1197     */

1198    private int _maxIdle = DEFAULT_MAX_IDLE;
1199
1200    /**
1201    * The cap on the minimum number of idle instances in the pool.
1202    * @see #setMinIdle
1203    * @see #getMinIdle
1204    */

1205   private int _minIdle = DEFAULT_MIN_IDLE;
1206
1207    /**
1208     * The cap on the total number of active instances from the pool.
1209     * @see #setMaxActive
1210     * @see #getMaxActive
1211     */

1212    private int _maxActive = DEFAULT_MAX_ACTIVE;
1213
1214    /**
1215     * The maximum amount of time (in millis) the
1216     * {@link #borrowObject} method should block before throwing
1217     * an exception when the pool is exhausted and the
1218     * {@link #getWhenExhaustedAction "when exhausted" action} is
1219     * {@link #WHEN_EXHAUSTED_BLOCK}.
1220     *
1221     * When less than 0, the {@link #borrowObject} method
1222     * may block indefinitely.
1223     *
1224     * @see #setMaxWait
1225     * @see #getMaxWait
1226     * @see #WHEN_EXHAUSTED_BLOCK
1227     * @see #setWhenExhaustedAction
1228     * @see #getWhenExhaustedAction
1229     */

1230    private long _maxWait = DEFAULT_MAX_WAIT;
1231
1232    /**
1233     * The action to take when the {@link #borrowObject} method
1234     * is invoked when the pool is exhausted (the maximum number
1235     * of "active" objects has been reached).
1236     *
1237     * @see #WHEN_EXHAUSTED_BLOCK
1238     * @see #WHEN_EXHAUSTED_FAIL
1239     * @see #WHEN_EXHAUSTED_GROW
1240     * @see #DEFAULT_WHEN_EXHAUSTED_ACTION
1241     * @see #setWhenExhaustedAction
1242     * @see #getWhenExhaustedAction
1243     */

1244    private byte _whenExhaustedAction = DEFAULT_WHEN_EXHAUSTED_ACTION;
1245
1246    /**
1247     * When <tt>true</tt>, objects will be
1248     * {@link PoolableObjectFactory#validateObject validated}
1249     * before being returned by the {@link #borrowObject}
1250     * method. If the object fails to validate,
1251     * it will be dropped from the pool, and we will attempt
1252     * to borrow another.
1253     *
1254     * @see #setTestOnBorrow
1255     * @see #getTestOnBorrow
1256     */

1257    private boolean _testOnBorrow = DEFAULT_TEST_ON_BORROW;
1258
1259    /**
1260     * When <tt>true</tt>, objects will be
1261     * {@link PoolableObjectFactory#validateObject validated}
1262     * before being returned to the pool within the
1263     * {@link #returnObject}.
1264     *
1265     * @see #getTestOnReturn
1266     * @see #setTestOnReturn
1267     */

1268    private boolean _testOnReturn = DEFAULT_TEST_ON_RETURN;
1269
1270    /**
1271     * When <tt>true</tt>, objects will be
1272     * {@link PoolableObjectFactory#validateObject validated}
1273     * by the idle object evictor (if any). If an object
1274     * fails to validate, it will be dropped from the pool.
1275     *
1276     * @see #setTestWhileIdle
1277     * @see #getTestWhileIdle
1278     * @see #getTimeBetweenEvictionRunsMillis
1279     * @see #setTimeBetweenEvictionRunsMillis
1280     */

1281    private boolean _testWhileIdle = DEFAULT_TEST_WHILE_IDLE;
1282
1283    /**
1284     * The number of milliseconds to sleep between runs of the
1285     * idle object evictor thread.
1286     * When non-positive, no idle object evictor thread will be
1287     * run.
1288     *
1289     * @see #setTimeBetweenEvictionRunsMillis
1290     * @see #getTimeBetweenEvictionRunsMillis
1291     */

1292    private long _timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
1293
1294    /**
1295     * The number of objects to examine during each run of the
1296     * idle object evictor thread (if any).
1297     * <p>
1298     * When a negative value is supplied, <tt>ceil({@link #getNumIdle})/abs({@link #getNumTestsPerEvictionRun})</tt>
1299     * tests will be run. I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
1300     * idle objects will be tested per run.
1301     *
1302     * @see #setNumTestsPerEvictionRun
1303     * @see #getNumTestsPerEvictionRun
1304     * @see #getTimeBetweenEvictionRunsMillis
1305     * @see #setTimeBetweenEvictionRunsMillis
1306     */

1307    private int _numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
1308
1309    /**
1310     * The minimum amount of time an object may sit idle in the pool
1311     * before it is eligable for eviction by the idle object evictor
1312     * (if any).
1313     * When non-positive, no objects will be evicted from the pool
1314     * due to idle time alone.
1315     *
1316     * @see #setMinEvictableIdleTimeMillis
1317     * @see #getMinEvictableIdleTimeMillis
1318     * @see #getTimeBetweenEvictionRunsMillis
1319     * @see #setTimeBetweenEvictionRunsMillis
1320     */

1321    private long _minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
1322
1323    /**
1324     * The minimum amount of time an object may sit idle in the pool
1325     * before it is eligable for eviction by the idle object evictor
1326     * (if any), with the extra condition that at least
1327     * "minIdle" amount of object remain in the pool.
1328     * When non-positive, no objects will be evicted from the pool
1329     * due to idle time alone.
1330     *
1331     * @see #setSoftMinEvictableIdleTimeMillis
1332     * @see #getSoftMinEvictableIdleTimeMillis
1333     */

1334    private long _softMinEvictableIdleTimeMillis = DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
1335
1336    /** My pool. */
1337    private CursorableLinkedList _pool = null;
1338
1339    /** My {@link PoolableObjectFactory}. */
1340    private PoolableObjectFactory _factory = null;
1341
1342    /**
1343     * The number of objects {@link #borrowObject} borrowed
1344     * from the pool, but not yet returned.
1345     */

1346    private int _numActive = 0;
1347
1348    /**
1349     * My idle object eviction thread, if any.
1350     */

1351    private Evictor _evictor = null;
1352
1353    private CursorableLinkedList.Cursor _evictionCursor = null;
1354}
1355
Popular Tags