001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.pool.impl; 019 020 import java.util.Iterator; 021 import java.util.NoSuchElementException; 022 import java.util.Stack; 023 024 import org.apache.commons.pool.BaseObjectPool; 025 import org.apache.commons.pool.ObjectPool; 026 import org.apache.commons.pool.PoolUtils; 027 import org.apache.commons.pool.PoolableObjectFactory; 028 029 /** 030 * A simple, {@link java.util.Stack Stack}-based {@link ObjectPool} implementation. 031 * <p> 032 * Given a {@link PoolableObjectFactory}, this class will maintain 033 * a simple pool of instances. A finite number of "sleeping" 034 * or idle instances is enforced, but when the pool is 035 * empty, new instances are created to support the new load. 036 * Hence this class places no limit on the number of "active" 037 * instances created by the pool, but is quite useful for 038 * re-using <tt>Object</tt>s without introducing 039 * artificial limits. 040 * 041 * @param <T> the type of objects held in this pool 042 * 043 * @author Rodney Waldhoff 044 * @author Dirk Verbeeck 045 * @author Sandy McArthur 046 * @version $Revision: 1222396 $ $Date: 2011-12-22 14:02:25 -0500 (Thu, 22 Dec 2011) $ 047 * @since Pool 1.0 048 */ 049 public class StackObjectPool<T> extends BaseObjectPool<T> implements ObjectPool<T> { 050 /** 051 * Create a new pool using no factory. Clients must first 052 * {@link #setFactory(PoolableObjectFactory) set the factory} or 053 * else this pool will not behave correctly. Clients may first populate the pool 054 * using {@link #returnObject(java.lang.Object)} before they can be {@link #borrowObject borrowed} 055 * but this usage is <strong>discouraged</strong>. 056 * 057 * @see #StackObjectPool(PoolableObjectFactory) 058 * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPool(PoolableObjectFactory)} 059 */ 060 @Deprecated 061 public StackObjectPool() { 062 this(null,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY); 063 } 064 065 /** 066 * Create a new pool using no factory. 067 * Clients must first {@link #setFactory(PoolableObjectFactory) set the factory} or 068 * else this pool will not behave correctly. Clients may first populate the pool 069 * using {@link #returnObject(java.lang.Object)} before they can be {@link #borrowObject borrowed} 070 * but this usage is <strong>discouraged</strong>. 071 * 072 * @param maxIdle cap on the number of "sleeping" instances in the pool 073 * @see #StackObjectPool(PoolableObjectFactory, int) 074 * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPool(PoolableObjectFactory, int)} 075 */ 076 @Deprecated 077 public StackObjectPool(int maxIdle) { 078 this(null,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY); 079 } 080 081 /** 082 * Create a new pool using no factory. 083 * Clients must first {@link #setFactory(PoolableObjectFactory) set the factory} or 084 * else this pool will not behave correctly. Clients may first populate the pool 085 * using {@link #returnObject(java.lang.Object)} before they can be {@link #borrowObject borrowed} 086 * but this usage is <strong>discouraged</strong>. 087 * 088 * @param maxIdle cap on the number of "sleeping" instances in the pool 089 * @param initIdleCapacity initial size of the pool (this specifies the size of the container, 090 * it does not cause the pool to be pre-populated.) 091 * @see #StackObjectPool(PoolableObjectFactory, int, int) 092 * @deprecated to be removed in pool 2.0 - use {@link #StackObjectPool(PoolableObjectFactory, int, int)} 093 */ 094 @Deprecated 095 public StackObjectPool(int maxIdle, int initIdleCapacity) { 096 this(null,maxIdle,initIdleCapacity); 097 } 098 099 /** 100 * Create a new <tt>StackObjectPool</tt> using the specified <i>factory</i> to create new instances. 101 * 102 * @param factory the {@link PoolableObjectFactory} used to populate the pool 103 */ 104 public StackObjectPool(PoolableObjectFactory<T> factory) { 105 this(factory,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY); 106 } 107 108 /** 109 * Create a new <tt>SimpleObjectPool</tt> using the specified <i>factory</i> to create new instances, 110 * capping the number of "sleeping" instances to <i>maxIdle</i>. 111 * 112 * @param factory the {@link PoolableObjectFactory} used to populate the pool 113 * @param maxIdle cap on the number of "sleeping" instances in the pool 114 */ 115 public StackObjectPool(PoolableObjectFactory<T> factory, int maxIdle) { 116 this(factory,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY); 117 } 118 119 /** 120 * <p>Create a new <tt>StackObjectPool</tt> using the specified <code>factory</code> to create new instances, 121 * capping the number of "sleeping" instances to <code>maxIdle</code>, and initially allocating a container 122 * capable of containing at least <code>initIdleCapacity</code> instances. The pool is not pre-populated. 123 * The <code>initIdleCapacity</code> parameter just determines the initial size of the underlying 124 * container, which can increase beyond this value if <code>maxIdle > initIdleCapacity.</code></p> 125 * 126 * <p>Negative values of <code>maxIdle</code> are ignored (i.e., the pool is created using 127 * {@link #DEFAULT_MAX_SLEEPING}) as are non-positive values for <code>initIdleCapacity.</code> 128 * 129 * @param factory the {@link PoolableObjectFactory} used to populate the pool 130 * @param maxIdle cap on the number of "sleeping" instances in the pool 131 * @param initIdleCapacity initial size of the pool (this specifies the size of the container, 132 * it does not cause the pool to be pre-populated.) 133 */ 134 public StackObjectPool(PoolableObjectFactory<T> factory, int maxIdle, int initIdleCapacity) { 135 _factory = factory; 136 _maxSleeping = (maxIdle < 0 ? DEFAULT_MAX_SLEEPING : maxIdle); 137 int initcapacity = (initIdleCapacity < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : initIdleCapacity); 138 _pool = new Stack<T>(); 139 _pool.ensureCapacity( initcapacity > _maxSleeping ? _maxSleeping : initcapacity); 140 } 141 142 /** 143 * <p>Borrows an object from the pool. If there are idle instances available on the stack, 144 * the top element of the stack is popped to activate, validate and return to the client. If there 145 * are no idle instances available, the {@link PoolableObjectFactory#makeObject() makeObject} 146 * method of the pool's {@link PoolableObjectFactory} is invoked to create a new instance.</p> 147 * 148 * <p>All instances are {@link PoolableObjectFactory#activateObject(Object) activated} and 149 * {@link PoolableObjectFactory#validateObject(Object) validated} before being returned to the 150 * client. If validation fails or an exception occurs activating or validating an instance 151 * popped from the idle instance stack, the failing instance is 152 * {@link PoolableObjectFactory#destroyObject(Object) destroyed} and the next instance on 153 * the stack is popped, validated and activated. This process continues until either the 154 * stack is empty or an instance passes validation. If the stack is empty on activation or 155 * it does not contain any valid instances, the factory's <code>makeObject</code> method is used 156 * to create a new instance. If a null instance is returned by the factory or the created 157 * instance either raises an exception on activation or fails validation, <code>NoSuchElementException</code> 158 * is thrown. Exceptions thrown by <code>MakeObject</code> are propagated to the caller; but 159 * other than <code>ThreadDeath</code> or <code>VirtualMachineError</code>, exceptions generated by 160 * activation, validation or destroy methods are swallowed silently.</p> 161 * 162 * @return an instance from the pool 163 */ 164 @Override 165 public synchronized T borrowObject() throws Exception { 166 assertOpen(); 167 T obj = null; 168 boolean newlyCreated = false; 169 while (null == obj) { 170 if (!_pool.empty()) { 171 obj = _pool.pop(); 172 } else { 173 if(null == _factory) { 174 throw new NoSuchElementException(); 175 } else { 176 obj = _factory.makeObject(); 177 newlyCreated = true; 178 if (obj == null) { 179 throw new NoSuchElementException("PoolableObjectFactory.makeObject() returned null."); 180 } 181 } 182 } 183 if (null != _factory && null != obj) { 184 try { 185 _factory.activateObject(obj); 186 if (!_factory.validateObject(obj)) { 187 throw new Exception("ValidateObject failed"); 188 } 189 } catch (Throwable t) { 190 PoolUtils.checkRethrow(t); 191 try { 192 _factory.destroyObject(obj); 193 } catch (Throwable t2) { 194 PoolUtils.checkRethrow(t2); 195 // swallowed 196 } finally { 197 obj = null; 198 } 199 if (newlyCreated) { 200 throw new NoSuchElementException( 201 "Could not create a validated object, cause: " + 202 t.getMessage()); 203 } 204 } 205 } 206 } 207 _numActive++; 208 return obj; 209 } 210 211 /** 212 * <p>Returns an instance to the pool, pushing it on top of the idle instance stack after successful 213 * validation and passivation. The returning instance is destroyed if any of the following are true:<ul> 214 * <li>the pool is closed</li> 215 * <li>{@link PoolableObjectFactory#validateObject(Object) validation} fails</li> 216 * <li>{@link PoolableObjectFactory#passivateObject(Object) passivation} throws an exception</li> 217 * </ul> 218 * If adding a validated, passivated returning instance to the stack would cause 219 * {@link #getMaxSleeping() maxSleeping} to be exceeded, the oldest (bottom) instance on the stack 220 * is destroyed to make room for the returning instance, which is pushed on top of the stack.</p> 221 * 222 * <p>Exceptions passivating or destroying instances are silently swallowed. Exceptions validating 223 * instances are propagated to the client.</p> 224 * 225 * @param obj instance to return to the pool 226 */ 227 @Override 228 public synchronized void returnObject(T obj) throws Exception { 229 boolean success = !isClosed(); 230 if(null != _factory) { 231 if(!_factory.validateObject(obj)) { 232 success = false; 233 } else { 234 try { 235 _factory.passivateObject(obj); 236 } catch(Exception e) { 237 success = false; 238 } 239 } 240 } 241 242 boolean shouldDestroy = !success; 243 244 _numActive--; 245 if (success) { 246 T toBeDestroyed = null; 247 if(_pool.size() >= _maxSleeping) { 248 shouldDestroy = true; 249 toBeDestroyed = _pool.remove(0); // remove the stalest object 250 } 251 _pool.push(obj); 252 obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed 253 } 254 notifyAll(); // _numActive has changed 255 256 if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null 257 try { 258 _factory.destroyObject(obj); 259 } catch(Exception e) { 260 // ignored 261 } 262 } 263 } 264 265 /** 266 * {@inheritDoc} 267 */ 268 @Override 269 public synchronized void invalidateObject(T obj) throws Exception { 270 _numActive--; 271 if (null != _factory) { 272 _factory.destroyObject(obj); 273 } 274 notifyAll(); // _numActive has changed 275 } 276 277 /** 278 * Return the number of instances 279 * currently idle in this pool. 280 * 281 * @return the number of instances currently idle in this pool 282 */ 283 @Override 284 public synchronized int getNumIdle() { 285 return _pool.size(); 286 } 287 288 /** 289 * Return the number of instances currently borrowed from this pool. 290 * 291 * @return the number of instances currently borrowed from this pool 292 */ 293 @Override 294 public synchronized int getNumActive() { 295 return _numActive; 296 } 297 298 /** 299 * Clears any objects sitting idle in the pool. Silently swallows any 300 * exceptions thrown by {@link PoolableObjectFactory#destroyObject(Object)}. 301 */ 302 @Override 303 public synchronized void clear() { 304 if(null != _factory) { 305 Iterator<T> it = _pool.iterator(); 306 while(it.hasNext()) { 307 try { 308 _factory.destroyObject(it.next()); 309 } catch(Exception e) { 310 // ignore error, keep destroying the rest 311 } 312 } 313 } 314 _pool.clear(); 315 } 316 317 /** 318 * <p>Close this pool, and free any resources associated with it. Invokes 319 * {@link #clear()} to destroy and remove instances in the pool.</p> 320 * 321 * <p>Calling {@link #addObject} or {@link #borrowObject} after invoking 322 * this method on a pool will cause them to throw an 323 * {@link IllegalStateException}.</p> 324 * 325 * @throws Exception never - exceptions clearing the pool are swallowed 326 */ 327 @Override 328 public void close() throws Exception { 329 super.close(); 330 clear(); 331 } 332 333 /** 334 * <p>Create an object, and place it on top of the stack. 335 * This method is useful for "pre-loading" a pool with idle objects.</p> 336 * 337 * <p>Before being added to the pool, the newly created instance is 338 * {@link PoolableObjectFactory#validateObject(Object) validated} and 339 * {@link PoolableObjectFactory#passivateObject(Object) passivated}. If validation 340 * fails, the new instance is {@link PoolableObjectFactory#destroyObject(Object) destroyed}. 341 * Exceptions generated by the factory <code>makeObject</code> or <code>passivate</code> are 342 * propagated to the caller. Exceptions destroying instances are silently swallowed.</p> 343 * 344 * <p>If a new instance is created and successfully validated and passivated and adding this 345 * instance to the pool causes {@link #getMaxSleeping() maxSleeping} to be exceeded, the oldest 346 * (bottom) instance in the pool is destroyed to make room for the newly created instance, which 347 * is pushed on top of the stack. 348 * 349 * @throws Exception when the {@link #getFactory() factory} has a problem creating or passivating an object. 350 */ 351 @Override 352 public synchronized void addObject() throws Exception { 353 assertOpen(); 354 if (_factory == null) { 355 throw new IllegalStateException("Cannot add objects without a factory."); 356 } 357 T obj = _factory.makeObject(); 358 359 boolean success = true; 360 if(!_factory.validateObject(obj)) { 361 success = false; 362 } else { 363 _factory.passivateObject(obj); 364 } 365 366 boolean shouldDestroy = !success; 367 368 if (success) { 369 T toBeDestroyed = null; 370 if(_pool.size() >= _maxSleeping) { 371 shouldDestroy = true; 372 toBeDestroyed = _pool.remove(0); // remove the stalest object 373 } 374 _pool.push(obj); 375 obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed 376 } 377 notifyAll(); // _numIdle has changed 378 379 if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null 380 try { 381 _factory.destroyObject(obj); 382 } catch(Exception e) { 383 // ignored 384 } 385 } 386 } 387 388 /** 389 * Sets the {@link PoolableObjectFactory factory} this pool uses 390 * to create new instances. Trying to change 391 * the <code>factory</code> while there are borrowed objects will 392 * throw an {@link IllegalStateException}. 393 * 394 * @param factory the {@link PoolableObjectFactory} used to create new instances. 395 * @throws IllegalStateException when the factory cannot be set at this time 396 * @deprecated to be removed in pool 2.0 397 */ 398 @Deprecated 399 @Override 400 public synchronized void setFactory(PoolableObjectFactory<T> factory) throws IllegalStateException { 401 assertOpen(); 402 if(0 < getNumActive()) { 403 throw new IllegalStateException("Objects are already active"); 404 } else { 405 clear(); 406 _factory = factory; 407 } 408 } 409 410 /** 411 * The cap on the number of "sleeping" instances in the pool. 412 */ 413 protected static final int DEFAULT_MAX_SLEEPING = 8; 414 415 /** 416 * The default initial size of the pool 417 * (this specifies the size of the container, it does not 418 * cause the pool to be pre-populated.) 419 */ 420 protected static final int DEFAULT_INIT_SLEEPING_CAPACITY = 4; 421 422 /** 423 * My pool. 424 * @deprecated to be made private in pool 2.0 425 */ 426 @Deprecated 427 protected Stack<T> _pool = null; 428 429 /** 430 * My {@link PoolableObjectFactory}. 431 * @deprecated to be made private in pool 2.0 - use {@link #getFactory()} 432 */ 433 @Deprecated 434 protected PoolableObjectFactory<T> _factory = null; 435 436 /** 437 * The cap on the number of "sleeping" instances in the pool. 438 * @deprecated to be made private in pool 2.0 - use {@link #getMaxSleeping()} 439 */ 440 @Deprecated 441 protected int _maxSleeping = DEFAULT_MAX_SLEEPING; 442 443 /** 444 * Number of objects borrowed but not yet returned to the pool. 445 * @deprecated to be made private in pool 2.0 - use {@link #getNumActive()} 446 */ 447 @Deprecated 448 protected int _numActive = 0; 449 450 /** 451 * Returns the {@link PoolableObjectFactory} used by this pool to create and manage object instances. 452 * 453 * @return the factory 454 * @since 1.5.5 455 */ 456 public synchronized PoolableObjectFactory<T> getFactory() { 457 return _factory; 458 } 459 460 /** 461 * Returns the maximum number of idle instances in the pool. 462 * 463 * @return maxSleeping 464 * @since 1.5.5 465 */ 466 public int getMaxSleeping() { 467 return _maxSleeping; 468 } 469 470 471 }