1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.pool.impl;
18
19 import java.util.Iterator;
20 import java.util.NoSuchElementException;
21 import java.util.Stack;
22
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 simple, {@link java.util.Stack Stack}-based {@link ObjectPool} implementation.
29 * <p>
30 * Given a {@link PoolableObjectFactory}, this class will maintain
31 * a simple pool of instances. A finite number of "sleeping"
32 * or idle instances is enforced, but when the pool is
33 * empty, new instances are created to support the new load.
34 * Hence this class places no limit on the number of "active"
35 * instances created by the pool, but is quite useful for
36 * re-using <tt>Object</tt>s without introducing
37 * artificial limits.
38 *
39 * @author Rodney Waldhoff
40 * @author Dirk Verbeeck
41 * @version $Revision: 383290 $ $Date: 2006-03-05 02:00:15 -0500 (Sun, 05 Mar 2006) $
42 */
43 public class StackObjectPool extends BaseObjectPool implements ObjectPool {
44 /***
45 * Create a new pool using
46 * no factory. Clients must first populate the pool
47 * using {@link #returnObject(java.lang.Object)}
48 * before they can be {@link #borrowObject borrowed}.
49 */
50 public StackObjectPool() {
51 this((PoolableObjectFactory)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)}
58 * before they can be {@link #borrowObject borrowed}.
59 *
60 * @param maxIdle cap on the number of "sleeping" instances in the pool
61 */
62 public StackObjectPool(int maxIdle) {
63 this((PoolableObjectFactory)null,maxIdle,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)}
70 * before they can be {@link #borrowObject borrowed}.
71 *
72 * @param maxIdle cap on the number of "sleeping" instances in the pool
73 * @param initIdleCapacity 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 StackObjectPool(int maxIdle, int initIdleCapacity) {
77 this((PoolableObjectFactory)null,maxIdle,initIdleCapacity);
78 }
79
80 /***
81 * Create a new <tt>StackObjectPool</tt> using
82 * the specified <i>factory</i> to create new instances.
83 *
84 * @param factory the {@link PoolableObjectFactory} used to populate the pool
85 */
86 public StackObjectPool(PoolableObjectFactory factory) {
87 this(factory,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY);
88 }
89
90 /***
91 * Create a new <tt>SimpleObjectPool</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 PoolableObjectFactory} used to populate the pool
96 * @param maxIdle cap on the number of "sleeping" instances in the pool
97 */
98 public StackObjectPool(PoolableObjectFactory factory, int maxIdle) {
99 this(factory,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY);
100 }
101
102 /***
103 * Create a new <tt>SimpleObjectPool</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 PoolableObjectFactory} used to populate the pool
110 * @param maxIdle cap on the number of "sleeping" instances in the pool
111 * @param initIdleCapacity 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 StackObjectPool(PoolableObjectFactory factory, int maxIdle, int initIdleCapacity) {
115 _factory = factory;
116 _maxSleeping = (maxIdle < 0 ? DEFAULT_MAX_SLEEPING : maxIdle);
117 int initcapacity = (initIdleCapacity < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : initIdleCapacity);
118 _pool = new Stack();
119 _pool.ensureCapacity( initcapacity > _maxSleeping ? _maxSleeping : initcapacity);
120 }
121
122 public synchronized Object borrowObject() throws Exception {
123 assertOpen();
124 Object obj = null;
125 while (null == obj) {
126 if (!_pool.empty()) {
127 obj = _pool.pop();
128 } else {
129 if(null == _factory) {
130 throw new NoSuchElementException();
131 } else {
132 obj = _factory.makeObject();
133 }
134 }
135 if(null != _factory && null != obj) {
136 _factory.activateObject(obj);
137 }
138 if (null != _factory && null != obj && !_factory.validateObject(obj)) {
139 _factory.destroyObject(obj);
140 obj = null;
141 }
142 }
143 _numActive++;
144 return obj;
145 }
146
147 public synchronized void returnObject(Object obj) throws Exception {
148 assertOpen();
149 boolean success = true;
150 if(null != _factory) {
151 if(!(_factory.validateObject(obj))) {
152 success = false;
153 } else {
154 try {
155 _factory.passivateObject(obj);
156 } catch(Exception e) {
157 success = false;
158 }
159 }
160 }
161
162 boolean shouldDestroy = !success;
163
164 _numActive--;
165 if (success) {
166 Object toBeDestroyed = null;
167 if(_pool.size() >= _maxSleeping) {
168 shouldDestroy = true;
169 toBeDestroyed = _pool.remove(0);
170 }
171 _pool.push(obj);
172 obj = toBeDestroyed;
173 }
174 notifyAll();
175
176 if(shouldDestroy) {
177 try {
178 _factory.destroyObject(obj);
179 } catch(Exception e) {
180
181 }
182 }
183 }
184
185 public synchronized void invalidateObject(Object obj) throws Exception {
186 assertOpen();
187 _numActive--;
188 if(null != _factory ) {
189 _factory.destroyObject(obj);
190 }
191 notifyAll();
192 }
193
194 public synchronized int getNumIdle() {
195 assertOpen();
196 return _pool.size();
197 }
198
199 public synchronized int getNumActive() {
200 assertOpen();
201 return _numActive;
202 }
203
204 public synchronized void clear() {
205 assertOpen();
206 if(null != _factory) {
207 Iterator it = _pool.iterator();
208 while(it.hasNext()) {
209 try {
210 _factory.destroyObject(it.next());
211 } catch(Exception e) {
212
213 }
214 }
215 }
216 _pool.clear();
217 }
218
219 public synchronized void close() throws Exception {
220 clear();
221 _pool = null;
222 _factory = null;
223 super.close();
224 }
225
226 /***
227 * Create an object, and place it into the pool.
228 * addObject() is useful for "pre-loading" a pool with idle objects.
229 * @throws Exception when the {@link #_factory} has a problem creating an object.
230 */
231 public synchronized void addObject() throws Exception {
232 assertOpen();
233 Object obj = _factory.makeObject();
234 _numActive++;
235 this.returnObject(obj);
236 }
237
238 public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException {
239 assertOpen();
240 if(0 < getNumActive()) {
241 throw new IllegalStateException("Objects are already active");
242 } else {
243 clear();
244 _factory = factory;
245 }
246 }
247
248 /*** The default cap on the number of "sleeping" instances in the pool. */
249 protected static final int DEFAULT_MAX_SLEEPING = 8;
250
251 /***
252 * The default initial size of the pool
253 * (this specifies the size of the container, it does not
254 * cause the pool to be pre-populated.)
255 */
256 protected static final int DEFAULT_INIT_SLEEPING_CAPACITY = 4;
257
258 /*** My pool. */
259 protected Stack _pool = null;
260
261 /*** My {@link PoolableObjectFactory}. */
262 protected PoolableObjectFactory _factory = null;
263
264 /*** The cap on the number of "sleeping" instances in the pool. */
265 protected int _maxSleeping = DEFAULT_MAX_SLEEPING;
266
267 /*** Number of object borrowed but not yet returned to the pool. */
268 protected int _numActive = 0;
269 }