KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > base > util > cache > UtilCache


1 /*
2  * $Id: UtilCache.java 5462 2005-08-05 18:35:48Z jonesde $
3  *
4  * Copyright (c) 2001-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */

24 package org.ofbiz.base.util.cache;
25
26 import java.io.Serializable JavaDoc;
27 import java.util.Collection JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.MissingResourceException JavaDoc;
32 import java.util.ResourceBundle JavaDoc;
33 import java.util.Set JavaDoc;
34 import java.util.WeakHashMap JavaDoc;
35
36 import javolution.util.FastList;
37 import javolution.util.FastMap;
38 import javolution.util.FastSet;
39
40 import org.ofbiz.base.util.Debug;
41 import org.ofbiz.base.util.ObjectType;
42 import org.ofbiz.base.util.UtilValidate;
43
44 /**
45  * Generalized caching utility. Provides a number of caching features:
46  * <ul>
47  * <li>Limited or unlimited element capacity
48  * <li>If limited, removes elements with the LRU (Least Recently Used) algorithm
49  * <li>Keeps track of when each element was loaded into the cache
50  * <li>Using the expireTime can report whether a given element has expired
51  * <li>Counts misses and hits
52  * </ul>
53  *
54  * @author <a HREF="mailto:jonesde@ofbiz.org">David E. Jones</a>
55  * @author <a HREF="mailto:jaz@ofbiz.org">Andy Zeneski</a>
56  * @version $Rev: 5462 $
57  * @since 2.0
58  */

