Coverage Report - org.apache.commons.pool.impl.SoftReferenceObjectPool
 
Classes in this File Line Coverage Branch Coverage Complexity
SoftReferenceObjectPool
0%
0/113
0%
0/52
3.769
 
 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.lang.ref.SoftReference;
 21  
 import java.lang.ref.ReferenceQueue;
 22  
 import java.lang.ref.Reference;
 23  
 import java.util.ArrayList;
 24  
 import java.util.Iterator;
 25  
 import java.util.List;
 26  
 import java.util.NoSuchElementException;
 27  
 
 28  
 import org.apache.commons.pool.BaseObjectPool;
 29  
 import org.apache.commons.pool.ObjectPool;
 30  
 import org.apache.commons.pool.PoolableObjectFactory;
 31  
 import org.apache.commons.pool.PoolUtils;
 32  
 
 33  
 /**
 34  
  * A {@link java.lang.ref.SoftReference SoftReference} based
 35  
  * {@link ObjectPool}.
 36  
  *
 37  
  * @author Rodney Waldhoff
 38  
  * @author Sandy McArthur
 39  
  * @version $Revision: 777748 $ $Date: 2009-05-22 20:00:44 -0400 (Fri, 22 May 2009) $
 40  
  * @since Pool 1.0
 41  
  */
 42  
 public class SoftReferenceObjectPool extends BaseObjectPool implements ObjectPool {
 43  
     /**
 44  
      * Create a <code>SoftReferenceObjectPool</code> without a factory.
 45  
      * {@link #setFactory(PoolableObjectFactory) setFactory} should be called
 46  
      * before any attempts to use the pool are made.
 47  
      * Generally speaking you should prefer the {@link #SoftReferenceObjectPool(PoolableObjectFactory)} constructor.
 48  
      *
 49  
      * @see #SoftReferenceObjectPool(PoolableObjectFactory)
 50  
      */
 51  0
     public SoftReferenceObjectPool() {
 52  0
         _pool = new ArrayList();
 53  0
         _factory = null;
 54  0
     }
 55  
 
 56  
     /**
 57  
      * Create a <code>SoftReferenceObjectPool</code> with the specified factory.
 58  
      *
 59  
      * @param factory object factory to use.
 60  
      */
 61  0
     public SoftReferenceObjectPool(PoolableObjectFactory factory) {
 62  0
         _pool = new ArrayList();
 63  0
         _factory = factory;
 64  0
     }
 65  
 
 66  
     /**
 67  
      * Create a <code>SoftReferenceObjectPool</code> with the specified factory and initial idle object count.
 68  
      *
 69  
      * @param factory object factory to use.
 70  
      * @param initSize initial size to attempt to prefill the pool.
 71  
      * @throws Exception when there is a problem prefilling the pool.
 72  
      * @throws IllegalArgumentException when <code>factory</code> is <code>null</code>.
 73  
      * @deprecated because this is a SoftReference pool, prefilled idle obejects may be garbage collected before they are used.
 74  
      *      To be removed in Pool 3.0.
 75  
      */
 76  0
     public SoftReferenceObjectPool(PoolableObjectFactory factory, int initSize) throws Exception, IllegalArgumentException {
 77  0
         if (factory == null) {
 78  0
             throw new IllegalArgumentException("factory required to prefill the pool.");
 79  
         }
 80  0
         _pool = new ArrayList(initSize);
 81  0
         _factory = factory;
 82  0
         PoolUtils.prefill(this, initSize);
 83  0
     }
 84  
 
 85  
     public synchronized Object borrowObject() throws Exception {
 86  0
         assertOpen();
 87  0
         Object obj = null;
 88  0
         boolean newlyCreated = false;
 89  0
         while(null == obj) {
 90  0
             if(_pool.isEmpty()) {
 91  0
                 if(null == _factory) {
 92  0
                     throw new NoSuchElementException();
 93  
                 } else {
 94  0
                     newlyCreated = true;
 95  0
                     obj = _factory.makeObject();
 96  
                 }
 97  
             } else {
 98  0
                 SoftReference ref = (SoftReference)(_pool.remove(_pool.size() - 1));
 99  0
                 obj = ref.get();
 100  0
                 ref.clear(); // prevent this ref from being enqueued with refQueue.
 101  
             }
 102  0
             if (null != _factory && null != obj) {
 103  
                 try {
 104  0
                     _factory.activateObject(obj);
 105  0
                     if (!_factory.validateObject(obj)) {
 106  0
                         throw new Exception("ValidateObject failed");
 107  
                     }
 108  0
                 } catch (Throwable t) {
 109  
                     try {
 110  0
                         _factory.destroyObject(obj);
 111  0
                     } catch (Throwable t2) {
 112  
                         // swallowed
 113  
                     } finally {
 114  0
                         obj = null;
 115  0
                     }
 116  0
                     if (newlyCreated) {
 117  0
                         throw new NoSuchElementException(
 118  
                             "Could not create a validated object, cause: " +
 119  
                             t.getMessage());
 120  
                     }
 121  0
                 }
 122  
             }
 123  
         }
 124  0
         _numActive++;
 125  0
         return obj;
 126  
     }
 127  
 
 128  
     public synchronized void returnObject(Object obj) throws Exception {
 129  0
         boolean success = !isClosed();
 130  0
         if (_factory != null) {
 131  0
             if(!_factory.validateObject(obj)) {
 132  0
                 success = false;
 133  
             } else {
 134  
                 try {
 135  0
                     _factory.passivateObject(obj);
 136  0
                 } catch(Exception e) {
 137  0
                     success = false;
 138  0
                 }
 139  
             }
 140  
         }
 141  
 
 142  0
         boolean shouldDestroy = !success;
 143  0
         _numActive--;
 144  0
         if(success) {
 145  0
             _pool.add(new SoftReference(obj, refQueue));
 146  
         }
 147  0
         notifyAll(); // _numActive has changed
 148  
 
 149  0
         if (shouldDestroy && _factory != null) {
 150  
             try {
 151  0
                 _factory.destroyObject(obj);
 152  0
             } catch(Exception e) {
 153  
                 // ignored
 154  0
             }
 155  
         }
 156  0
     }
 157  
 
 158  
     public synchronized void invalidateObject(Object obj) throws Exception {
 159  0
         _numActive--;
 160  0
         if (_factory != null) {
 161  0
             _factory.destroyObject(obj);
 162  
         }
 163  0
         notifyAll(); // _numActive has changed
 164  0
     }
 165  
 
 166  
     /**
 167  
      * Create an object, and place it into the pool.
 168  
      * addObject() is useful for "pre-loading" a pool with idle objects.
 169  
      */
 170  
     public synchronized void addObject() throws Exception {
 171  0
         assertOpen();
 172  0
         if (_factory == null) {
 173  0
             throw new IllegalStateException("Cannot add objects without a factory.");
 174  
         }
 175  0
         Object obj = _factory.makeObject();
 176  
 
 177  0
         boolean success = true;
 178  0
         if(!_factory.validateObject(obj)) {
 179  0
             success = false;
 180  
         } else {
 181  0
             _factory.passivateObject(obj);
 182  
         }
 183  
 
 184  0
         boolean shouldDestroy = !success;
 185  0
         if(success) {
 186  0
             _pool.add(new SoftReference(obj, refQueue));
 187  0
             notifyAll(); // _numActive has changed
 188  
         }
 189  
 
 190  0
         if(shouldDestroy) {
 191  
             try {
 192  0
                 _factory.destroyObject(obj);
 193  0
             } catch(Exception e) {
 194  
                 // ignored
 195  0
             }
 196  
         }
 197  0
     }
 198  
 
 199  
     /** Returns an approximation not less than the of the number of idle instances in the pool. */
 200  
     public synchronized int getNumIdle() {
 201  0
         pruneClearedReferences();
 202  0
         return _pool.size();
 203  
     }
 204  
 
 205  
     /**
 206  
      * Return the number of instances currently borrowed from this pool.
 207  
      *
 208  
      * @return the number of instances currently borrowed from this pool
 209  
      */
 210  
     public synchronized int getNumActive() {
 211  0
         return _numActive;
 212  
     }
 213  
 
 214  
     /**
 215  
      * Clears any objects sitting idle in the pool.
 216  
      */
 217  
     public synchronized void clear() {
 218  0
         if(null != _factory) {
 219  0
             Iterator iter = _pool.iterator();
 220  0
             while(iter.hasNext()) {
 221  
                 try {
 222  0
                     Object obj = ((SoftReference)iter.next()).get();
 223  0
                     if(null != obj) {
 224  0
                         _factory.destroyObject(obj);
 225  
                     }
 226  0
                 } catch(Exception e) {
 227  
                     // ignore error, keep destroying the rest
 228  0
                 }
 229  
             }
 230  
         }
 231  0
         _pool.clear();
 232  0
         pruneClearedReferences();
 233  0
     }
 234  
 
 235  
     public void close() throws Exception {
 236  0
         super.close();
 237  0
         clear();
 238  0
     }
 239  
 
 240  
     /**
 241  
      * Sets the {@link PoolableObjectFactory factory} this pool uses
 242  
      * to create new instances. Trying to change
 243  
      * the <code>factory</code> while there are borrowed objects will
 244  
      * throw an {@link IllegalStateException}.
 245  
      *
 246  
      * @param factory the {@link PoolableObjectFactory} used to create new instances.
 247  
      * @throws IllegalStateException when the factory cannot be set at this time
 248  
      */
 249  
     public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException {
 250  0
         assertOpen();
 251  0
         if(0 < getNumActive()) {
 252  0
             throw new IllegalStateException("Objects are already active");
 253  
         } else {
 254  0
             clear();
 255  0
             _factory = factory;
 256  
         }
 257  0
     }
 258  
 
 259  
     /**
 260  
      * If any idle objects were garbage collected, remove their
 261  
      * {@link Reference} wrappers from the idle object pool.
 262  
      */
 263  
     private void pruneClearedReferences() {
 264  
         Reference ref;
 265  0
         while ((ref = refQueue.poll()) != null) {
 266  
             try {
 267  0
                 _pool.remove(ref);
 268  0
             } catch (UnsupportedOperationException uoe) {
 269  
                 // ignored
 270  0
             }
 271  
         }
 272  0
     }
 273  
 
 274  
     /** My pool. */
 275  0
     private List _pool = null;
 276  
 
 277  
     /** My {@link PoolableObjectFactory}. */
 278  0
     private PoolableObjectFactory _factory = null;
 279  
 
 280  
     /**
 281  
      * Queue of broken references that might be able to be removed from <code>_pool</code>.
 282  
      * This is used to help {@link #getNumIdle()} be more accurate with minimial
 283  
      * performance overhead.
 284  
      */
 285  0
     private final ReferenceQueue refQueue = new ReferenceQueue();
 286  
 
 287  
     /** Number of active objects. */
 288  0
     private int _numActive = 0;
 289  
 }