View Javadoc

1   /*
2    * Copyright 1999-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.pool.impl;
18  
19  import java.lang.ref.SoftReference;
20  import java.util.ArrayList;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.NoSuchElementException;
24  
25  import org.apache.commons.pool.BaseObjectPool;
26  import org.apache.commons.pool.ObjectPool;
27  import org.apache.commons.pool.PoolableObjectFactory;
28  
29  /***
30   * A {@link java.lang.ref.SoftReference SoftReference} based
31   * {@link ObjectPool}.
32   *
33   * @author Rodney Waldhoff
34   * @version $Revision: 383290 $ $Date: 2006-03-05 02:00:15 -0500 (Sun, 05 Mar 2006) $
35   */
36  public class SoftReferenceObjectPool extends BaseObjectPool implements ObjectPool {
37      public SoftReferenceObjectPool() {
38          _pool = new ArrayList();
39          _factory = null;
40      }
41  
42      public SoftReferenceObjectPool(PoolableObjectFactory factory) {
43          _pool = new ArrayList();
44          _factory = factory;
45      }
46  
47      public SoftReferenceObjectPool(PoolableObjectFactory factory, int initSize) throws Exception {
48          _pool = new ArrayList();
49          _factory = factory;
50          if(null != _factory) {
51              for(int i=0;i<initSize;i++) {
52                  Object obj = _factory.makeObject();
53                  _factory.passivateObject(obj);
54                  _pool.add(new SoftReference(obj));
55              }
56          }
57      }
58  
59      public synchronized Object borrowObject() throws Exception {        
60          assertOpen();
61          Object obj = null;
62          while(null == obj) {
63              if(_pool.isEmpty()) {
64                  if(null == _factory) {
65                      throw new NoSuchElementException();
66                  } else {
67                      obj = _factory.makeObject();
68                  }
69              } else {
70                  SoftReference ref = (SoftReference)(_pool.remove(_pool.size() - 1));
71                  obj = ref.get();
72              }
73              if(null != _factory && null != obj) {
74                  _factory.activateObject(obj);
75              }
76              if (null != _factory && null != obj && !_factory.validateObject(obj)) {
77                  _factory.destroyObject(obj);
78                  obj = null;
79              }
80          }
81          _numActive++;
82          return obj;
83      }
84  
85      public synchronized void returnObject(Object obj) throws Exception {
86          assertOpen();
87          boolean success = true;
88          if(!(_factory.validateObject(obj))) {
89              success = false;
90          } else {
91              try {
92                  _factory.passivateObject(obj);
93              } catch(Exception e) {
94                  success = false;
95              }
96          }
97  
98          boolean shouldDestroy = !success;
99          _numActive--;
100         if(success) {
101             _pool.add(new SoftReference(obj));
102         }
103         notifyAll(); // _numActive has changed
104 
105         if(shouldDestroy) {
106             try {
107                 _factory.destroyObject(obj);
108             } catch(Exception e) {
109                 // ignored
110             }
111         }
112 
113     }
114 
115     public synchronized void invalidateObject(Object obj) throws Exception {
116         assertOpen();
117         _numActive--;
118         _factory.destroyObject(obj);
119         notifyAll(); // _numActive has changed
120     }
121 
122     /***
123      * Create an object, and place it into the pool.
124      * addObject() is useful for "pre-loading" a pool with idle objects.
125      */
126     public synchronized void addObject() throws Exception {
127         assertOpen();
128         Object obj = _factory.makeObject();
129         _numActive++;   // A little slimy - must do this because returnObject decrements it.
130         returnObject(obj);
131     }
132 
133     /*** Returns an approximation not less than the of the number of idle instances in the pool. */
134     public synchronized int getNumIdle() {
135         assertOpen();
136         return _pool.size();
137     }
138 
139     public synchronized int getNumActive() {
140         assertOpen();
141         return _numActive;
142     }
143 
144     public synchronized void clear() {
145         assertOpen();
146         if(null != _factory) {
147             Iterator iter = _pool.iterator();
148             while(iter.hasNext()) {
149                 try {
150                     Object obj = ((SoftReference)iter.next()).get();
151                     if(null != obj) {
152                         _factory.destroyObject(obj);
153                     }
154                 } catch(Exception e) {
155                     // ignore error, keep destroying the rest
156                 }
157             }
158         }
159         _pool.clear();
160     }
161 
162     public synchronized void close() throws Exception {
163         clear();
164         _pool = null;
165         _factory = null;
166         super.close();
167     }
168 
169     public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException {
170         assertOpen();
171         if(0 < getNumActive()) {
172             throw new IllegalStateException("Objects are already active");
173         } else {
174             clear();
175             _factory = factory;
176         }
177     }
178 
179     /*** My pool. */
180     private List _pool = null;
181 
182     /*** My {@link PoolableObjectFactory}. */
183     private PoolableObjectFactory _factory = null;
184 
185     /*** Number of active objects. */
186     private int _numActive = 0;
187 }