59 public class UtilCache implements Serializable JavaDoc {
60
61     public static final String JavaDoc module = UtilCache.class.getName();
62     
63     /** A static Map to keep track of all of the UtilCache instances. */
64     public static Map JavaDoc utilCacheTable = new WeakHashMap JavaDoc();
65
66     /** An index number appended to utilCacheTable names when there are conflicts. */
67     protected static Map JavaDoc defaultIndices = FastMap.newInstance();
68
69     /** The name of the UtilCache instance, is also the key for the instance in utilCacheTable. */
70     protected String JavaDoc name = null;
71
72     /** A hashtable containing a CacheLine object with a value and a loadTime for each element. */
73     public CacheLineTable cacheLineTable = null;
74
75     /** A count of the number of cache hits */
76     protected long hitCount = 0;
77
78     /** A count of the number of cache misses because it is not found in the cache */
79     protected long missCountNotFound = 0;
80     /** A count of the number of cache misses because it expired */
81     protected long missCountExpired = 0;
82     /** A count of the number of cache misses because it was cleared from the Soft Reference (ie garbage collection, etc) */
83     protected long missCountSoftRef = 0;
84
85     /** A count of the number of cache hits on removes */
86     protected long removeHitCount = 0;
87     /** A count of the number of cache misses on removes */
88     protected long removeMissCount = 0;
89     
90     /** The maximum number of elements in the cache.
91      * If set to 0, there will be no limit on the number of elements in the cache.
92      */

93     protected int maxSize = 0;
94     protected int maxInMemory = 0;
95
96     /** Specifies the amount of time since initial loading before an element will be reported as expired.
97      * If set to 0, elements will never expire.
98      */

99     protected long expireTime = 0;
100
101     /** Specifies whether or not to use soft references for this cache, defaults to false */
102     protected boolean useSoftReference = false;
103
104     /** Specifies whether or not to use file base stored for this cache, defautls to false */
105     protected boolean useFileSystemStore = false;
106     private String JavaDoc fileStore = "data/utilcache";
107
108     /** The set of listeners to receive notifcations when items are modidfied(either delibrately or because they were expired). */
109     protected Set JavaDoc listeners = FastSet.newInstance();
110     
111     /** Constructor which specifies the cacheName as well as the maxSize, expireTime and useSoftReference.
112      * The passed maxSize, expireTime and useSoftReference will be overridden by values from cache.properties if found.
113      * @param maxSize The maxSize member is set to this value
114      * @param expireTime The expireTime member is set to this value
115      * @param cacheName The name of the cache.
116      * @param useSoftReference Specifies whether or not to use soft references for this cache.
117      */

118     public UtilCache(String JavaDoc cacheName, int maxSize, int maxInMemory, long expireTime, boolean useSoftReference, boolean useFileSystemStore) {
119         this.maxSize = maxSize;
120         this.maxInMemory = maxInMemory;
121         this.expireTime = expireTime;
122         this.useSoftReference = useSoftReference;
123         this.useFileSystemStore = useFileSystemStore;
124         name = cacheName + this.getNextDefaultIndex(cacheName);
125
126         setPropertiesParams(cacheName);
127
128         utilCacheTable.put(name, this);
129     }
130
131     public UtilCache(String JavaDoc cacheName, int maxSize, long expireTime, boolean useSoftReference) {
132         this(cacheName, maxSize, maxSize, expireTime, useSoftReference, false);
133     }
134
135     /** Constructor which specifies the cacheName as well as the maxSize and expireTime.
136      * The passed maxSize and expireTime will be overridden by values from cache.properties if found.
137      * @param maxSize The maxSize member is set to this value
138      * @param expireTime The expireTime member is set to this value
139      * @param cacheName The name of the cache.
140      */

141     public UtilCache(String JavaDoc cacheName, int maxSize, long expireTime) {
142         this(cacheName, maxSize, expireTime, false);
143     }
144
145     /** Constructor which specifies the maxSize and expireTime.
146      * @param maxSize The maxSize member is set to this value
147      * @param expireTime The expireTime member is set to this value
148      */

149     public UtilCache(int maxSize, long expireTime) {
150         this.useSoftReference = false;
151         this.maxSize = maxSize;
152         this.expireTime = expireTime;
153         String JavaDoc name = "specified" + this.getNextDefaultIndex("specified");
154
155         setPropertiesParams(name);
156
157         utilCacheTable.put(name, this);
158     }
159
160     /** This constructor takes a name for the cache, puts itself in the utilCacheTable.
161      * It also uses the cacheName to lookup the initialization parameters from cache.properties.
162      * @param cacheName The name of the cache.
163      */

164     public UtilCache(String JavaDoc cacheName, boolean useSoftReference) {
165         name = cacheName + this.getNextDefaultIndex(cacheName);
166         this.useSoftReference = useSoftReference;
167
168         setPropertiesParams("default");
169         setPropertiesParams(cacheName);
170
171         utilCacheTable.put(name, this);
172     }
173
174     /** This constructor takes a name for the cache, puts itself in the utilCacheTable.
175      * It also uses the cacheName to lookup the initialization parameters from cache.properties.
176      * @param cacheName The name of the cache.
177      */

178     public UtilCache(String JavaDoc cacheName) {
179         name = cacheName + this.getNextDefaultIndex(cacheName);
180
181         setPropertiesParams("default");
182         setPropertiesParams(cacheName);
183
184         utilCacheTable.put(name, this);
185     }
186
187     /** Default constructor, all members stay at default values as defined in cache.properties, or the defaults in this file if cache.properties is not found, or there are no 'default' entries in it. */
188     public UtilCache() {
189         setPropertiesParams("default");
190
191         name = "default" + this.getNextDefaultIndex("default");
192         utilCacheTable.put(name, this);
193     }
194
195     protected String JavaDoc getNextDefaultIndex(String JavaDoc cacheName) {
196         Integer JavaDoc curInd = (Integer JavaDoc) UtilCache.defaultIndices.get(cacheName);
197
198         if (curInd == null) {
199             UtilCache.defaultIndices.put(cacheName, new Integer JavaDoc(1));
200             return "";
201         } else {
202             UtilCache.defaultIndices.put(cacheName, new Integer JavaDoc(curInd.intValue() + 1));
203             return Integer.toString(curInd.intValue() + 1);
204         }
205     }
206
207     public static String JavaDoc getPropertyParam(ResourceBundle JavaDoc res, String JavaDoc[] propNames, String JavaDoc parameter) {
208         String JavaDoc value = null;
209         for (int i = 0; i < propNames.length && value == null; i++ ) {
210             try {
211                 value = res.getString(propNames[i] + '.' + parameter);
212             } catch (MissingResourceException JavaDoc e) {}
213         }
214         // don't need this, just return null
215
//if (value == null) {
216
// throw new MissingResourceException("Can't find resource for bundle", res.getClass().getName(), Arrays.asList(propNames) + "." + parameter);
217
//}
218
return value;
219     }
220
221     protected void setPropertiesParams(String JavaDoc cacheName) {
222         setPropertiesParams(new String JavaDoc[] {cacheName});
223     }
224
225     public void setPropertiesParams(String JavaDoc[] propNames) {
226         ResourceBundle JavaDoc res = ResourceBundle.getBundle("cache");
227
228         if (res != null) {
229             try {
230                 String JavaDoc value = getPropertyParam(res, propNames, "maxSize");
231                 if (UtilValidate.isNotEmpty(value)) {
232                     Integer JavaDoc intValue = new Integer JavaDoc(value);
233                     if (intValue != null) {
234                         this.maxSize = intValue.intValue();
235                     }
236                 }
237             } catch (Exception JavaDoc e) {
238                 Debug.logWarning(e, "Error getting maxSize value from cache.properties file for propNames: " + propNames, module);
239             }
240             try {
241                 String JavaDoc value = getPropertyParam(res, propNames, "maxInMemory");
242                 if (UtilValidate.isNotEmpty(value)) {
243                     Integer JavaDoc intValue = new Integer JavaDoc(value);
244                     if (intValue != null) {
245                         this.maxInMemory = intValue.intValue();
246                     }
247                 }
248             } catch (Exception JavaDoc e) {
249                 Debug.logWarning(e, "Error getting maxInMemory value from cache.properties file for propNames: " + propNames, module);
250             }
251             try {
252                 String JavaDoc value = getPropertyParam(res, propNames, "expireTime");
253                 if (UtilValidate.isNotEmpty(value)) {
254                     Long JavaDoc longValue = new Long JavaDoc(value);
255                     if (longValue != null) {
256                         this.expireTime = longValue.longValue();
257                     }
258                 }
259             } catch (Exception JavaDoc e) {
260                 Debug.logWarning(e, "Error getting expireTime value from cache.properties file for propNames: " + propNames, module);
261             }
262             try {
263                 String JavaDoc value = getPropertyParam(res, propNames, "useSoftReference");
264                 if (value != null) {
265                     useSoftReference = "true".equals(value);
266                 }
267             } catch (Exception JavaDoc e) {
268                 Debug.logWarning(e, "Error getting useSoftReference value from cache.properties file for propNames: " + propNames, module);
269             }
270             try {
271                 String JavaDoc value = getPropertyParam(res, propNames, "useFileSystemStore");
272                 if (value != null) {
273                     useFileSystemStore = "true".equals(value);
274                 }
275             } catch (Exception JavaDoc e) {
276                 Debug.logWarning(e, "Error getting useFileSystemStore value from cache.properties file for propNames: " + propNames, module);
277             }
278             try {
279                 String JavaDoc value = res.getString("cache.file.store");
280                 if (value != null) {
281                     fileStore = value;
282                 }
283             } catch (Exception JavaDoc e) {
284                 Debug.logWarning(e, "Error getting cache.file.store value from cache.properties file for propNames: " + propNames, module);
285             }
286         }
287
288         int maxMemSize = this.maxInMemory;
289         if (maxMemSize == 0) maxMemSize = (int) maxSize;
290         this.cacheLineTable = new CacheLineTable(this.fileStore, this.name, this.useFileSystemStore, maxMemSize);
291     }
292
293     /** Puts or loads the passed element into the cache
294      * @param key The key for the element, used to reference it in the hastables and LRU linked list
295      * @param value The value of the element
296      */

297     public synchronized Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
298         return put(key, value, expireTime);
299     }
300
301     /** Puts or loads the passed element into the cache
302      * @param key The key for the element, used to reference it in the hastables and LRU linked list
303      * @param value The value of the element
304      * @param expireTime how long to keep this key in the cache
305      */

