Coverage Report - org.apache.commons.pool.impl.StackObjectPool
 
Classes in this File Line Coverage Branch Coverage Complexity
StackObjectPool
0%
0/116
0%
0/56
3.467
 
 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.PoolableObjectFactory;
 27  
 
 28  
 /**
 29  
  * A simple, {@link java.util.Stack Stack}-based {@link ObjectPool} implementation.
 30  
  * <p>
 31  
  * Given a {@link PoolableObjectFactory}, this class will maintain
 32  
  * a simple pool of instances.  A finite number of "sleeping"
 33  
  * or idle 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  
  * @author Dirk Verbeeck
 42  
  * @author Sandy McArthur
 43  
  * @version $Revision: 777748 $ $Date: 2009-05-22 20:00:44 -0400 (Fri, 22 May 2009) $
 44  
  * @since Pool 1.0
 45  
  */
 46  
 public class StackObjectPool extends BaseObjectPool implements ObjectPool {
 47  
     /**
 48  
      * Create a new pool using
 49  
      * no factory.
 50  
      * Clients must first {@link #setFactory(PoolableObjectFactory) set the factory}
 51  
      * else this pool will not behave correctly.
 52  
      * Clients may first populate the pool
 53  
      * using {@link #returnObject(java.lang.Object)}
 54  
      * before they can be {@link #borrowObject borrowed} but this useage is <strong>discouraged</strong>.
 55  
      *
 56  
      * @see #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
 64  
      * no factory.
 65  
      * Clients must first {@link #setFactory(PoolableObjectFactory) set the factory}
 66  
      * else this pool will not behave correctly.
 67  
      * Clients may first populate the pool
 68  
      * using {@link #returnObject(java.lang.Object)}
 69  
      * before they can be {@link #borrowObject borrowed} but this useage is <strong>discouraged</strong>.
 70  
      *
 71  
      * @param maxIdle cap on the number of "sleeping" instances in the pool
 72  
      * @see #StackObjectPool(PoolableObjectFactory, int)
 73  
      */
 74  
     public StackObjectPool(int maxIdle) {
 75  0
         this((PoolableObjectFactory)null,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY);
 76  0
     }
 77  
 
 78  
     /**
 79  
      * Create a new pool using
 80  
      * no factory.
 81  
      * Clients must first {@link #setFactory(PoolableObjectFactory) set the factory}
 82  
      * else this pool will not behave correctly.
 83  
      * Clients may first populate the pool
 84  
      * using {@link #returnObject(java.lang.Object)}
 85  
      * before they can be {@link #borrowObject borrowed} but this useage is <strong>discouraged</strong>.
 86  
      *
 87  
      * @param maxIdle cap on the number of "sleeping" instances in the pool
 88  
      * @param initIdleCapacity initial size of the pool (this specifies the size of the container,
 89  
      *             it does not cause the pool to be pre-populated.)
 90  
      * @see #StackObjectPool(PoolableObjectFactory, int, int)
 91  
      */
 92  
     public StackObjectPool(int maxIdle, int initIdleCapacity) {
 93  0
         this((PoolableObjectFactory)null,maxIdle,initIdleCapacity);
 94  0
     }
 95  
 
 96  
     /**
 97  
      * Create a new <tt>StackObjectPool</tt> using
 98  
      * the specified <i>factory</i> to create new instances.
 99  
      *
 100  
      * @param factory the {@link PoolableObjectFactory} used to populate the pool
 101  
      */
 102  
     public StackObjectPool(PoolableObjectFactory factory) {
 103  0
         this(factory,DEFAULT_MAX_SLEEPING,DEFAULT_INIT_SLEEPING_CAPACITY);
 104  0
     }
 105  
 
 106  
     /**
 107  
      * Create a new <tt>SimpleObjectPool</tt> using
 108  
      * the specified <i>factory</i> to create new instances,
 109  
      * capping the number of "sleeping" instances to <i>max</i>.
 110  
      *
 111  
      * @param factory the {@link PoolableObjectFactory} used to populate the pool
 112  
      * @param maxIdle cap on the number of "sleeping" instances in the pool
 113  
      */
 114  
     public StackObjectPool(PoolableObjectFactory factory, int maxIdle) {
 115  0
         this(factory,maxIdle,DEFAULT_INIT_SLEEPING_CAPACITY);
 116  0
     }
 117  
 
 118  
     /**
 119  
      * Create a new <tt>SimpleObjectPool</tt> using
 120  
      * the specified <i>factory</i> to create new instances,
 121  
      * capping the number of "sleeping" instances to <i>max</i>,
 122  
      * and initially allocating a container capable of containing
 123  
      * at least <i>init</i> instances.
 124  
      *
 125  
      * @param factory the {@link PoolableObjectFactory} used to populate the pool
 126  
      * @param maxIdle cap on the number of "sleeping" instances in the pool
 127  
      * @param initIdleCapacity initial size of the pool (this specifies the size of the container,
 128  
      *             it does not cause the pool to be pre-populated.)
 129  
      */
 130  0
     public StackObjectPool(PoolableObjectFactory factory, int maxIdle, int initIdleCapacity) {
 131  0
         _factory = factory;
 132  0
         _maxSleeping = (maxIdle < 0 ? DEFAULT_MAX_SLEEPING : maxIdle);
 133  0
         int initcapacity = (initIdleCapacity < 1 ? DEFAULT_INIT_SLEEPING_CAPACITY : initIdleCapacity);
 134  0
         _pool = new Stack();
 135  0
         _pool.ensureCapacity( initcapacity > _maxSleeping ? _maxSleeping : initcapacity);
 136  0
     }
 137  
 
 138  
     public synchronized Object borrowObject() throws Exception {
 139  0
         assertOpen();
 140  0
         Object obj = null;
 141  0
         boolean newlyCreated = false;
 142  0
         while (null == obj) {
 143  0
             if (!_pool.empty()) {
 144  0
                 obj = _pool.pop();
 145  
             } else {
 146  0
                 if(null == _factory) {
 147  0
                     throw new NoSuchElementException();
 148  
                 } else {
 149  0
                     obj = _factory.makeObject();
 150  0
                     newlyCreated = true;
 151  0
                   if (obj == null) {
 152  0
                     throw new NoSuchElementException("PoolableObjectFactory.makeObject() returned null.");
 153  
                   }
 154  
                 }
 155  
             }
 156  0
             if (null != _factory && null != obj) {
 157  
                 try {
 158  0
                     _factory.activateObject(obj);
 159  0
                     if (!_factory.validateObject(obj)) {
 160  0
                         throw new Exception("ValidateObject failed");
 161  
                     }
 162  0
                 } catch (Throwable t) {
 163  
                     try {
 164  0
                         _factory.destroyObject(obj);
 165  0
                     } catch (Throwable t2) {
 166  
                         // swallowed
 167  
                     } finally {
 168  0
                         obj = null;
 169  0
                     }
 170  0
                     if (newlyCreated) {
 171  0
                         throw new NoSuchElementException(
 172  
                             "Could not create a validated object, cause: " +
 173  
                             t.getMessage());
 174  
                     }
 175  0
                 }
 176  
             }
 177  
         }
 178  0
         _numActive++;
 179  0
         return obj;
 180  
     }
 181  
 
 182  
     public synchronized void returnObject(Object obj) throws Exception {
 183  0
         boolean success = !isClosed();
 184  0
         if(null != _factory) {
 185  0
             if(!_factory.validateObject(obj)) {
 186  0
                 success = false;
 187  
             } else {
 188  
                 try {
 189  0
                     _factory.passivateObject(obj);
 190  0
                 } catch(Exception e) {
 191  0
                     success = false;
 192  0
                 }
 193  
             }
 194  
         }
 195  
 
 196  0
         boolean shouldDestroy = !success;
 197  
 
 198  0
         _numActive--;
 199  0
         if (success) {
 200  0
             Object toBeDestroyed = null;
 201  0
             if(_pool.size() >= _maxSleeping) {
 202  0
                 shouldDestroy = true;
 203  0
                 toBeDestroyed = _pool.remove(0); // remove the stalest object
 204  
             }
 205  0
             _pool.push(obj);
 206  0
             obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed
 207  
         }
 208  0
         notifyAll(); // _numActive has changed
 209  
 
 210  0
         if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null
 211  
             try {
 212  0
                 _factory.destroyObject(obj);
 213  0
             } catch(Exception e) {
 214  
                 // ignored
 215  0
             }
 216  
         }
 217  0
     }
 218  
 
 219  
     public synchronized void invalidateObject(Object obj) throws Exception {
 220  0
         _numActive--;
 221  0
         if (null != _factory) {
 222  0
             _factory.destroyObject(obj);
 223  
         }
 224  0
         notifyAll(); // _numActive has changed
 225  0
     }
 226  
 
 227  
     /**
 228  
      * Return the number of instances
 229  
      * currently idle in this pool.
 230  
      *
 231  
      * @return the number of instances currently idle in this pool
 232  
      */
 233  
     public synchronized int getNumIdle() {
 234  0
         return _pool.size();
 235  
     }
 236  
 
 237  
     /**
 238  
      * Return the number of instances currently borrowed from this pool.
 239  
      *
 240  
      * @return the number of instances currently borrowed from this pool
 241  
      */
 242  
     public synchronized int getNumActive() {
 243  0
         return _numActive;
 244  
     }
 245  
 
 246  
     /**
 247  
      * Clears any objects sitting idle in the pool.
 248  
      */
 249  
     public synchronized void clear() {
 250  0
         if(null != _factory) {
 251  0
             Iterator it = _pool.iterator();
 252  0
             while(it.hasNext()) {
 253  
                 try {
 254  0
                     _factory.destroyObject(it.next());
 255  0
                 } catch(Exception e) {
 256  
                     // ignore error, keep destroying the rest
 257  0
                 }
 258  
             }
 259  
         }
 260  0
         _pool.clear();
 261  0
     }
 262  
 
 263  
     /**
 264  
      * Close this pool, and free any resources associated with it.
 265  
      * <p>
 266  
      * Calling {@link #addObject} or {@link #borrowObject} after invoking
 267  
      * this method on a pool will cause them to throw an
 268  
      * {@link IllegalStateException}.
 269  
      * </p>
 270  
      *
 271  
      * @throws Exception <strong>deprecated</strong>: implementations should silently fail if not all resources can be freed.
 272  
      */
 273  
     public void close() throws Exception {
 274  0
         super.close();
 275  0
         clear();
 276  0
     }
 277  
 
 278  
     /**
 279  
      * Create an object, and place it into the pool.
 280  
      * addObject() is useful for "pre-loading" a pool with idle objects.
 281  
      * @throws Exception when the {@link #_factory} has a problem creating an object.
 282  
      */
 283  
     public synchronized void addObject() throws Exception {
 284  0
         assertOpen();
 285  0
         if (_factory == null) {
 286  0
             throw new IllegalStateException("Cannot add objects without a factory.");
 287  
         }
 288  0
         Object obj = _factory.makeObject();
 289  
 
 290  0
         boolean success = true;
 291  0
         if(!_factory.validateObject(obj)) {
 292  0
             success = false;
 293  
         } else {
 294  0
             _factory.passivateObject(obj);
 295  
         }
 296  
 
 297  0
         boolean shouldDestroy = !success;
 298  
 
 299  0
         if (success) {
 300  0
             Object toBeDestroyed = null;
 301  0
             if(_pool.size() >= _maxSleeping) {
 302  0
                 shouldDestroy = true;
 303  0
                 toBeDestroyed = _pool.remove(0); // remove the stalest object
 304  
             }
 305  0
             _pool.push(obj);
 306  0
             obj = toBeDestroyed; // swap returned obj with the stalest one so it can be destroyed
 307  
         }
 308  0
         notifyAll(); // _numIdle has changed
 309  
 
 310  0
         if(shouldDestroy) { // by constructor, shouldDestroy is false when _factory is null
 311  
             try {
 312  0
                 _factory.destroyObject(obj);
 313  0
             } catch(Exception e) {
 314  
                 // ignored
 315  0
             }
 316  
         }
 317  0
     }
 318  
 
 319  
     /**
 320  
      * Sets the {@link PoolableObjectFactory factory} this pool uses
 321  
      * to create new instances. Trying to change
 322  
      * the <code>factory</code> while there are borrowed objects will
 323  
      * throw an {@link IllegalStateException}.
 324  
      *
 325  
      * @param factory the {@link PoolableObjectFactory} used to create new instances.
 326  
      * @throws IllegalStateException when the factory cannot be set at this time
 327  
      */
 328  
     public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException {
 329  0
         assertOpen();
 330  0
         if(0 < getNumActive()) {
 331  0
             throw new IllegalStateException("Objects are already active");
 332  
         } else {
 333  0
             clear();
 334  0
             _factory = factory;
 335  
         }
 336  0
     }
 337  
 
 338  
     /** The default cap on the number of "sleeping" instances in the pool. */
 339  
     protected static final int DEFAULT_MAX_SLEEPING  = 8;
 340  
 
 341  
     /**
 342  
      * The default initial size of the pool
 343  
      * (this specifies the size of the container, it does not
 344  
      * cause the pool to be pre-populated.)
 345  
      */
 346  
     protected static final int DEFAULT_INIT_SLEEPING_CAPACITY = 4;
 347  
 
 348  
     /** My pool. */
 349  0
     protected Stack _pool = null;
 350  
 
 351  
     /** My {@link PoolableObjectFactory}. */
 352  0
     protected PoolableObjectFactory _factory = null;
 353  
 
 354  
     /** The cap on the number of "sleeping" instances in the pool. */
 355  0
     protected int _maxSleeping = DEFAULT_MAX_SLEEPING;
 356  
 
 357  
     /** Number of object borrowed but not yet returned to the pool. */
 358  0
     protected int _numActive = 0;
 359  
 }