KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openharmonise > commons > pool > AbstractPool


1 /*
2  * The contents of this file are subject to the
3  * Mozilla Public License Version 1.1 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
6  *
7  * Software distributed under the License is distributed on an "AS IS"
8  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
9  * See the License for the specific language governing rights and
10  * limitations under the License.
11  *
12  * The Initial Developer of the Original Code is Simulacra Media Ltd.
13  * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
14  *
15  * All Rights Reserved.
16  *
17  * Contributor(s):
18  */

19 package org.openharmonise.commons.pool;
20
21 import java.util.*;
22 import java.util.logging.*;
23 import java.util.logging.Logger JavaDoc;
24
25 /**
26  * Abstract class providing base functionality for managing a pool of objects.
27  *
28  * @author Michael Bell
29  * @version $Revision: 1.1 $
30  *
31  */

32 public abstract class AbstractPool {
33     
34     /**
35      * Object expiration time
36      */

37     private long expirationTime;
38     
39     /**
40      * Last check out time
41      */

42     private long lastCheckOut;
43     
44     /**
45      * List of locked objects
46      */

47     private Map lockedMap;
48     
49     /**
50      * List of available unlocked objects
51      */

52     private Map unlockedMap;
53     
54     /**
55      * Clean-up thread
56      */

57     private CleanUpThread cleaner;
58     
59     /**
60      * Minimum number in pool
61      */

62     private int MIN_POOL = 0;
63
64     /**
65      * Logger for logging comments
66      */

67     private static Logger JavaDoc m_logger = Logger.getLogger(AbstractPool.class.getName());
68
69     /**
70      * Constructs pool object with default settings
71      */

72     public AbstractPool() {
73         expirationTime = (1000 * 300000); // 30 seconds
74
lockedMap = new Hashtable();
75         unlockedMap = new Hashtable();
76         lastCheckOut = System.currentTimeMillis();
77
78         cleaner = new CleanUpThread(this, expirationTime);
79         cleaner.start();
80
81         //initialise pool with min objects
82
Object JavaDoc o;
83
84         try {
85             for (int i = 0; i < MIN_POOL; i++) {
86                 o = create();
87
88                 unlockedMap.put(o, new TimestampedObject(o,
89                     new Long JavaDoc(System.currentTimeMillis())));
90             }
91         } catch (Exception JavaDoc e) {
92             m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
93         }
94     }
95     
96     /**
97      * Creates new object for pool.
98      *
99      * @return object to be pooled
100      * @throws Exception if any errors occur
101      */

102     abstract public Object JavaDoc create() throws Exception JavaDoc;
103
104     /**
105      * Returns <code>true</code> if object is valid.
106      *
107      * @param o object to be validated
108      * @return <code>true</code> of object is valid
109      */

110     abstract public boolean validate(Object JavaDoc o);
111
112     /**
113      * Expires given object.
114      *
115      * @param o object to be expired
116      */

117     abstract public void expire(Object JavaDoc o);
118
119     /**
120      * Sets the minimum pool size.
121      *
122      * @param num desired minimum pool size
123      */

124     public void setMinPoolSize(int num) {
125         MIN_POOL = num;
126
127         ensureMinPool();
128     }
129
130     /**
131      * Returns the number of objects in the pool.
132      *
133      * @return the number of objects in the pool
134      */

135     public synchronized int countObjects() {
136         return lockedMap.size() + unlockedMap.size();
137     }
138
139     /**
140      * Checkout an object from the pool.
141      *
142      * @return a pooled object
143      * @throws Exception if any errors occur
144      */

145     public synchronized Object JavaDoc checkOut() throws Exception JavaDoc {
146         long now = System.currentTimeMillis();
147         lastCheckOut = now;
148
149         Object JavaDoc o;
150         TimestampedObject to;
151         synchronized (unlockedMap) {
152             synchronized (lockedMap) {
153                 if (unlockedMap.size() > 0) {
154                     boolean bFoundValid = false;
155
156                     while ((bFoundValid == false) && (unlockedMap.size() > 0)) {
157                         o = unlockedMap.keySet().iterator().next();
158                         
159                         if (validate(o)) {
160                             bFoundValid = true;
161                             lockedMap.put(o, unlockedMap.get(o));
162                             unlockedMap.remove(o);
163
164                             m_logger.logp(Level.FINER, this.getClass().getName(), "checkOut", "Giving out object - " +
165                                 o.hashCode() );
166            
167
168                             return o;
169                         } else {
170                             unlockedMap.remove(o);
171                             expire(o);
172                             to = null;
173                         }
174                     }
175                 }
176                 o = create();
177                 lockedMap.put(o,new TimestampedObject(o, new Long JavaDoc(now)));
178             }
179         }
180
181         ensureMinPool();
182
183         return o;
184     }
185
186     /**
187      * Checks the given object back in to the pool.
188      *
189      * @param o object to be checked in
190      */

191     public synchronized void checkIn(Object JavaDoc o) {
192         if (o != null) {
193             synchronized (unlockedMap) {
194                 synchronized (lockedMap) {
195                     
196
197                     m_logger.log(Level.FINER, "Checking in..." + o.hashCode());
198                     
199                     unlockedMap.put(o, lockedMap.get(o));
200                     lockedMap.remove(o);
201                 }
202             }
203         }
204     }
205
206     /**
207      * Cleans up expired objects from the pool.
208      */

209     synchronized void cleanUp() {
210         synchronized (unlockedMap) {
211             TimestampedObject to;
212             Object JavaDoc o;
213             ArrayList toRemove = new ArrayList();
214
215             long now = System.currentTimeMillis();
216
217             for (Iterator iter = unlockedMap.keySet().iterator();
218                 iter.hasNext();
219                 ) {
220                 o = (Object JavaDoc) iter.next();
221                 
222                 to = (TimestampedObject) unlockedMap.get(o);
223                 
224                 if ((now - to.getTimestamp().longValue()) > expirationTime) {
225                     //unlocked.remove(unlocked.indexOf(to));
226
toRemove.add(o);
227                     expire(o);
228                 }
229             }
230             
231             for (Iterator iter = toRemove.iterator(); iter.hasNext();) {
232                 Object JavaDoc obj = (Object JavaDoc) iter.next();
233                 unlockedMap.remove(obj);
234             }
235         }
236
237         ensureMinPool();
238     }
239
240     /**
241      * Ensures there is a minimum number of valid objects in the pool.
242      *
243      */

244     private void ensureMinPool() {
245         Object JavaDoc o;
246         synchronized (unlockedMap) {
247             if ((unlockedMap.size() + lockedMap.size()) < MIN_POOL) {
248                 int num2add = MIN_POOL - unlockedMap.size();
249
250                 try {
251                     for (int i = 0; i < num2add; i++) {
252                         o = create();
253
254                         unlockedMap.put(o, new TimestampedObject(o,
255                             new Long JavaDoc(System.currentTimeMillis())));
256
257                     }
258                 } catch (Exception JavaDoc e) {
259                     m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
260                 }
261             }
262         }
263     }
264
265     /**
266      * Class to wrap up a pooled object which has a timestamp attached to
267      * it.
268      *
269      * @author Michael Bell
270      * @version $Revision: 1.1 $
271      *
272      */

273     private class TimestampedObject {
274         /**
275          * Object to be timestamp
276          */

277         private Object JavaDoc m_object;
278         /**
279          * Timestamp of object
280          */

281         private Long JavaDoc m_timestamp;
282
283         /**
284          * Constructs time stamped object with given parameters
285          *
286          * @param obj the object to be timestamped
287          * @param timestamp the timestamp of the object
288          */

289         public TimestampedObject(Object JavaDoc obj, Long JavaDoc timestamp) {
290             m_timestamp = timestamp;
291             m_object = obj;
292         }
293
294         /**
295          * Returns the object
296          *
297          * @return the object
298          */

299         public Object JavaDoc getObject() {
300             return m_object;
301         }
302
303         /**
304          * Returns the timestamp associated to the object
305          *
306          * @return the timestamp
307          */

308         public Long JavaDoc getTimestamp() {
309             return m_timestamp;
310         }
311
312         
313         /* (non-Javadoc)
314          * @see java.lang.Object#equals(java.lang.Object)
315          */

316         public boolean equals(Object JavaDoc obj) {
317             TimestampedObject to = (TimestampedObject) obj;
318
319             boolean bReturn = m_object.equals(to.getObject());
320
321             return bReturn;
322         }
323
324         /* (non-Javadoc)
325          * @see java.lang.Object#toString()
326          */

327         public String JavaDoc toString() {
328             return "(" + m_object.hashCode() + "," + m_timestamp + ")";
329         }
330     }
331 }
332
333 /**
334  * <code>Thread</code> class which controls the cleaning up of expired objects
335  * in the pool.
336  *
337  * @author Michael Bell
338  * @version $Revision: 1.1 $
339  *
340  */

341 class CleanUpThread extends Thread JavaDoc {
342     /**
343      * The pool to be cleaned up
344      */

345     private AbstractPool pool;
346     /**
347      * Time period to sleep for between runs
348      */

349     private long sleepTime;
350
351     /**
352      * Constructs a clean up thread with the given parameters
353      *
354      * @param pool the pool to be cleaned up
355      * @param sleepTime the period of time between runs
356      */

357     CleanUpThread(AbstractPool pool, long sleepTime) {
358         this.pool = pool;
359         this.sleepTime = sleepTime;
360     }
361
362     
363     /* (non-Javadoc)
364      * @see java.lang.Runnable#run()
365      */

366     public void run() {
367         while (true) {
368             try {
369                 sleep(sleepTime);
370             } catch (InterruptedException JavaDoc e) {
371                 // ignore it
372
}
373
374             pool.cleanUp();
375         }
376     }
377 }
Popular Tags