306     public synchronized Object JavaDoc put(Object JavaDoc key, Object JavaDoc value, long expireTime) {
307         if (key == null) {
308             if (Debug.verboseOn()) Debug.logVerbose("In UtilCache tried to put with null key, using NullObject for cache " + this.getName(), module);
309             key = ObjectType.NULL;
310         }
311         CacheLine oldCacheLine;
312         if (expireTime > 0) {
313             oldCacheLine = (CacheLine) cacheLineTable.put(key, new CacheLine(value, useSoftReference, System.currentTimeMillis(), expireTime));
314         } else {
315             oldCacheLine = (CacheLine) cacheLineTable.put(key, new CacheLine(value, useSoftReference, expireTime));
316         }
317
318         if (oldCacheLine == null) {
319             noteAddition(key, value);
320             return null;
321         } else {
322             noteUpdate(key, value, oldCacheLine.getValue());
323             return oldCacheLine.getValue();
324         }
325
326     }
327
328     /** Gets an element from the cache according to the specified key.
329      * If the requested element hasExpired, it is removed before it is looked up which causes the function to return null.
330      * @param key The key for the element, used to reference it in the hastables and LRU linked list
331      * @return The value of the element specified by the key
332      */

333     public Object JavaDoc get(Object JavaDoc key) {
334         CacheLine line = getInternal(key, true);
335         if (line == null) {
336             return null;
337         } else {
338             return line.getValue();
339         }
340     }
341
342     protected CacheLine getInternalNoCheck(Object JavaDoc key) {
343         if (key == null) {
344             if (Debug.verboseOn()) Debug.logVerbose("In UtilCache tried to get with null key, using NullObject for cache " + this.getName(), module);
345             key = ObjectType.NULL;
346         }
347         CacheLine line = (CacheLine) cacheLineTable.get(key);
348         return line;
349     }
350     
351     protected CacheLine getInternal(Object JavaDoc key, boolean countGet) {
352         CacheLine line = getInternalNoCheck(key);
353         if (line == null) {
354             if (countGet) missCountNotFound++;
355         } else if (line.softReferenceCleared()) {
356             removeInternal(key, false);
357             if (countGet) missCountSoftRef++;
358             line = null;
359         } else if (this.hasExpired(line)) {
360             // note that print.info in debug.properties cannot be checked through UtilProperties here, it would cause infinite recursion...
361
// if (Debug.infoOn()) Debug.logInfo("Element has expired with key " + key, module);
362
removeInternal(key, false);
363             if (countGet) missCountExpired++;
364             line = null;
365         } else {
366             if (countGet) hitCount++;
367         }
368         return line;
369     }
370
371     public List JavaDoc values() {
372         if (cacheLineTable == null) {
373             return null;
374         }
375         
376         List JavaDoc valuesList = FastList.newInstance();
377         Iterator JavaDoc i = cacheLineTable.keySet().iterator();
378         while (i.hasNext()) {
379             Object JavaDoc key = i.next();
380             valuesList.add(this.get(key));
381         }
382
383         return valuesList;
384     }
385
386     public long getSizeInBytes() {
387         long totalSize = 0;
388         Iterator JavaDoc i = cacheLineTable.values().iterator();
389         while (i.hasNext()) {
390             totalSize += ((CacheLine) i.next()).getSizeInBytes();
391         }
392         return totalSize;
393     }
394
395     /** Removes an element from the cache according to the specified key
396      * @param key The key for the element, used to reference it in the hastables and LRU linked list
397      * @return The value of the removed element specified by the key
398      */

