KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > shiftone > cache > decorator > soft > SoftCache


1 package org.shiftone.cache.decorator.soft;
2
3
4
5 import org.shiftone.cache.Cache;
6 import org.shiftone.cache.util.Log;
7 import org.shiftone.cache.util.reaper.ReapableCache;
8
9 import java.lang.ref.Reference JavaDoc;
10 import java.lang.ref.ReferenceQueue JavaDoc;
11 import java.lang.ref.SoftReference JavaDoc;
12
13
14 /**
15  * Memory sensitive cache.
16  * <p>
17  * This cache implementation proxies to a cache that was passed to it's constructor.
18  * When objects are added to the cache, the object wrapped in a SoftReference,
19  * and then the Reference is added to the delegate cache.
20  * <p>
21  * Once a SoftCache is created for a cache, the SoftCache should always be used to
22  * access this cache. Using the original cache directly is not recommended.
23  * <p>
24  * Note that there are <n>no guarantees</b> as to how long objects you put in cache will remain
25  * there. This is entirely at the digression of the garbage collector, which tends to
26  * be hasty about freeing up memory.
27  *
28  * @author <a HREF="mailto:jeff@shiftone.org">Jeff Drost</a>
29  * @version $Revision: 1.5 $
30  */

31 public class SoftCache implements Cache, ReapableCache
32 {
33
34     private static final Log LOG = new Log(SoftCache.class);
35
36     //private static CacheReaper reaper = CacheReaper.getReaper();
37
private final ReferenceQueue JavaDoc referenceQueue = new ReferenceQueue JavaDoc();
38     private final Cache cache;
39
40     public SoftCache(Cache cache)
41     {
42
43         if (cache instanceof SoftCache)
44         {
45             throw new UnsupportedOperationException JavaDoc("SoftCache should not delegate to SoftCache");
46         }
47
48         this.cache = cache;
49
50         // reaper.register(this);
51
}
52
53
54     public void addObject(Object JavaDoc userKey, Object JavaDoc cacheObject)
55     {
56
57         // thanks to JD Evora for the bug report
58
cache.addObject(userKey, new KeyReference(userKey, cacheObject, referenceQueue));
59     }
60
61
62     /**
63      * Gets a soft reference out of the underlying cache implementation, and then
64      * returns the value held by the reference.
65      */

66     public Object JavaDoc getObject(Object JavaDoc key)
67     {
68
69         Object JavaDoc result = null;
70         Reference JavaDoc ref = null;
71
72         ref = (Reference JavaDoc) cache.getObject(key);
73
74         if (ref != null)
75         {
76             result = ref.get();
77
78             if (result == null)
79             {
80                 LOG.debug("reference found in cache but GC removed object");
81                 cache.remove(key);
82             }
83         }
84
85         return result;
86     }
87
88
89     public final void remove(Object JavaDoc key)
90     {
91         cache.remove(key);
92     }
93
94
95     public final int size()
96     {
97         return cache.size();
98     }
99
100
101     public final void clear()
102     {
103         cache.clear();
104     }
105
106
107     /**
108      * Cleans all cache elements out that have had their objects collected by the GC.
109      */

110     public synchronized void removeExpiredElements()
111     {
112
113         Reference JavaDoc ref = null;
114         Object JavaDoc key = null;
115         int removeCount = 0;
116
117         while ((ref = referenceQueue.poll()) != null)
118         {
119             key = ((KeyReference) ref).getKey();
120
121             cache.remove(key);
122
123             removeCount++;
124         }
125
126         LOG.debug(this + " removeExpiredElements() removed - " + removeCount + " refs - " + size() + " left");
127     }
128
129
130     public final String JavaDoc toString()
131     {
132         return "SoftCache->" + cache;
133     }
134
135
136     /**
137      * Class KeyReference
138      *
139      *
140      * @author <a HREF="mailto:jeff@shiftone.org">Jeff Drost</a>
141      * @version $Revision: 1.5 $
142      */

143     class KeyReference extends SoftReference JavaDoc
144     {
145
146         private Object JavaDoc key = null;
147
148         /**
149          * Constructor KeyReference
150          *
151          *
152          * @param key
153          * @param cacheObject
154          * @param referenceQueue
155          */

156         public KeyReference(Object JavaDoc key, Object JavaDoc cacheObject, ReferenceQueue JavaDoc referenceQueue)
157         {
158
159             super(cacheObject, referenceQueue);
160
161             this.key = key;
162         }
163
164
165         /**
166          * Method getKey
167          */

168         Object JavaDoc getKey()
169         {
170             return key;
171         }
172     }
173 }
174
Popular Tags