1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.pool.impl; 19 20 import java.util.Iterator; 21 import java.util.NoSuchElementException; 22 import java.util.Stack; 23 24 import org.apache.commons.pool.BaseObjectPool; 25 import org.apache.commons.pool.ObjectPool; 26 import org.apache.commons.pool.PoolUtils; 27 import org.apache.commons.pool.PoolableObjectFactory; 28 29 /** 30 * A simple, {@link java.util.Stack Stack}-based {@link ObjectPool} implementation. 31 * <p> 32 * Given a {@link PoolableObjectFactory}, this class will maintain 33 * a simple pool of instances. A finite number of "sleeping" 34 * or idle instances is enforced, but when the pool is 35 * empty, new instances are created to support the new load. 36 * Hence this class places no limit on the number of "active" 37 * instances created by the pool, but is quite useful for 38 * re-using <tt>Object</tt>s without introducing 39 * artificial limits. 40 * 41 * @author Rodney Waldhoff 42 * @author Dirk Verbeeck 43 * @author Sandy McArthur 44 * @version $Revision: 965338 $ $Date: 2010-07-18 18:09:29 -0700 (Sun, 18 Jul 2010) $ 45 * @since Pool 1.0 46 */ 47 public class StackObjectPool extends BaseObjectPool implements ObjectPool { 48 /** 49 * Create a new pool using no factory. Clients must first 50 * {@link #setFactory(PoolableObjectFactory) set the factory} or 51 * else this pool will not behave correctly. Clients may first populate the pool 52 * using {@link #returnObject(java.lang.Object)} before they can be {@link #borrowObject borrowed} 53 * but this usage is <strong>discouraged</strong>. 54 * 55 * @see #StackObjectPool(PoolableObjectFactory) 56 * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPool(PoolableObjectFactory)} 57 */ 58 public StackObjectPool() { 59 this((PoolableObjectFactory)null,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY); 60 } 61 62 /** 63 * Create a new pool using no factory. 64 * Clients must first {@link #setFactory(PoolableObjectFactory) set the factory} or 65 * else this pool will not behave correctly. Clients may first populate the pool 66 * using {@link #returnObject(java.lang.Object)} before they can be {@link #borrowObject borrowed} 67 * but this usage is <strong>discouraged</strong>. 68 * 69 * @param maxIdle cap on the number of "sleeping" instances in the pool 70 * @see #StackObjectPool(PoolableObjectFactory, int) 71 * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPool(PoolableObjectFactory, int)} 72 */ 73 public StackObjectPool(int maxIdle) { 74 this((PoolableObjectFactory)null,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY); 75 } 76 77 /** 78 * Create a new pool using no factory. 79 * Clients must first {@link #setFactory(PoolableObjectFactory) set the factory} or 80 * else this pool will not behave correctly. Clients may first populate the pool 81 * using {@link #returnObject(java.lang.Object)} before they can be {@link #borrowObject borrowed} 82 * but this usage is <strong>discouraged</strong>. 83 * 84 * @param maxIdle cap on the number of "sleeping" instances in the pool 85 * @param initIdleCapacity initial size of the pool (this specifies the size of the container, 86 * it does not cause the pool to be pre-populated.) 87 * @see #StackObjectPool(PoolableObjectFactory, int, int) 88 * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPool(PoolableObjectFactory, int, int)} 89 */ 90 public StackObjectPool(int maxIdle, int initIdleCapacity) { 91 this((PoolableObjectFactory)null,maxIdle,initIdleCapacity); 92 } 93 94 /** 95 * Create a new <tt>StackObjectPool</tt> using the specified <i>factory</i> to create new instances. 96 * 97 * @param factory the {@link PoolableObjectFactory} used to populate the pool 98 */ 99 public StackObjectPool(PoolableObjectFactory factory) { 100 this(factory,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY); 101 } 102 103 /** 104 * Create a new <tt>SimpleObjectPool</tt> using the specified <i>factory</i> to create new instances, 105 * capping the number of "sleeping" instances to <i>maxIdle</i>. 106 * 107 * @param factory the {@link PoolableObjectFactory} used to populate the pool 108 * @param maxIdle cap on the number of "sleeping" instances in the pool 109 */ 110 public StackObjectPool(PoolableObjectFactory factory, int maxIdle) { 111 this(factory,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY); 112 } 113 114 /** 115 * <p>Create a new <tt>StackObjectPool</tt> using the specified <code>factory</code> to create new instances, 116 * capping the number of "sleeping" instances to <code>maxIdle</code>, and initially allocating a container 117 * capable of containing at least <code>initIdleCapacity</code> instances. The pool is not pre-populated. 118 * The <code>initIdleCapacity</code> parameter just determines the initial size of the underlying 119 * container, which can increase beyond this value if <code>maxIdle > initIdleCapacity.</code></p> 120 * 121 * <p>Negative values of <code>maxIdle</code> are ignored (i.e., the pool is created using 122 * {@link #DEFAULT_MAX_SLEEPING}) as are non-positive values for <code>initIdleCapacity.</code> 123 * 124 * @param factory the {@link PoolableObjectFactory} used to populate the pool 125 * @param maxIdle cap on the number of "sleeping" instances in the pool 126 * @param initIdleCapacity initial size of the pool (this specifies the size of the container, 127 * it does not cause the pool to be pre-populated.) 128 */ 129 public StackObjectPool(PoolableObjectFactory factory, int maxIdle, int initIdleCapacity) { 130 _factory = factory; 131 _maxSleeping = (maxIdle < 0 ? DEFAULT_MAX_SLEEPING : maxIdle); 132 int initcapacity = (initIdleCapacity < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : initIdleCapacity); 133 _pool = new Stack(); 134 _pool.ensureCapacity( initcapacity > _maxSleeping ? _maxSleeping : initcapacity); 135 } 136 137 /** 138 * <p>Borrows an object from the pool. If there are idle instances available on the stack, 139 * the top element of the stack is popped to activate, validate and return to the client. If there 140 * are no idle instances available, the {@link PoolableObjectFactory#makeObject() makeObject} 141 * method of the pool's {@link PoolableObjectFactory} is invoked to create a new instance.</p> 142 * 143 * <p>All instances are {@link PoolableObjectFactory#activateObject(Object) activated} and 144 * {@link PoolableObjectFactory#validateObject(Object) validated} before being returned to the 145 * client. If validation fails or an exception occurs activating or validating an instance 146 * popped from the idle instance stack, the failing instance is 147 * {@link PoolableObjectFactory#destroyObject(Object) destroyed} and the next instance on 148 * the stack is popped, validated and activated. This process continues until either the 149 * stack is empty or an instance passes validation. If the stack is empty on activation or 150 * it does not contain any valid instances, the factory's <code>makeObject</code> method is used 151 * to create a new instance. If a null instance is returned by the factory or the created 152 * instance either raises an exception on activation or fails validation, <code>NoSuchElementException</code> 153 * is thrown. Exceptions thrown by <code>MakeObject</code> are propagated to the caller; but 154 * other than <code>ThreadDeath</code> or <code>VirtualMachineError</code>, exceptions generated by 155 * activation, validation or destroy methods are swallowed silently.</p> 156 * 157 * @return an instance from the pool 158 */ 159 public synchronized Object borrowObject() throws Exception { 160 assertOpen(); 161 Object obj = null; 162 boolean newlyCreated = false; 163 while (null == obj) { 164 if (!_pool.empty()) { 165 obj = _pool.pop(); 166 } else { 167 if(null == _factory) { 168 throw new NoSuchElementException(); 169 } else { 170 obj = _factory.makeObject(); 171 newlyCreated = true; 172 if (obj == null) { 173 throw new NoSuchElementException("PoolableObjectFactory.makeObject() returned null."); 174 } 175 } 176 } 177 if (null != _factory && null != obj) { 178 try { 179 _factory.activateObject(obj); 180 if (!_factory.validateObject(obj)) { 181 throw new Exception("ValidateObject failed"); 182 } 183 } catch (Throwable t) { 184 PoolUtils.checkRethrow(t); 185 try { 186 _factory.destroyObject(obj); 187 } catch (Throwable t2) { 188 PoolUtils.checkRethrow(t2); 189 // swallowed 190 } finally { 191 obj = null; 192 } 193 if (newlyCreated) { 194 throw new NoSuchElementException( 195 "Could not create a validated object, cause: " + 196 t.getMessage()); 197 } 198 } 199 } 200 } 201 _numActive++; 202 return obj; 203 } 204 205 /** 206 * <p>Returns an instance to the pool, pushing it on top of the idle instance stack after successful 207 * validation and passivation. The returning instance is destroyed if any of the following are true:<ul> 208 * <li>the pool is closed</li> 209 * <li>{@link PoolableObjectFactory#validateObject(Object) validation} fails</li> 210 * <li>{@link PoolableObjectFactory#passivateObject(Object) passivation} throws an exception</li> 211 * </ul> 212 * If adding a validated, passivated returning instance to the stack would cause 213 * {@link #getMaxSleeping() maxSleeping} to be exceeded, the oldest (bottom) instance on the stack 214 * is destroyed to make room for the returning instance, which is pushed on top of the stack.</p> 215 * 216 * <p>Exceptions passivating or destroying instances are silently swallowed. Exceptions validating 217 * instances are propagated to the client.</p> 218 * 219 * @param obj instance to return to the pool 220 */ 221 public synchronized void returnObject(Object obj) throws Exception { 222 boolean success = !isClosed(); 223 if(null != _factory) { 224 if(!_factory.validateObject(obj)) { 225 success = false; 226 } else { 227 try { 228 _factory.passivateObject(obj); 229 } catch(Exception e) { 230 success = false; 231 } 232 } 233 } 234 235 boolean shouldDestroy = !success; 236 237 _numActive--; 238 if (success) { 239 Object toBeDestroyed = null; 240 if(_pool.size() >= _maxSleeping) { 241 shouldDestroy = true; 242 toBeDestroyed = _pool.remove(0); // remove the stalest object 243 } 244 _pool.push(obj); 245 obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed 246 } 247 notifyAll(); // _numActive has changed 248 249 if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null 250 try { 251 _factory.destroyObject(obj); 252 } catch(Exception e) { 253 // ignored 254 } 255 } 256 } 257 258 /** 259 * {@inheritDoc} 260 */ 261 public synchronized void invalidateObject(Object obj) throws Exception { 262 _numActive--; 263 if (null != _factory) { 264 _factory.destroyObject(obj); 265 } 266 notifyAll(); // _numActive has changed 267 } 268 269 /** 270 * Return the number of instances 271 * currently idle in this pool. 272 * 273 * @return the number of instances currently idle in this pool 274 */ 275 public synchronized int getNumIdle() { 276 return _pool.size(); 277 } 278 279 /** 280 * Return the number of instances currently borrowed from this pool. 281 * 282 * @return the number of instances currently borrowed from this pool 283 */ 284 public synchronized int getNumActive() { 285 return _numActive; 286 } 287 288 /** 289 * Clears any objects sitting idle in the pool. Silently swallows any 290 * exceptions thrown by {@link PoolableObjectFactory#destroyObject(Object)}. 291 */ 292 public synchronized void clear() { 293 if(null != _factory) { 294 Iterator it = _pool.iterator(); 295 while(it.hasNext()) { 296 try { 297 _factory.destroyObject(it.next()); 298 } catch(Exception e) { 299 // ignore error, keep destroying the rest 300 } 301 } 302 } 303 _pool.clear(); 304 } 305 306 /** 307 * <p>Close this pool, and free any resources associated with it. Invokes 308 * {@link #clear()} to destroy and remove instances in the pool.</p> 309 * 310 * <p>Calling {@link #addObject} or {@link #borrowObject} after invoking 311 * this method on a pool will cause them to throw an 312 * {@link IllegalStateException}.</p> 313 * 314 * @throws Exception never - exceptions clearing the pool are swallowed 315 */ 316 public void close() throws Exception { 317 super.close(); 318 clear(); 319 } 320 321 /** 322 * <p>Create an object, and place it on top of the stack. 323 * This method is useful for "pre-loading" a pool with idle objects.</p> 324 * 325 * <p>Before being added to the pool, the newly created instance is 326 * {@link PoolableObjectFactory#validateObject(Object) validated} and 327 * {@link PoolableObjectFactory#passivateObject(Object) passivated}. If validation 328 * fails, the new instance is {@link PoolableObjectFactory#destroyObject(Object) destroyed}. 329 * Exceptions generated by the factory <code>makeObject</code> or <code>passivate</code> are 330 * propagated to the caller. Exceptions destroying instances are silently swallowed.</p> 331 * 332 * <p>If a new instance is created and successfully validated and passivated and adding this 333 * instance to the pool causes {@link #getMaxSleeping() maxSleeping} to be exceeded, the oldest 334 * (bottom) instance in the pool is destroyed to make room for the newly created instance, which 335 * is pushed on top of the stack. 336 * 337 * @throws Exception when the {@link #getFactory() factory} has a problem creating or passivating an object. 338 */ 339 public synchronized void addObject() throws Exception { 340 assertOpen(); 341 if (_factory == null) { 342 throw new IllegalStateException("Cannot add objects without a factory."); 343 } 344 Object obj = _factory.makeObject(); 345 346 boolean success = true; 347 if(!_factory.validateObject(obj)) { 348 success = false; 349 } else { 350 _factory.passivateObject(obj); 351 } 352 353 boolean shouldDestroy = !success; 354 355 if (success) { 356 Object toBeDestroyed = null; 357 if(_pool.size() >= _maxSleeping) { 358 shouldDestroy = true; 359 toBeDestroyed = _pool.remove(0); // remove the stalest object 360 } 361 _pool.push(obj); 362 obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed 363 } 364 notifyAll(); // _numIdle has changed 365 366 if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null 367 try { 368 _factory.destroyObject(obj); 369 } catch(Exception e) { 370 // ignored 371 } 372 } 373 } 374 375 /** 376 * Sets the {@link PoolableObjectFactory factory} this pool uses 377 * to create new instances. Trying to change 378 * the <code>factory</code> while there are borrowed objects will 379 * throw an {@link IllegalStateException}. 380 * 381 * @param factory the {@link PoolableObjectFactory} used to create new instances. 382 * @throws IllegalStateException when the factory cannot be set at this time 383 * @deprecated to be removed in pool 2.0 384 */ 385 public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException { 386 assertOpen(); 387 if(0 < getNumActive()) { 388 throw new IllegalStateException("Objects are already active"); 389 } else { 390 clear(); 391 _factory = factory; 392 } 393 } 394 395 /** 396 * The cap on the number of "sleeping" instances in the pool. 397 */ 398 protected static final int DEFAULT_MAX_SLEEPING = 8; 399 400 /** 401 * The default initial size of the pool 402 * (this specifies the size of the container, it does not 403 * cause the pool to be pre-populated.) 404 */ 405 protected static final int DEFAULT_INIT_SLEEPING_CAPACITY = 4; 406 407 /** 408 * My pool. 409 * @deprecated to be made private in pool 2.0 410 */ 411 protected Stack _pool = null; 412 413 /** 414 * My {@link PoolableObjectFactory}. 415 * @deprecated to be made private in pool 2.0 - use {@link #getFactory()} 416 */ 417 protected PoolableObjectFactory _factory = null; 418 419 /** 420 * The cap on the number of "sleeping" instances in the pool. 421 * @deprecated to be made private in pool 2.0 - use {@link #getMaxSleeping()} 422 */ 423 protected int _maxSleeping = DEFAULT_MAX_SLEEPING; 424 425 /** 426 * Number of objects borrowed but not yet returned to the pool. 427 * @deprecated to be made private in pool 2.0 - use {@link #getNumActive()} 428 */ 429 protected int _numActive = 0; 430 431 /** 432 * Returns the {@link PoolableObjectFactory} used by this pool to create and manage object instances. 433 * 434 * @return the factory 435 * @since 1.5.5 436 */ 437 public synchronized PoolableObjectFactory getFactory() { 438 return _factory; 439 } 440 441 /** 442 * Returns the maximum number of idle instances in the pool. 443 * 444 * @return maxSleeping 445 * @since 1.5.5 446 */ 447 public int getMaxSleeping() { 448 return _maxSleeping; 449 } 450 451 452 }