399     public synchronized Object JavaDoc remove(Object JavaDoc key) {
400         return this.removeInternal(key, true);
401     }
402     
403     /** This is used for internal remove calls because we only want to count external calls */
404     protected synchronized Object JavaDoc removeInternal(Object JavaDoc key, boolean countRemove) {
405         if (key == null) {
406             if (Debug.verboseOn()) Debug.logVerbose("In UtilCache tried to remove with null key, using NullObject for cache " + this.getName(), module);
407             key = ObjectType.NULL;
408         }
409         CacheLine line = (CacheLine) cacheLineTable.remove(key);
410         if (line != null) {
411             noteRemoval(key, line.getValue());
412             if (countRemove) this.removeHitCount++;
413             return line.getValue();
414         } else {
415             if (countRemove) this.removeMissCount++;
416             return null;
417         }
418     }
419
420     /** Removes all elements from this cache */
421     public synchronized void clear() {
422         Iterator JavaDoc it = cacheLineTable.keySet().iterator();
423         while (it.hasNext()) {
424             Object JavaDoc key = it.next();
425             CacheLine line = getInternalNoCheck(key);
426             noteRemoval(key, line == null ? null : line.getValue());
427         }
428         cacheLineTable.clear();
429         clearCounters();
430     }
431
432     /** Removes all elements from this cache */
433     public static void clearAllCaches() {
434         Iterator JavaDoc entries = utilCacheTable.entrySet().iterator();
435         while (entries.hasNext()) {
436             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entries.next();
437             UtilCache utilCache = (UtilCache) entry.getValue();
438             utilCache.clear();
439         }
440     }
441
442     /** Getter for the name of the UtilCache instance.
443      * @return The name of the instance
444      */

