1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
35
36
37
38
39
40
41
42 public class SoftReferenceObjectPool extends BaseObjectPool implements ObjectPool {
43
44
45
46
47
48
49
50
51 public SoftReferenceObjectPool() {
52 _pool = new ArrayList();
53 _factory = null;
54 }
55
56
57
58
59
60
61 public SoftReferenceObjectPool(PoolableObjectFactory factory) {
62 _pool = new ArrayList();
63 _factory = factory;
64 }
65
66
67
68
69
70
71
72
73
74
75
76 public SoftReferenceObjectPool(PoolableObjectFactory factory, int initSize) throws Exception, IllegalArgumentException {
77 if (factory == null) {
78 throw new IllegalArgumentException("factory required to prefill the pool.");
79 }
80 _pool = new ArrayList(initSize);
81 _factory = factory;
82 PoolUtils.prefill(this, initSize);
83 }
84
85 public synchronized Object borrowObject() throws Exception {
86 assertOpen();
87 Object obj = null;
88 boolean newlyCreated = false;
89 while(null == obj) {
90 if(_pool.isEmpty()) {
91 if(null == _factory) {
92 throw new NoSuchElementException();
93 } else {
94 newlyCreated = true;
95 obj = _factory.makeObject();
96 }
97 } else {
98 SoftReference ref = (SoftReference)(_pool.remove(_pool.size() - 1));
99 obj = ref.get();
100 ref.clear();
101 }
102 if (null != _factory && null != obj) {
103 try {
104 _factory.activateObject(obj);
105 if (!_factory.validateObject(obj)) {
106 throw new Exception("ValidateObject failed");
107 }
108 } catch (Throwable t) {
109 try {
110 _factory.destroyObject(obj);
111 } catch (Throwable t2) {
112
113 } finally {
114 obj = null;
115 }
116 if (newlyCreated) {
117 throw new NoSuchElementException(
118 "Could not create a validated object, cause: " +
119 t.getMessage());
120 }
121 }
122 }
123 }
124 _numActive++;
125 return obj;
126 }
127
128 public synchronized void returnObject(Object obj) throws Exception {
129 boolean success = !isClosed();
130 if (_factory != null) {
131 if(!_factory.validateObject(obj)) {
132 success = false;
133 } else {
134 try {
135 _factory.passivateObject(obj);
136 } catch(Exception e) {
137 success = false;
138 }
139 }
140 }
141
142 boolean shouldDestroy = !success;
143 _numActive--;
144 if(success) {
145 _pool.add(new SoftReference(obj, refQueue));
146 }
147 notifyAll();
148
149 if (shouldDestroy && _factory != null) {
150 try {
151 _factory.destroyObject(obj);
152 } catch(Exception e) {
153
154 }
155 }
156 }
157
158 public synchronized void invalidateObject(Object obj) throws Exception {
159 _numActive--;
160 if (_factory != null) {
161 _factory.destroyObject(obj);
162 }
163 notifyAll();
164 }
165
166
167
168
169
170 public synchronized void addObject() throws Exception {
171 assertOpen();
172 if (_factory == null) {
173 throw new IllegalStateException("Cannot add objects without a factory.");
174 }
175 Object obj = _factory.makeObject();
176
177 boolean success = true;
178 if(!_factory.validateObject(obj)) {
179 success = false;
180 } else {
181 _factory.passivateObject(obj);
182 }
183
184 boolean shouldDestroy = !success;
185 if(success) {
186 _pool.add(new SoftReference(obj, refQueue));
187 notifyAll();
188 }
189
190 if(shouldDestroy) {
191 try {
192 _factory.destroyObject(obj);
193 } catch(Exception e) {
194
195 }
196 }
197 }
198
199
200 public synchronized int getNumIdle() {
201 pruneClearedReferences();
202 return _pool.size();
203 }
204
205
206
207
208
209
210 public synchronized int getNumActive() {
211 return _numActive;
212 }
213
214
215
216
217 public synchronized void clear() {
218 if(null != _factory) {
219 Iterator iter = _pool.iterator();
220 while(iter.hasNext()) {
221 try {
222 Object obj = ((SoftReference)iter.next()).get();
223 if(null != obj) {
224 _factory.destroyObject(obj);
225 }
226 } catch(Exception e) {
227
228 }
229 }
230 }
231 _pool.clear();
232 pruneClearedReferences();
233 }
234
235 public void close() throws Exception {
236 super.close();
237 clear();
238 }
239
240
241
242
243
244
245
246
247
248
249 public synchronized void setFactory(PoolableObjectFactory factory) throws IllegalStateException {
250 assertOpen();
251 if(0 < getNumActive()) {
252 throw new IllegalStateException("Objects are already active");
253 } else {
254 clear();
255 _factory = factory;
256 }
257 }
258
259
260
261
262
263 private void pruneClearedReferences() {
264 Reference ref;
265 while ((ref = refQueue.poll()) != null) {
266 try {
267 _pool.remove(ref);
268 } catch (UnsupportedOperationException uoe) {
269
270 }
271 }
272 }
273
274
275 private List _pool = null;
276
277
278 private PoolableObjectFactory _factory = null;
279
280
281
282
283
284
285 private final ReferenceQueue refQueue = new ReferenceQueue();
286
287
288 private int _numActive = 0;
289 }