KickJava   Java API By Example, From Geeks To Geeks.

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


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.HashMap JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.NoSuchElementException JavaDoc;
22 import java.util.Stack JavaDoc;
23
24 import org.apache.commons.pool.BaseKeyedObjectPool;
25 import org.apache.commons.pool.KeyedObjectPool;
26 import org.apache.commons.pool.KeyedPoolableObjectFactory;
27
28 /**
29  * A simple, {@link java.util.Stack Stack}-based {@link KeyedObjectPool} implementation.
30  * <p>
31  * Given a {@link KeyedPoolableObjectFactory}, this class will maintain
32  * a simple pool of instances. A finite number of "sleeping"
33  * or inactive instances is enforced, but when the pool is
34  * empty, new instances are created to support the new load.
35  * Hence this class places no limit on the number of "active"
36  * instances created by the pool, but is quite useful for
37  * re-using <tt>Object</tt>s without introducing
38  * artificial limits.
39  *
40  * @author Rodney Waldhoff
41  * @version $Revision$ $Date: 2005-02-26 05:13:28 -0800 (Sat, 26 Feb 2005) $
42  */

43 public class StackKeyedObjectPool extends BaseKeyedObjectPool implements KeyedObjectPool {
44     /**
45      * Create a new pool using
46      * no factory. Clients must first populate the pool
47      * using {@link #returnObject(java.lang.Object,java.lang.Object)}
48      * before they can be {@link #borrowObject(java.lang.Object) borrowed}.
49      */

50     public StackKeyedObjectPool() {
51         this((KeyedPoolableObjectFactory)null,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY);
52     }
53
54     /**
55      * Create a new pool using
56      * no factory. Clients must first populate the pool
57      * using {@link #returnObject(java.lang.Object,java.lang.Object)}
58      * before they can be {@link #borrowObject(java.lang.Object) borrowed}.
59      *
60      * @param max cap on the number of "sleeping" instances in the pool
61      */

62     public StackKeyedObjectPool(int max) {
63         this((KeyedPoolableObjectFactory)null,max,DEFAULT_INIT_SLEEPING_CAPACITY);
64     }
65
66     /**
67      * Create a new pool using
68      * no factory. Clients must first populate the pool
69      * using {@link #returnObject(java.lang.Object,java.lang.Object)}
70      * before they can be {@link #borrowObject(java.lang.Object) borrowed}.
71      *
72      * @param max cap on the number of "sleeping" instances in the pool
73      * @param init initial size of the pool (this specifies the size of the container,
74      * it does not cause the pool to be pre-populated.)
75      */

76     public StackKeyedObjectPool(int max, int init) {
77         this((KeyedPoolableObjectFactory)null,max,init);
78     }
79
80     /**
81      * Create a new <tt>SimpleKeyedObjectPool</tt> using
82      * the specified <i>factory</i> to create new instances.
83      *
84      * @param factory the {@link KeyedPoolableObjectFactory} used to populate the pool
85      */

86     public StackKeyedObjectPool(KeyedPoolableObjectFactory factory) {
87         this(factory,DEFAULT_MAX_SLEEPING);
88     }
89
90     /**
91      * Create a new <tt>SimpleKeyedObjectPool</tt> using
92      * the specified <i>factory</i> to create new instances.
93      * capping the number of "sleeping" instances to <i>max</i>
94      *
95      * @param factory the {@link KeyedPoolableObjectFactory} used to populate the pool
96      * @param max cap on the number of "sleeping" instances in the pool
97      */

98     public StackKeyedObjectPool(KeyedPoolableObjectFactory factory, int max) {
99         this(factory,max,DEFAULT_INIT_SLEEPING_CAPACITY);
100     }
101
102     /**
103      * Create a new <tt>SimpleKeyedObjectPool</tt> using
104      * the specified <i>factory</i> to create new instances.
105      * capping the number of "sleeping" instances to <i>max</i>,
106      * and initially allocating a container capable of containing
107      * at least <i>init</i> instances.
108      *
109      * @param factory the {@link KeyedPoolableObjectFactory} used to populate the pool
110      * @param max cap on the number of "sleeping" instances in the pool
111      * @param init initial size of the pool (this specifies the size of the container,
112      * it does not cause the pool to be pre-populated.)
113      */

114     public StackKeyedObjectPool(KeyedPoolableObjectFactory factory, int max, int init) {
115         _factory = factory;
116         _maxSleeping = (max < 0 ? DEFAULT_MAX_SLEEPING : max);
117         _initSleepingCapacity = (init < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : init);
118         _pools = new HashMap JavaDoc();
119         _activeCount = new HashMap JavaDoc();
120     }
121
122     public synchronized Object JavaDoc borrowObject(Object JavaDoc key) throws Exception JavaDoc {
123         Object JavaDoc obj = null;
124         Stack JavaDoc stack = (Stack JavaDoc)(_pools.get(key));
125         if(null == stack) {
126             stack = new Stack JavaDoc();
127             stack.ensureCapacity( _initSleepingCapacity > _maxSleeping ? _maxSleeping : _initSleepingCapacity);
128             _pools.put(key,stack);
129         }
130         try {
131             obj = stack.pop();
132             _totIdle--;
133         } catch(Exception JavaDoc e) {
134             if(null == _factory) {
135                 throw new NoSuchElementException JavaDoc();
136             } else {
137                 obj = _factory.makeObject(key);
138             }
139         }
140         if(null != obj && null != _factory) {
141             _factory.activateObject(key,obj);
142         }
143         incrementActiveCount(key);
144         return obj;
145     }
146
147     public synchronized void returnObject(Object JavaDoc key, Object JavaDoc obj) throws Exception JavaDoc {
148         decrementActiveCount(key);
149         if(null == _factory || _factory.validateObject(key,obj)) {
150             Stack JavaDoc stack = (Stack JavaDoc)(_pools.get(key));
151             if(null == stack) {
152                 stack = new Stack JavaDoc();
153                 stack.ensureCapacity( _initSleepingCapacity > _maxSleeping ? _maxSleeping : _initSleepingCapacity);
154                 _pools.put(key,stack);
155             }
156             if(null != _factory) {
157                 try {
158                     _factory.passivateObject(key,obj);
159                 } catch(Exception JavaDoc e) {
160                     _factory.destroyObject(key,obj);
161                     return;
162                 }
163             }
164             if(stack.size() < _maxSleeping) {
165                 stack.push(obj);
166                 _totIdle++;
167             } else {
168                 if(null != _factory) {
169                     _factory.destroyObject(key,obj);
170                 }
171             }
172         } else {
173             if(null != _factory) {
174                 _factory.destroyObject(key,obj);
175             }
176         }
177     }
178
179     public synchronized void invalidateObject(Object JavaDoc key, Object JavaDoc obj) throws Exception JavaDoc {
180         decrementActiveCount(key);
181         if(null != _factory) {
182             _factory.destroyObject(key,obj);
183         }
184         notifyAll(); // _totalActive has changed
185
}
186
187     public void addObject(Object JavaDoc key) throws Exception JavaDoc {
188         Object JavaDoc obj = _factory.makeObject(key);
189         synchronized(this) {
190             incrementActiveCount(key); // returnObject will decrement this
191
returnObject(key,obj);
192         }
193     }
194
195     public int getNumIdle() {
196         return _totIdle;
197     }
198
199     public int getNumActive() {
200         return _totActive;
201     }
202
203     public int getNumActive(Object JavaDoc key) {
204         return getActiveCount(key);
205     }
206
207     public synchronized int getNumIdle(Object JavaDoc key) {
208         try {
209             return((Stack JavaDoc)(_pools.get(key))).size();
210         } catch(Exception JavaDoc e) {
211             return 0;
212         }
213     }
214
215     public synchronized void clear() {
216         Iterator JavaDoc it = _pools.keySet().iterator();
217         while(it.hasNext()) {
218             Object JavaDoc key = it.next();
219             Stack JavaDoc stack = (Stack JavaDoc)(_pools.get(key));
220             destroyStack(key,stack);
221         }
222         _totIdle = 0;
223         _pools.clear();
224         _activeCount.clear();
225     }
226
227     public synchronized void clear(Object JavaDoc key) {
228         Stack JavaDoc stack = (Stack JavaDoc)(_pools.remove(key));
229         destroyStack(key,stack);
230     }
231
232     private synchronized void destroyStack(Object JavaDoc key, Stack JavaDoc stack) {
233         if(null == stack) {
234             return;
235         } else {
236             if(null != _factory) {
237                 Iterator JavaDoc it = stack.iterator();
238                 while(it.hasNext()) {
239                     try {
240                         _factory.destroyObject(key,it.next());
241                     } catch(Exception JavaDoc e) {
242                         // ignore error, keep destroying the rest
243
}
244                 }
245             }
246             _totIdle -= stack.size();
247             _activeCount.remove(key);
248             stack.clear();
249         }
250     }
251
252     public synchronized String JavaDoc toString() {
253         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
254         buf.append(getClass().getName());
255         buf.append(" contains ").append(_pools.size()).append(" distinct pools: ");
256         Iterator JavaDoc it = _pools.keySet().iterator();
257         while(it.hasNext()) {
258             Object JavaDoc key = it.next();
259             buf.append(" |").append(key).append("|=");
260             Stack JavaDoc s = (Stack JavaDoc)(_pools.get(key));
261             buf.append(s.size());
262         }
263         return buf.toString();
264     }
265
266     public synchronized void close() throws Exception JavaDoc {
267         clear();
268         _pools = null;
269         _factory = null;
270         _activeCount = null;
271     }
272
273     public synchronized void setFactory(KeyedPoolableObjectFactory factory) throws IllegalStateException JavaDoc {
274         if(0 < getNumActive()) {
275             throw new IllegalStateException JavaDoc("Objects are already active");
276         } else {
277             clear();
278             _factory = factory;
279         }
280     }
281
282     private int getActiveCount(Object JavaDoc key) {
283         try {
284             return ((Integer JavaDoc)_activeCount.get(key)).intValue();
285         } catch(NoSuchElementException JavaDoc e) {
286             return 0;
287         } catch(NullPointerException JavaDoc e) {
288             return 0;
289         }
290     }
291
292     private void incrementActiveCount(Object JavaDoc key) {
293         _totActive++;
294         Integer JavaDoc old = (Integer JavaDoc)(_activeCount.get(key));
295         if(null == old) {
296             _activeCount.put(key,new Integer JavaDoc(1));
297         } else {
298             _activeCount.put(key,new Integer JavaDoc(old.intValue() + 1));
299         }
300     }
301
302     private void decrementActiveCount(Object JavaDoc key) {
303         _totActive--;
304         Integer JavaDoc active = (Integer JavaDoc)(_activeCount.get(key));
305         if(null == active) {
306             // do nothing, either null or zero is OK
307
} else if(active.intValue() <= 1) {
308             _activeCount.remove(key);
309         } else {
310             _activeCount.put(key, new Integer JavaDoc(active.intValue() - 1));
311         }
312     }
313
314     /** The default cap on the number of "sleeping" instances in the pool. */
315     protected static final int DEFAULT_MAX_SLEEPING = 8;
316
317     /**
318      * The default initial size of the pool
319      * (this specifies the size of the container, it does not
320      * cause the pool to be pre-populated.)
321      */

322     protected static final int DEFAULT_INIT_SLEEPING_CAPACITY = 4;
323
324     /** My named-set of pools. */
325     protected HashMap JavaDoc _pools = null;
326
327     /** My {@link KeyedPoolableObjectFactory}. */
328     protected KeyedPoolableObjectFactory _factory = null;
329
330     /** The cap on the number of "sleeping" instances in <i>each</i> pool. */
331     protected int _maxSleeping = DEFAULT_MAX_SLEEPING;
332
333     /** The initial capacity of each pool. */
334     protected int _initSleepingCapacity = DEFAULT_INIT_SLEEPING_CAPACITY;
335
336     /** Total number of object borrowed and not yet retuened for all pools */
337     protected int _totActive = 0;
338
339     /** Total number of objects "sleeping" for all pools */
340     protected int _totIdle = 0;
341
342     /** Number of active objects borrowed and not yet returned by pool */
343     protected HashMap JavaDoc _activeCount = null;
344
345 }
346
Popular Tags