445     public String JavaDoc getName() {
446         return this.name;
447     }
448
449     /** Returns the number of successful hits on the cache
450      * @return The number of successful cache hits
451      */

452     public long getHitCount() {
453         return this.hitCount;
454     }
455
456     /** Returns the number of cache misses from entries that are not found in the cache
457      * @return The number of cache misses
458      */

459     public long getMissCountNotFound() {
460         return this.missCountNotFound;
461     }
462
463     /** Returns the number of cache misses from entries that are expired
464      * @return The number of cache misses
465      */

466     public long getMissCountExpired() {
467         return this.missCountExpired;
468     }
469
470     /** Returns the number of cache misses from entries that are have had the soft reference cleared out (by garbage collector and such)
471      * @return The number of cache misses
472      */

473     public long getMissCountSoftRef() {
474         return this.missCountSoftRef;
475     }
476
477     /** Returns the number of cache misses caused by any reason
478      * @return The number of cache misses
479      */

480     public long getMissCountTotal() {
481         return this.missCountSoftRef + this.missCountNotFound + this.missCountExpired;
482     }
483     
484     public long getRemoveHitCount() {
485         return this.removeHitCount;
486     }
487     
488     public long getRemoveMissCount() {
489         return this.removeMissCount;
490     }
491
492     /** Clears the hit and miss counters
493      */

494     public void clearCounters() {
495         this.hitCount = 0;
496         this.missCountNotFound = 0;
497         this.missCountExpired = 0;
498         this.missCountSoftRef = 0;
499         this.removeHitCount = 0;
500         this.removeMissCount = 0;
501     }
502
503     /** Sets the maximum number of elements in the cache.
504      * If 0, there is no maximum.
505      * @param maxSize The maximum number of elements in the cache
506      */

507     public void setMaxSize(int maxSize) {
508         cacheLineTable.setLru((int) maxSize);
509         this.maxSize = maxSize;
510     }
511
512     /** Returns the current maximum number of elements in the cache
513      * @return The maximum number of elements in the cache
514      */

515     public long getMaxSize() {
516         return maxSize;
517     }
518
519     /** Sets the expire time for the cache elements.
520      * If 0, elements never expire.
521      * @param expireTime The expire time for the cache elements
522      */

