Coverage Report - org.apache.commons.pool.impl.StackObjectPool
 
Classes in this File Line Coverage Branch Coverage Complexity
StackObjectPool
0%
0/120
0%
0/56
3.176
 
 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  0
         this((PoolableObjectFactory)null,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY);
 60  0
     }
 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  0
         this((PoolableObjectFactory)null,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY);
 75  0
     }
 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  0
         this((PoolableObjectFactory)null,maxIdle,initIdleCapacity);
 92  0
     }
 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  0
         this(factory,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY);
 101  0
     }
 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  0
         this(factory,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY);
 112  0
     }
 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 &gt; 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  0
     public StackObjectPool(PoolableObjectFactory factory, int maxIdle, int initIdleCapacity) {
 130  0
         _factory = factory;
 131  0
         _maxSleeping = (maxIdle < 0 ? DEFAULT_MAX_SLEEPING : maxIdle);
 132  0
         int initcapacity = (initIdleCapacity < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : initIdleCapacity);
 133  0
         _pool = new Stack();
 134  0
         _pool.ensureCapacity( initcapacity > _maxSleeping ? _maxSleeping : initcapacity);
 135  0
     }
 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  0
         assertOpen();
 161  0
         Object obj = null;
 162  0
         boolean newlyCreated = false;
 163  0
         while (null == obj) {
 164  0
             if (!_pool.empty()) {
 165  0
                 obj = _pool.pop();
 166  
             } else {
 167  0
                 if(null == _factory) {
 168  0
                     throw new NoSuchElementException();
 169  
                 } else {
 170  0
                     obj = _factory.makeObject();
 171  0
                     newlyCreated = true;
 172  0
                   if (obj == null) {
 173  0
                     throw new NoSuchElementException("PoolableObjectFactory.makeObject() returned null.");
 174  
                   }
 175  
                 }
 176  
             }
 177  0
             if (null != _factory && null != obj) {
 178  
                 try {
 179  0
                     _factory.activateObject(obj);
 180  0
                     if (!_factory.validateObject(obj)) {
 181  0
                         throw new Exception("ValidateObject failed");
 182  
                     }
 183  0
                 } catch (Throwable t) {
 184  0
                     PoolUtils.checkRethrow(t);
 185  
                     try {
 186  0
                         _factory.destroyObject(obj);
 187  0
                     } catch (Throwable t2) {
 188  0
                         PoolUtils.checkRethrow(t2);
 189  
                         // swallowed
 190  
                     } finally {
 191  0
                         obj = null;
 192  0
                     }
 193  0
                     if (newlyCreated) {
 194  0
                         throw new NoSuchElementException(
 195  
                             "Could not create a validated object, cause: " +
 196  
                             t.getMessage());
 197  
                     }
 198  0
                 }
 199  
             }
 200  
         }
 201  0
         _numActive++;
 202  0
         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  0
         boolean success = !isClosed();
 223  0
         if(null != _factory) {
 224  0
             if(!_factory.validateObject(obj)) {
 225  0
                 success = false;
 226  
             } else {
 227  
                 try {
 228  0
                     _factory.passivateObject(obj);
 229  0
                 } catch(Exception e) {
 230  0
                     success = false;
 231  0
                 }
 232  
             }
 233  
         }
 234  
 
 235  0
         boolean shouldDestroy = !success;
 236  
 
 237  0
         _numActive--;
 238  0
         if (success) {
 239  0
             Object toBeDestroyed = null;
 240  0
             if(_pool.size() >= _maxSleeping) {
 241  0
                 shouldDestroy = true;
 242  0
                 toBeDestroyed = _pool.remove(0); // remove the stalest object
 243  
             }
 244  0
             _pool.push(obj);
 245  0
             obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed
 246  
         }
 247  0
         notifyAll(); // _numActive has changed
 248  
 
 249  0
         if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null
 250  
             try {
 251  0
                 _factory.destroyObject(obj);
 252  0
             } catch(Exception e) {
 253  
                 // ignored
 254  0
             }
 255  
         }
 256  0
     }
 257  
 
 258  
     /**
 259  
      * {@inheritDoc}
 260  
      */
 261  
     public synchronized void invalidateObject(Object obj) throws Exception {
 262  0
         _numActive--;
 263  0
         if (null != _factory) {
 264  0
             _factory.destroyObject(obj);
 265  
         }
 266  0
         notifyAll(); // _numActive has changed
 267  0
     }
 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  0
         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  0
         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  0
         if(null != _factory) {
 294  0
             Iterator it = _pool.iterator();
 295  0
             while(it.hasNext()) {
 296  
                 try {
 297  0
                     _factory.destroyObject(it.next());
 298  0
                 } catch(Exception e) {
 299  
                     // ignore error, keep destroying the rest
 300  0
                 }
 301  
             }
 302  
         }
 303  0
         _pool.clear();
 304  0
     }
 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  0
         super.close();
 318  0
         clear();
 319  0
     }
 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  0
         assertOpen();
 341  0
         if (_factory == null) {
 342  0
             throw new IllegalStateException("Cannot add objects without a factory.");
 343  
         }
 344  0
         Object obj = _factory.makeObject();
 345  
 
 346  0
         boolean success = true;
 347  0
         if(!_factory.validateObject(obj)) {
 348  0
             success = false;
 349  
         } else {
 350  0
             _factory.passivateObject(obj);
 351  
         }
 352  
 
 353  0
         boolean shouldDestroy = !success;
 354  
 
 355  0
         if (success) {
 356  0
             Object toBeDestroyed = null;
 357  0
             if(_pool.size() >= _maxSleeping) {
 358  0
                 shouldDestroy = true;
 359  0
                 toBeDestroyed = _pool.remove(0); // remove the stalest object
 360  
             }
 361  0
             _pool.push(obj);
 362  0
             obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed
 363  
         }
 364  0
         notifyAll(); // _numIdle has changed
 365  
 
 366  0
         if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null
 367  
             try {
 368  0
                 _factory.destroyObject(obj);
 369  0
             } catch(Exception e) {
 370  
                 // ignored
 371  0
             }
 372  
         }
 373  0
     }
 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  0
         assertOpen();
 387  0
         if(0 < getNumActive()) {
 388  0
             throw new IllegalStateException("Objects are already active");
 389  
         } else {
 390  0
             clear();
 391  0
             _factory = factory;
 392  
         }
 393  0
     }
 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  0
     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  0
     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  0
     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  0
     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  0
         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  0
         return _maxSleeping;
 449  
     }
 450  
 
 451  
    
 452  
 }