1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.pool;
18
19 import java.util.Collection;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.Map;
23 import java.util.NoSuchElementException;
24 import java.util.Timer;
25 import java.util.TimerTask;
26
27 /***
28 * This class consists exclusively of static methods that operate on or return keyedPool related interfaces.
29 *
30 * @author Sandy McArthur
31 * @version $Revision: 385296 $ $Date: 2006-03-12 10:28:08 -0500 (Sun, 12 Mar 2006) $
32 * @since Pool 1.3
33 */
34 public final class PoolUtils {
35
36 /***
37 * Timer used to periodically check pools idle object count.
38 * Because a {@link Timer} creates a {@link Thread} this is lazily instantiated.
39 */
40 private static Timer MIN_IDLE_TIMER;
41
42 /***
43 * PoolUtils instances should NOT be constructed in standard programming.
44 * Instead, the class should be used procedurally: PoolUtils.adapt(aPool);.
45 * This constructor is public to permit tools that require a JavaBean instance to operate.
46 */
47 public PoolUtils() {
48 }
49
50 /***
51 * Adapt a <code>KeyedPoolableObjectFactory</code> instance to work where a <code>PoolableObjectFactory</code> is
52 * needed. This method is the equivalent of calling
53 * {@link #adapt(KeyedPoolableObjectFactory, Object) PoolUtils.adapt(aKeyedPoolableObjectFactory, new Object())}.
54 *
55 * @param keyedFactory the {@link KeyedPoolableObjectFactory} to delegate to.
56 * @return a {@link PoolableObjectFactory} that delegates to <code>keyedFactory</code> with an internal key.
57 * @throws IllegalArgumentException when <code>keyedFactory</code> is <code>null</code>.
58 * @see #adapt(KeyedPoolableObjectFactory, Object)
59 * @since Pool 1.3
60 */
61 public static PoolableObjectFactory adapt(final KeyedPoolableObjectFactory keyedFactory) throws IllegalArgumentException {
62 return adapt(keyedFactory, new Object());
63 }
64
65 /***
66 * Adapt a <code>KeyedPoolableObjectFactory</code> instance to work where a <code>PoolableObjectFactory</code> is
67 * needed using the specified <code>key</code> when delegating.
68 *
69 * @param keyedFactory the {@link KeyedPoolableObjectFactory} to delegate to.
70 * @param key the key to use when delegating.
71 * @return a {@link PoolableObjectFactory} that delegates to <code>keyedFactory</code> with the specified key.
72 * @throws IllegalArgumentException when <code>keyedFactory</code> or <code>key</code> is <code>null</code>.
73 * @see #adapt(KeyedPoolableObjectFactory)
74 * @since Pool 1.3
75 */
76 public static PoolableObjectFactory adapt(final KeyedPoolableObjectFactory keyedFactory, final Object key) throws IllegalArgumentException {
77 return new PoolableObjectFactoryAdaptor(keyedFactory, key);
78 }
79
80 /***
81 * Adapt a <code>PoolableObjectFactory</code> instance to work where a <code>KeyedPoolableObjectFactory</code> is
82 * needed. The key is ignored.
83 *
84 * @param factory the {@link PoolableObjectFactory} to delegate to.
85 * @return a {@link KeyedPoolableObjectFactory} that delegates to <code>factory</code> ignoring the key.
86 * @throws IllegalArgumentException when <code>factory</code> is <code>null</code>.
87 * @since Pool 1.3
88 */
89 public static KeyedPoolableObjectFactory adapt(final PoolableObjectFactory factory) throws IllegalArgumentException {
90 return new KeyedPoolableObjectFactoryAdaptor(factory);
91 }
92
93 /***
94 * Adapt a <code>KeyedObjectPool</code> instance to work where an <code>ObjectPool</code> is needed. This is the
95 * equivalent of calling {@link #adapt(KeyedObjectPool, Object) PoolUtils.adapt(aKeyedObjectPool, new Object())}.
96 *
97 * @param keyedPool the {@link KeyedObjectPool} to delegate to.
98 * @return an {@link ObjectPool} that delegates to <code>keyedPool</code> with an internal key.
99 * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code>.
100 * @see #adapt(KeyedObjectPool, Object)
101 * @since Pool 1.3
102 */
103 public static ObjectPool adapt(final KeyedObjectPool keyedPool) throws IllegalArgumentException {
104 return adapt(keyedPool, new Object());
105 }
106
107 /***
108 * Adapt a <code>KeyedObjectPool</code> instance to work where an <code>ObjectPool</code> is needed using the
109 * specified <code>key</code> when delegating.
110 *
111 * @param keyedPool the {@link KeyedObjectPool} to delegate to.
112 * @param key the key to use when delegating.
113 * @return an {@link ObjectPool} that delegates to <code>keyedPool</code> with the specified key.
114 * @throws IllegalArgumentException when <code>keyedPool</code> or <code>key</code> is <code>null</code>.
115 * @see #adapt(KeyedObjectPool)
116 * @since Pool 1.3
117 */
118 public static ObjectPool adapt(final KeyedObjectPool keyedPool, final Object key) throws IllegalArgumentException {
119 return new ObjectPoolAdaptor(keyedPool, key);
120 }
121
122 /***
123 * Adapt an <code>ObjectPool</code> to work where an <code>KeyedObjectPool</code> is needed.
124 * The key is ignored.
125 *
126 * @param pool the {@link ObjectPool} to delegate to.
127 * @return a {@link KeyedObjectPool} that delegates to <code>keyedPool</code> ignoring the key.
128 * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code>.
129 * @since Pool 1.3
130 */
131 public static KeyedObjectPool adapt(final ObjectPool pool) throws IllegalArgumentException {
132 return new KeyedObjectPoolAdaptor(pool);
133 }
134
135 /***
136 * Wraps an <code>ObjectPool</code> and dynamically checks the type of objects borrowed and returned to the keyedPool.
137 * If an object is passed to the keyedPool that isn't of type <code>type</code> a {@link ClassCastException} will be thrown.
138 *
139 * @param pool the keyedPool to enforce type safety on
140 * @return an <code>ObjectPool</code> that will only allow objects of <code>type</code>
141 * @since Pool 1.3
142 */
143 public static ObjectPool checkedPool(final ObjectPool pool, final Class type) {
144 if (pool == null) {
145 throw new IllegalArgumentException("pool must not be null.");
146 }
147 if (type == null) {
148 throw new IllegalArgumentException("type must not be null.");
149 }
150 return new CheckedObjectPool(pool, type);
151 }
152
153 /***
154 * Wraps an <code>KeyedObjectPool</code> and dynamically checks the type of objects borrowed and returned to the keyedPool.
155 * If an object is passed to the keyedPool that isn't of type <code>type</code> a {@link ClassCastException} will be thrown.
156 *
157 * @param keyedPool the keyedPool to enforce type safety on
158 * @return an <code>KeyedObjectPool</code> that will only allow objects of <code>type</code>
159 * @since Pool 1.3
160 */
161 public static KeyedObjectPool checkedPool(final KeyedObjectPool keyedPool, final Class type) {
162 if (keyedPool == null) {
163 throw new IllegalArgumentException("keyedPool must not be null.");
164 }
165 if (type == null) {
166 throw new IllegalArgumentException("type must not be null.");
167 }
168 return new CheckedKeyedObjectPool(keyedPool, type);
169 }
170
171 /***
172 * Periodically check the idle object count for the keyedPool. At most one idle object will be added per period.
173 * If there is an exception when calling {@link ObjectPool#addObject()} then no more checks will be performed.
174 *
175 * @param pool the keyedPool to check periodically.
176 * @param minIdle if the {@link ObjectPool#getNumIdle()} is less than this then add an idle object.
177 * @param period the frequency to check the number of idle objects in a keyedPool, see
178 * {@link Timer#schedule(TimerTask, long, long)}.
179 * @return the {@link TimerTask} that will periodically check the pools idle object count.
180 * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code> or
181 * when <code>minIdle</code> is negative or when <code>period</code> isn't
182 * valid for {@link Timer#schedule(TimerTask, long, long)}.
183 * @since Pool 1.3
184 */
185 public static TimerTask checkMinIdle(final ObjectPool pool, final int minIdle, final long period) throws IllegalArgumentException {
186 if (pool == null) {
187 throw new IllegalArgumentException("keyedPool must not be null.");
188 }
189 if (minIdle < 0) {
190 throw new IllegalArgumentException("minIdle must be non-negative.");
191 }
192 final TimerTask task = new ObjectPoolMinIdleTimerTask(pool, minIdle);
193 getMinIdleTimer().schedule(task, 0L, period);
194 return task;
195 }
196
197 /***
198 * Periodically check the idle object count for the key in the keyedPool. At most one idle object will be added per period.
199 * If there is an exception when calling {@link KeyedObjectPool#addObject(Object)} then no more checks for that key
200 * will be performed.
201 *
202 * @param keyedPool the keyedPool to check periodically.
203 * @param key the key to check the idle count of.
204 * @param minIdle if the {@link KeyedObjectPool#getNumIdle(Object)} is less than this then add an idle object.
205 * @param period the frequency to check the number of idle objects in a keyedPool, see
206 * {@link Timer#schedule(TimerTask, long, long)}.
207 * @return the {@link TimerTask} that will periodically check the pools idle object count.
208 * @throws IllegalArgumentException when <code>keyedPool</code>, <code>key</code> is <code>null</code> or
209 * when <code>minIdle</code> is negative or when <code>period</code> isn't
210 * valid for {@link Timer#schedule(TimerTask, long, long)}.
211 * @since Pool 1.3
212 */
213 public static TimerTask checkMinIdle(final KeyedObjectPool keyedPool, final Object key, final int minIdle, final long period) throws IllegalArgumentException {
214 if (keyedPool == null) {
215 throw new IllegalArgumentException("keyedPool must not be null.");
216 }
217 if (key == null) {
218 throw new IllegalArgumentException("key must not be null.");
219 }
220 if (minIdle < 0) {
221 throw new IllegalArgumentException("minIdle must be non-negative.");
222 }
223 final TimerTask task = new KeyedObjectPoolMinIdleTimerTask(keyedPool, key, minIdle);
224 getMinIdleTimer().schedule(task, 0L, period);
225 return task;
226 }
227
228 /***
229 * Periodically check the idle object count for each key in the <code>Collection</code> <code>keys</code> in the keyedPool.
230 * At most one idle object will be added per period.
231 *
232 * @param keyedPool the keyedPool to check periodically.
233 * @param keys a collection of keys to check the idle object count.
234 * @param minIdle if the {@link KeyedObjectPool#getNumIdle(Object)} is less than this then add an idle object.
235 * @param period the frequency to check the number of idle objects in a keyedPool, see
236 * {@link Timer#schedule(TimerTask, long, long)}.
237 * @return a {@link Map} of key and {@link TimerTask} pairs that will periodically check the pools idle object count.
238 * @throws IllegalArgumentException when <code>keyedPool</code>, <code>keys</code>, or any of the values in the
239 * collection is <code>null</code> or when <code>minIdle</code> is negative or when <code>period</code> isn't
240 * valid for {@link Timer#schedule(TimerTask, long, long)}.
241 * @see #checkMinIdle(KeyedObjectPool, Object, int, long)
242 * @since Pool 1.3
243 */
244 public static Map checkMinIdle(final KeyedObjectPool keyedPool, final Collection keys, final int minIdle, final long period) throws IllegalArgumentException {
245 if (keys == null) {
246 throw new IllegalArgumentException("keys must not be null.");
247 }
248 final Map tasks = new HashMap(keys.size());
249 final Iterator iter = keys.iterator();
250 while (iter.hasNext()) {
251 final Object key = iter.next();
252 final TimerTask task = checkMinIdle(keyedPool, key, minIdle, period);
253 tasks.put(key, task);
254 }
255 return tasks;
256 }
257
258 /***
259 * Call <code>addObject()</code> on <code>keyedPool</code> <code>count</code> number of times.
260 *
261 * @param pool the keyedPool to prefill.
262 * @param count the number of idle objects to add.
263 * @throws Exception when {@link ObjectPool#addObject()} fails.
264 * @throws IllegalArgumentException when <code>keyedPool</code> is <code>null</code>.
265 * @since Pool 1.3
266 */
267 public static void prefill(final ObjectPool pool, final int count) throws Exception, IllegalArgumentException {
268 if (pool == null) {
269 throw new IllegalArgumentException("keyedPool must not be null.");
270 }
271 for (int i = 0; i < count; i++) {
272 pool.addObject();
273 }
274 }
275
276 /***
277 * Call <code>addObject(Object)</code> on <code>keyedPool</code> with <code>key</code> <code>count</code>
278 * number of times.
279 *
280 * @param keyedPool the keyedPool to prefill.
281 * @param key the key to add objects for.
282 * @param count the number of idle objects to add for <code>key</code>.
283 * @throws Exception when {@link KeyedObjectPool#addObject(Object)} fails.
284 * @throws IllegalArgumentException when <code>keyedPool</code> or <code>key</code> is <code>null</code>.
285 * @since Pool 1.3
286 */
287 public static void prefill(final KeyedObjectPool keyedPool, final Object key, final int count) throws Exception, IllegalArgumentException {
288 if (keyedPool == null) {
289 throw new IllegalArgumentException("keyedPool must not be null.");
290 }
291 if (key == null) {
292 throw new IllegalArgumentException("key must not be null.");
293 }
294 for (int i = 0; i < count; i++) {
295 keyedPool.addObject(key);
296 }
297 }
298
299 /***
300 * Call <code>addObject(Object)</code> on <code>keyedPool</code> with each key in <code>keys</code> for
301 * <code>count</code> number of times. This has the same effect as calling
302 * {@link #prefill(KeyedObjectPool, Object, int)} for each key in the <code>keys</code> collection.
303 *
304 * @param keyedPool the keyedPool to prefill.
305 * @param keys {@link Collection} of keys to add objects for.
306 * @param count the number of idle objects to add for each <code>key</code>.
307 * @throws Exception when {@link KeyedObjectPool#addObject(Object)} fails.
308 * @throws IllegalArgumentException when <code>keyedPool</code>, <code>keys</code>, or
309 * any value in <code>keys</code> is <code>null</code>.
310 * @see #prefill(KeyedObjectPool, Object, int)
311 * @since Pool 1.3
312 */
313 public static void prefill(final KeyedObjectPool keyedPool, final Collection keys, final int count) throws Exception, IllegalArgumentException {
314 if (keys == null) {
315 throw new IllegalArgumentException("keys must not be null.");
316 }
317 final Iterator iter = keys.iterator();
318 while (iter.hasNext()) {
319 prefill(keyedPool, iter.next(), count);
320 }
321 }
322
323 /***
324 * Returns a synchronized (thread-safe) ObjectPool backed by the specified ObjectPool.
325 *
326 * @param pool the ObjectPool to be "wrapped" in a synchronized ObjectPool.
327 * @return a synchronized view of the specified ObjectPool.
328 * @since Pool 1.3
329 */
330 public static ObjectPool synchronizedPool(final ObjectPool pool) {
331 return new SynchronizedObjectPool(pool);
332 }
333
334 /***
335 * Returns a synchronized (thread-safe) KeyedObjectPool backed by the specified KeyedObjectPool.
336 *
337 * @param keyedPool the KeyedObjectPool to be "wrapped" in a synchronized KeyedObjectPool.
338 * @return a synchronized view of the specified KeyedObjectPool.
339 * @since Pool 1.3
340 */
341 public static KeyedObjectPool synchronizedPool(final KeyedObjectPool keyedPool) {
342 return new SynchronizedKeyedObjectPool(keyedPool);
343 }
344
345 /***
346 * Returns a synchronized (thread-safe) PoolableObjectFactory backed by the specified PoolableObjectFactory.
347 *
348 * @param factory the PoolableObjectFactory to be "wrapped" in a synchronized PoolableObjectFactory.
349 * @return a synchronized view of the specified PoolableObjectFactory.
350 * @since Pool 1.3
351 */
352 public static PoolableObjectFactory synchronizedPoolableFactory(final PoolableObjectFactory factory) {
353 return new SynchronizedPoolableObjectFactory(factory);
354 }
355
356 /***
357 * Returns a synchronized (thread-safe) KeyedPoolableObjectFactory backed by the specified KeyedPoolableObjectFactory.
358 *
359 * @param keyedFactory the KeyedPoolableObjectFactory to be "wrapped" in a synchronized KeyedPoolableObjectFactory.
360 * @return a synchronized view of the specified KeyedPoolableObjectFactory.
361 * @since Pool 1.3
362 */
363 public static KeyedPoolableObjectFactory synchronizedPoolableFactory(final KeyedPoolableObjectFactory keyedFactory) {
364 return new SynchronizedKeyedPoolableObjectFactory(keyedFactory);
365 }
366
367 /***
368 * Get the <code>Timer</code> for checking keyedPool's idle count. Lazily create the {@link Timer} as needed.
369 *
370 * @return the {@link Timer} for checking keyedPool's idle count.
371 * @since Pool 1.3
372 */
373 private static synchronized Timer getMinIdleTimer() {
374 if (MIN_IDLE_TIMER == null) {
375 MIN_IDLE_TIMER = new Timer(true);
376 }
377 return MIN_IDLE_TIMER;
378 }
379
380 private static class PoolableObjectFactoryAdaptor implements PoolableObjectFactory {
381 private final Object key;
382 private final KeyedPoolableObjectFactory keyedFactory;
383
384 PoolableObjectFactoryAdaptor(final KeyedPoolableObjectFactory keyedFactory, final Object key) throws IllegalArgumentException {
385 if (keyedFactory == null) {
386 throw new IllegalArgumentException("keyedFactory must not be null.");
387 }
388 if (key == null) {
389 throw new IllegalArgumentException("key must not be null.");
390 }
391 this.keyedFactory = keyedFactory;
392 this.key = key;
393 }
394
395 public Object makeObject() throws Exception {
396 return keyedFactory.makeObject(key);
397 }
398
399 public void destroyObject(final Object obj) throws Exception {
400 keyedFactory.destroyObject(key, obj);
401 }
402
403 public boolean validateObject(final Object obj) {
404 return keyedFactory.validateObject(key, obj);
405 }
406
407 public void activateObject(final Object obj) throws Exception {
408 keyedFactory.activateObject(key, obj);
409 }
410
411 public void passivateObject(final Object obj) throws Exception {
412 keyedFactory.passivateObject(key, obj);
413 }
414
415 public String toString() {
416 final StringBuffer sb = new StringBuffer();
417 sb.append("PoolableObjectFactoryAdaptor");
418 sb.append("{key=").append(key);
419 sb.append(", keyedFactory=").append(keyedFactory);
420 sb.append('}');
421 return sb.toString();
422 }
423 }
424
425 private static class KeyedPoolableObjectFactoryAdaptor implements KeyedPoolableObjectFactory {
426 private final PoolableObjectFactory factory;
427
428 KeyedPoolableObjectFactoryAdaptor(final PoolableObjectFactory factory) throws IllegalArgumentException {
429 if (factory == null) {
430 throw new IllegalArgumentException("factory must not be null.");
431 }
432 this.factory = factory;
433 }
434
435 public Object makeObject(final Object key) throws Exception {
436 return factory.makeObject();
437 }
438
439 public void destroyObject(final Object key, final Object obj) throws Exception {
440 factory.destroyObject(obj);
441 }
442
443 public boolean validateObject(final Object key, final Object obj) {
444 return factory.validateObject(obj);
445 }
446
447 public void activateObject(final Object key, final Object obj) throws Exception {
448 factory.activateObject(obj);
449 }
450
451 public void passivateObject(final Object key, final Object obj) throws Exception {
452 factory.passivateObject(obj);
453 }
454
455 public String toString() {
456 final StringBuffer sb = new StringBuffer();
457 sb.append("KeyedPoolableObjectFactoryAdaptor");
458 sb.append("{factory=").append(factory);
459 sb.append('}');
460 return sb.toString();
461 }
462 }
463
464 private static class ObjectPoolAdaptor implements ObjectPool {
465 private final Object key;
466 private final KeyedObjectPool keyedPool;
467
468 ObjectPoolAdaptor(final KeyedObjectPool keyedPool, final Object key) throws IllegalArgumentException {
469 if (keyedPool == null) {
470 throw new IllegalArgumentException("keyedPool must not be null.");
471 }
472 if (key == null) {
473 throw new IllegalArgumentException("key must not be null.");
474 }
475 this.keyedPool = keyedPool;
476 this.key = key;
477 }
478
479 public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
480 return keyedPool.borrowObject(key);
481 }
482
483 public void returnObject(final Object obj) throws Exception {
484 keyedPool.returnObject(key, obj);
485 }
486
487 public void invalidateObject(final Object obj) throws Exception {
488 keyedPool.invalidateObject(key, obj);
489 }
490
491 public void addObject() throws Exception, IllegalStateException {
492 keyedPool.addObject(key);
493 }
494
495 public int getNumIdle() throws UnsupportedOperationException {
496 return keyedPool.getNumIdle(key);
497 }
498
499 public int getNumActive() throws UnsupportedOperationException {
500 return keyedPool.getNumActive(key);
501 }
502
503 public void clear() throws Exception, UnsupportedOperationException {
504 keyedPool.clear();
505 }
506
507 public void close() throws Exception {
508 keyedPool.close();
509 }
510
511 public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
512 keyedPool.setFactory(adapt(factory));
513 }
514
515 public String toString() {
516 final StringBuffer sb = new StringBuffer();
517 sb.append("ObjectPoolAdaptor");
518 sb.append("{key=").append(key);
519 sb.append(", keyedPool=").append(keyedPool);
520 sb.append('}');
521 return sb.toString();
522 }
523 }
524
525 private static class KeyedObjectPoolAdaptor implements KeyedObjectPool {
526 private final ObjectPool pool;
527
528 KeyedObjectPoolAdaptor(final ObjectPool pool) throws IllegalArgumentException {
529 if (pool == null) {
530 throw new IllegalArgumentException("keyedPool must not be null.");
531 }
532 this.pool = pool;
533 }
534
535 public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException {
536 return pool.borrowObject();
537 }
538
539 public void returnObject(final Object key, final Object obj) throws Exception {
540 pool.returnObject(obj);
541 }
542
543 public void invalidateObject(final Object key, final Object obj) throws Exception {
544 pool.invalidateObject(obj);
545 }
546
547 public void addObject(final Object key) throws Exception, IllegalStateException {
548 pool.addObject();
549 }
550
551 public int getNumIdle(final Object key) throws UnsupportedOperationException {
552 return pool.getNumIdle();
553 }
554
555 public int getNumActive(final Object key) throws UnsupportedOperationException {
556 return pool.getNumActive();
557 }
558
559 public int getNumIdle() throws UnsupportedOperationException {
560 return pool.getNumIdle();
561 }
562
563 public int getNumActive() throws UnsupportedOperationException {
564 return pool.getNumActive();
565 }
566
567 public void clear() throws Exception, UnsupportedOperationException {
568 pool.clear();
569 }
570
571 public void clear(final Object key) throws Exception, UnsupportedOperationException {
572 pool.clear();
573 }
574
575 public void close() throws Exception {
576 pool.close();
577 }
578
579 public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
580 pool.setFactory(adapt(factory));
581 }
582
583 public String toString() {
584 final StringBuffer sb = new StringBuffer();
585 sb.append("KeyedObjectPoolAdaptor");
586 sb.append("{keyedPool=").append(pool);
587 sb.append('}');
588 return sb.toString();
589 }
590 }
591
592 private static class CheckedObjectPool implements ObjectPool {
593 private final Class type;
594 private final ObjectPool pool;
595
596 CheckedObjectPool(final ObjectPool pool, final Class type) {
597 if (pool == null) {
598 throw new IllegalArgumentException("pool must not be null.");
599 }
600 if (type == null) {
601 throw new IllegalArgumentException("type must not be null.");
602 }
603 this.pool = pool;
604 this.type = type;
605 }
606
607 public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
608 final Object obj = pool.borrowObject();
609 if (type.isInstance(obj)) {
610 return obj;
611 } else {
612 throw new ClassCastException("Borrowed object is not of type: " + type.getName() + " was: " + obj);
613 }
614 }
615
616 public void returnObject(final Object obj) throws Exception {
617 if (type.isInstance(obj)) {
618 pool.returnObject(obj);
619 } else {
620 throw new ClassCastException("Returned object is not of type: " + type.getName() + " was: " + obj);
621 }
622 }
623
624 public void invalidateObject(final Object obj) throws Exception {
625 if (type.isInstance(obj)) {
626 pool.invalidateObject(obj);
627 } else {
628 throw new ClassCastException("Invalidated object is not of type: " + type.getName() + " was: " + obj);
629 }
630 }
631
632 public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {
633 pool.addObject();
634 }
635
636 public int getNumIdle() throws UnsupportedOperationException {
637 return pool.getNumIdle();
638 }
639
640 public int getNumActive() throws UnsupportedOperationException {
641 return pool.getNumActive();
642 }
643
644 public void clear() throws Exception, UnsupportedOperationException {
645 pool.clear();
646 }
647
648 public void close() throws Exception {
649 pool.close();
650 }
651
652 public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
653 pool.setFactory(factory);
654 }
655
656 public String toString() {
657 final StringBuffer sb = new StringBuffer();
658 sb.append("CheckedObjectPool");
659 sb.append("{type=").append(type);
660 sb.append(", keyedPool=").append(pool);
661 sb.append('}');
662 return sb.toString();
663 }
664 }
665
666 private static class CheckedKeyedObjectPool implements KeyedObjectPool {
667 private final Class type;
668 private final KeyedObjectPool keyedPool;
669
670 CheckedKeyedObjectPool(final KeyedObjectPool keyedPool, final Class type) {
671 if (keyedPool == null) {
672 throw new IllegalArgumentException("keyedPool must not be null.");
673 }
674 if (type == null) {
675 throw new IllegalArgumentException("type must not be null.");
676 }
677 this.keyedPool = keyedPool;
678 this.type = type;
679 }
680
681 public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException {
682 Object obj = keyedPool.borrowObject(key);
683 if (type.isInstance(obj)) {
684 return obj;
685 } else {
686 throw new ClassCastException("Borrowed object for key: " + key + " is not of type: " + type.getName() + " was: " + obj);
687 }
688 }
689
690 public void returnObject(final Object key, final Object obj) throws Exception {
691 if (type.isInstance(obj)) {
692 keyedPool.returnObject(key, obj);
693 } else {
694 throw new ClassCastException("Returned object for key: " + key + " is not of type: " + type.getName() + " was: " + obj);
695 }
696 }
697
698 public void invalidateObject(final Object key, final Object obj) throws Exception {
699 if (type.isInstance(obj)) {
700 keyedPool.invalidateObject(key, obj);
701 } else {
702 throw new ClassCastException("Invalidated object for key: " + key + " is not of type: " + type.getName() + " was: " + obj);
703 }
704 }
705
706 public void addObject(final Object key) throws Exception, IllegalStateException, UnsupportedOperationException {
707 keyedPool.addObject(key);
708 }
709
710 public int getNumIdle(final Object key) throws UnsupportedOperationException {
711 return keyedPool.getNumIdle(key);
712 }
713
714 public int getNumActive(final Object key) throws UnsupportedOperationException {
715 return keyedPool.getNumActive(key);
716 }
717
718 public int getNumIdle() throws UnsupportedOperationException {
719 return keyedPool.getNumIdle();
720 }
721
722 public int getNumActive() throws UnsupportedOperationException {
723 return keyedPool.getNumActive();
724 }
725
726 public void clear() throws Exception, UnsupportedOperationException {
727 keyedPool.clear();
728 }
729
730 public void clear(final Object key) throws Exception, UnsupportedOperationException {
731 keyedPool.clear(key);
732 }
733
734 public void close() throws Exception {
735 keyedPool.close();
736 }
737
738 public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
739 keyedPool.setFactory(factory);
740 }
741
742 public String toString() {
743 final StringBuffer sb = new StringBuffer();
744 sb.append("CheckedKeyedObjectPool");
745 sb.append("{type=").append(type);
746 sb.append(", keyedPool=").append(keyedPool);
747 sb.append('}');
748 return sb.toString();
749 }
750 }
751
752 private static class ObjectPoolMinIdleTimerTask extends TimerTask {
753 private final int minIdle;
754 private final ObjectPool pool;
755
756 ObjectPoolMinIdleTimerTask(final ObjectPool pool, final int minIdle) throws IllegalArgumentException {
757 if (pool == null) {
758 throw new IllegalArgumentException("poll must not be null.");
759 }
760 this.pool = pool;
761 this.minIdle = minIdle;
762 }
763
764 public void run() {
765 boolean success = false;
766 try {
767 if (pool.getNumIdle() < minIdle) {
768 pool.addObject();
769 }
770 success = true;
771
772 } catch (Exception e) {
773 cancel();
774
775 } finally {
776
777 if (!success) {
778 cancel();
779 }
780 }
781 }
782
783 public String toString() {
784 final StringBuffer sb = new StringBuffer();
785 sb.append("ObjectPoolMinIdleTimerTask");
786 sb.append("{minIdle=").append(minIdle);
787 sb.append(", keyedPool=").append(pool);
788 sb.append('}');
789 return sb.toString();
790 }
791 }
792
793 private static class KeyedObjectPoolMinIdleTimerTask extends TimerTask {
794 private final int minIdle;
795 private final Object key;
796 private final KeyedObjectPool pool;
797
798 KeyedObjectPoolMinIdleTimerTask(final KeyedObjectPool pool, final Object key, final int minIdle) throws IllegalArgumentException {
799 if (pool == null) {
800 throw new IllegalArgumentException("keyedPool must not be null.");
801 }
802 this.pool = pool;
803 this.key = key;
804 this.minIdle = minIdle;
805 }
806
807 public void run() {
808 boolean success = false;
809 try {
810 if (pool.getNumIdle(key) < minIdle) {
811 pool.addObject(key);
812 }
813 success = true;
814
815 } catch (Exception e) {
816 cancel();
817
818 } finally {
819
820 if (!success) {
821 cancel();
822 }
823 }
824 }
825
826 public String toString() {
827 final StringBuffer sb = new StringBuffer();
828 sb.append("KeyedObjectPoolMinIdleTimerTask");
829 sb.append("{minIdle=").append(minIdle);
830 sb.append(", key=").append(key);
831 sb.append(", keyedPool=").append(pool);
832 sb.append('}');
833 return sb.toString();
834 }
835 }
836
837 private static class SynchronizedObjectPool implements ObjectPool {
838 private final Object lock;
839 private final ObjectPool pool;
840
841 SynchronizedObjectPool(final ObjectPool pool) throws IllegalArgumentException {
842 if (pool == null) {
843 throw new IllegalArgumentException("keyedPool must not be null.");
844 }
845 this.pool = pool;
846 lock = new Object();
847 }
848
849 public Object borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
850 synchronized (lock) {
851 return pool.borrowObject();
852 }
853 }
854
855 public void returnObject(final Object obj) throws Exception {
856 synchronized (lock) {
857 pool.returnObject(obj);
858 }
859 }
860
861 public void invalidateObject(final Object obj) throws Exception {
862 synchronized (lock) {
863 pool.invalidateObject(obj);
864 }
865 }
866
867 public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {
868 synchronized (lock) {
869 pool.addObject();
870 }
871 }
872
873 public int getNumIdle() throws UnsupportedOperationException {
874 synchronized (lock) {
875 return pool.getNumIdle();
876 }
877 }
878
879 public int getNumActive() throws UnsupportedOperationException {
880 synchronized (lock) {
881 return pool.getNumActive();
882 }
883 }
884
885 public void clear() throws Exception, UnsupportedOperationException {
886 synchronized (lock) {
887 pool.clear();
888 }
889 }
890
891 public void close() throws Exception {
892 synchronized (lock) {
893 pool.close();
894 }
895 }
896
897 public void setFactory(final PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
898 synchronized (lock) {
899 pool.setFactory(factory);
900 }
901 }
902
903 public String toString() {
904 final StringBuffer sb = new StringBuffer();
905 sb.append("SynchronizedObjectPool");
906 sb.append("{keyedPool=").append(pool);
907 sb.append('}');
908 return sb.toString();
909 }
910 }
911
912 private static class SynchronizedKeyedObjectPool implements KeyedObjectPool {
913 private final Object lock;
914 private final KeyedObjectPool keyedPool;
915
916 SynchronizedKeyedObjectPool(final KeyedObjectPool keyedPool) throws IllegalArgumentException {
917 if (keyedPool == null) {
918 throw new IllegalArgumentException("keyedPool must not be null.");
919 }
920 this.keyedPool = keyedPool;
921 lock = new Object();
922 }
923
924 public Object borrowObject(final Object key) throws Exception, NoSuchElementException, IllegalStateException {
925 synchronized (lock) {
926 return keyedPool.borrowObject(key);
927 }
928 }
929
930 public void returnObject(final Object key, final Object obj) throws Exception {
931 synchronized (lock) {
932 keyedPool.returnObject(key, obj);
933 }
934 }
935
936 public void invalidateObject(final Object key, final Object obj) throws Exception {
937 synchronized (lock) {
938 keyedPool.invalidateObject(key, obj);
939 }
940 }
941
942 public void addObject(final Object key) throws Exception, IllegalStateException, UnsupportedOperationException {
943 synchronized (lock) {
944 keyedPool.addObject(key);
945 }
946 }
947
948 public int getNumIdle(final Object key) throws UnsupportedOperationException {
949 synchronized (lock) {
950 return keyedPool.getNumIdle(key);
951 }
952 }
953
954 public int getNumActive(final Object key) throws UnsupportedOperationException {
955 synchronized (lock) {
956 return keyedPool.getNumActive(key);
957 }
958 }
959
960 public int getNumIdle() throws UnsupportedOperationException {
961 synchronized (lock) {
962 return keyedPool.getNumIdle();
963 }
964 }
965
966 public int getNumActive() throws UnsupportedOperationException {
967 synchronized (lock) {
968 return keyedPool.getNumActive();
969 }
970 }
971
972 public void clear() throws Exception, UnsupportedOperationException {
973 synchronized (lock) {
974 keyedPool.clear();
975 }
976 }
977
978 public void clear(final Object key) throws Exception, UnsupportedOperationException {
979 synchronized (lock) {
980 keyedPool.clear(key);
981 }
982 }
983
984 public void close() throws Exception {
985 synchronized (lock) {
986 keyedPool.close();
987 }
988 }
989
990 public void setFactory(final KeyedPoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException {
991 synchronized (lock) {
992 keyedPool.setFactory(factory);
993 }
994 }
995
996 public String toString() {
997 final StringBuffer sb = new StringBuffer();
998 sb.append("SynchronizedKeyedObjectPool");
999 sb.append("{keyedPool=").append(keyedPool);
1000 sb.append('}');
1001 return sb.toString();
1002 }
1003 }
1004
1005 private static class SynchronizedPoolableObjectFactory implements PoolableObjectFactory {
1006 private final Object lock;
1007 private final PoolableObjectFactory factory;
1008
1009 SynchronizedPoolableObjectFactory(final PoolableObjectFactory factory) throws IllegalArgumentException {
1010 if (factory == null) {
1011 throw new IllegalArgumentException("factory must not be null.");
1012 }
1013 this.factory = factory;
1014 lock = new Object();
1015 }
1016
1017 public Object makeObject() throws Exception {
1018 synchronized (lock) {
1019 return factory.makeObject();
1020 }
1021 }
1022
1023 public void destroyObject(final Object obj) throws Exception {
1024 synchronized (lock) {
1025 factory.destroyObject(obj);
1026 }
1027 }
1028
1029 public boolean validateObject(final Object obj) {
1030 synchronized (lock) {
1031 return factory.validateObject(obj);
1032 }
1033 }
1034
1035 public void activateObject(final Object obj) throws Exception {
1036 synchronized (lock) {
1037 factory.activateObject(obj);
1038 }
1039 }
1040
1041 public void passivateObject(final Object obj) throws Exception {
1042 synchronized (lock) {
1043 factory.passivateObject(obj);
1044 }
1045 }
1046
1047 public String toString() {
1048 final StringBuffer sb = new StringBuffer();
1049 sb.append("SynchronizedPoolableObjectFactory");
1050 sb.append("{factory=").append(factory);
1051 sb.append('}');
1052 return sb.toString();
1053 }
1054 }
1055
1056 private static class SynchronizedKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory {
1057 private final Object lock;
1058 private final KeyedPoolableObjectFactory keyedFactory;
1059
1060 SynchronizedKeyedPoolableObjectFactory(final KeyedPoolableObjectFactory keyedFactory) throws IllegalArgumentException {
1061 if (keyedFactory == null) {
1062 throw new IllegalArgumentException("keyedFactory must not be null.");
1063 }
1064 this.keyedFactory = keyedFactory;
1065 lock = new Object();
1066 }
1067
1068 public Object makeObject(final Object key) throws Exception {
1069 synchronized (lock) {
1070 return keyedFactory.makeObject(key);
1071 }
1072 }
1073
1074 public void destroyObject(final Object key, final Object obj) throws Exception {
1075 synchronized (lock) {
1076 keyedFactory.destroyObject(key, obj);
1077 }
1078 }
1079
1080 public boolean validateObject(final Object key, final Object obj) {
1081 synchronized (lock) {
1082 return keyedFactory.validateObject(key, obj);
1083 }
1084 }
1085
1086 public void activateObject(final Object key, final Object obj) throws Exception {
1087 synchronized (lock) {
1088 keyedFactory.activateObject(key, obj);
1089 }
1090 }
1091
1092 public void passivateObject(final Object key, final Object obj) throws Exception {
1093 synchronized (lock) {
1094 keyedFactory.passivateObject(key, obj);
1095 }
1096 }
1097
1098 public String toString() {
1099 final StringBuffer sb = new StringBuffer();
1100 sb.append("SynchronizedKeyedPoolableObjectFactory");
1101 sb.append("{keyedFactory=").append(keyedFactory);
1102 sb.append('}');
1103 return sb.toString();
1104 }
1105 }
1106 }