523     public void setExpireTime(long expireTime) {
524         // if expire time was <= 0 and is now greater, fill expire table now
525
if (this.expireTime <= 0 && expireTime > 0) {
526             long currentTime = System.currentTimeMillis();
527             Iterator JavaDoc values = cacheLineTable.values().iterator();
528             while (values.hasNext()) {
529                 CacheLine line = (CacheLine) values.next();
530                 line.loadTime = currentTime;
531             }
532         } else if (this.expireTime <= 0 && expireTime > 0) {
533             // if expire time was > 0 and is now <=, do nothing, just leave the load times in place, won't hurt anything...
534
}
535
536         this.expireTime = expireTime;
537     }
538
539     /** return the current expire time for the cache elements
540      * @return The expire time for the cache elements
541      */

542     public long getExpireTime() {
543         return expireTime;
544     }
545
546     /** Set whether or not the cache lines should use a soft reference to the data */
547     public void setUseSoftReference(boolean useSoftReference) {
548         if (this.useSoftReference != useSoftReference) {
549             this.useSoftReference = useSoftReference;
550             Iterator JavaDoc values = cacheLineTable.values().iterator();
551             while (values.hasNext()) {
552                 CacheLine line = (CacheLine) values.next();
553                 line.setUseSoftReference(useSoftReference);
554             }
555         }
556     }
557
558     /** Return whether or not the cache lines should use a soft reference to the data */
559     public boolean getUseSoftReference() {
560         return this.useSoftReference;
561     }
562     
563     public boolean getUseFileSystemStore() {
564         return this.useFileSystemStore;
565     }
566
567     /** Returns the number of elements currently in the cache
568      * @return The number of elements currently in the cache
569      */

570     public long size() {
571         return cacheLineTable.size();
572     }
573
574     /** Returns a boolean specifying whether or not an element with the specified key is in the cache.
575      * If the requested element hasExpired, it is removed before it is looked up which causes the function to return false.
576      * @param key The key for the element, used to reference it in the hastables and LRU linked list
577      * @return True is the cache contains an element corresponding to the specified key, otherwise false
578      */

579     public boolean containsKey(Object JavaDoc key) {
580         CacheLine line = getInternal(key, false);
581         if (line != null) {
582             return true;
583         } else {
584             return false;
585         }
586     }
587     
588     /**
589      * NOTE: this returns an unmodifiable copy of the keySet, so removing from here won't have an effect,
590      * and calling a remove while iterating through the set will not cause a concurrent modification exception.
591      * This behavior is necessary for now for the persisted cache feature.
592      */

593     public Set JavaDoc getCacheLineKeys() {
594         return cacheLineTable.keySet();
595     }
596
597     public Collection JavaDoc getCacheLineValues() {
598         return cacheLineTable.values();
599     }
600
601     /** Returns a boolean specifying whether or not the element corresponding to the key has expired.
602      * Only returns true if element is in cache and has expired. Error conditions return false, if no expireTable entry, returns true.
603      * Always returns false if expireTime <= 0.
604      * Also, if SoftReference in the CacheLine object has been cleared by the gc return true.
605      *
606      * @param key The key for the element, used to reference it in the hastables and LRU linked list
607      * @return True is the element corresponding to the specified key has expired, otherwise false
608      */

609     public boolean hasExpired(Object JavaDoc key) {
610         CacheLine line = getInternalNoCheck(key);
611         return hasExpired(line);
612     }
613
614     protected boolean hasExpired(CacheLine line) {
615         if (line == null) return false;
616
617         // check this BEFORE checking to see if expireTime <= 0, ie if time expiration is enabled
618
// check to see if we are using softReference first, slight performance increase
619
if (line.softReferenceCleared()) return true;
620         
621         // check if expireTime <= 0, ie if time expiration is not enabled
622
if (line.expireTime <= 0) return false;
623
624         // check if the time was saved for this; if the time was not saved, but expire time is > 0, then we don't know when it was saved so expire it to be safe
625
if (line.loadTime <= 0) return true;
626         
627         if ((line.loadTime + line.expireTime) < System.currentTimeMillis()) {
628             return true;
629         } else {
630             return false;
631         }
632     }
633
634     /** Clears all expired cache entries; also clear any cache entries where the SoftReference in the CacheLine object has been cleared by the gc */
635     public void clearExpired() {
636         Iterator JavaDoc keys = cacheLineTable.keySet().iterator();
637         while (keys.hasNext()) {
638             Object JavaDoc key = keys.next();
639             if (hasExpired(key)) {
640                 removeInternal(key, false);
641             }
642         }
643     }
644
645     /** Send a key addition event to all registered listeners */
646     protected void noteAddition(Object JavaDoc key, Object JavaDoc newValue) {
647         synchronized (listeners) {
648             Iterator JavaDoc it = listeners.iterator();
649             while (it.hasNext()) {
650                 CacheListener listener = (CacheListener) it.next();
651                 listener.noteKeyAddition(this, key, newValue);
652             }
653         }
654     }
655
656     /** Send a key removal event to all registered listeners */
657     protected void noteRemoval(Object JavaDoc key, Object JavaDoc oldValue) {
658         synchronized (listeners) {
659             Iterator JavaDoc it = listeners.iterator();
660             while (it.hasNext()) {
661                 CacheListener listener = (CacheListener) it.next();
662                 listener.noteKeyRemoval(this, key, oldValue);
663             }
664         }
665     }
666
667     /** Send a key update event to all registered listeners */
668     protected void noteUpdate(Object JavaDoc key, Object JavaDoc newValue, Object JavaDoc oldValue) {
669         synchronized (listeners) {
670             Iterator JavaDoc it = listeners.iterator();
671             while (it.hasNext()) {
672                 CacheListener listener = (CacheListener) it.next();
673                 listener.noteKeyUpdate(this, key, newValue, oldValue);
674             }
675         }
676     }
677
678     /** Adds an event listener for key removals */
679     public void addListener(CacheListener listener) {
680         synchronized (listeners) {
681             listeners.add(listener);
682         }
683     }
684     
685     /** Removes an event listener for key removals */
686     public void removeListener(CacheListener listener) {
687         synchronized (listeners) {
688             listeners.remove(listener);
689         }
690     }
691     
692     /** Clears all expired cache entries from all caches */
693     public static void clearExpiredFromAllCaches() {
694         Iterator JavaDoc entries = utilCacheTable.entrySet().iterator();
695         while (entries.hasNext()) {
696             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entries.next();
697             UtilCache utilCache = (UtilCache) entry.getValue();
698             utilCache.clearExpired();
699         }
700     }
701     
702     /** Checks for a non-expired key in a specific cache */
703     public static boolean validKey(String JavaDoc cacheName, Object JavaDoc key) {
704         UtilCache cache = (UtilCache) utilCacheTable.get(cacheName);
705         if (cache != null) {
706             if (cache.containsKey(key))
707                 return true;
708         }
709         return false;
710     }
711     
712     public static void clearCachesThatStartWith(String JavaDoc startsWith) {
713         synchronized (utilCacheTable) {
714             Iterator JavaDoc it = utilCacheTable.entrySet().iterator();
715             while (it.hasNext()) {
716                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
717                 String JavaDoc name = (String JavaDoc) entry.getKey();
718                 if (name.startsWith(startsWith)) {
719                     UtilCache cache = (UtilCache) entry.getValue();
720                     cache.clear();
721                 }
722             }
723         }
724     }
725
726     public static void clearCache(String JavaDoc cacheName) {
727         synchronized (UtilCache.utilCacheTable) {
728             UtilCache cache = (UtilCache) UtilCache.utilCacheTable.get(cacheName);
729             if (cache == null) return;
730             cache.clear();
731         }
732     }
733 }
734
Popular Tags