PassiveMemoryCache.java

biz/hammurapi/cache/PassiveMemoryCache.java

Violations

Inspector Message Severity Location
Java Inspector 048 Copyrights information should be present in each file. 1
Java Inspector 082 Parenthesis are redundant. 2 99:67
Java Inspector 082 Parenthesis are redundant. 2 169:37
Java Inspector 089 Constructor is not properly documented 2 58:17
Java Inspector 089 Undocumented parameter value 2 58:17
Java Inspector 089 Undocumented parameter time 2 58:17
Java Inspector 089 Parameter expires is not documented 2 58:17
Java Inspector 089 Javadoc contains tag for non-existent parameter referent 2 58:17
Java Inspector 089 Javadoc contains tag for non-existent parameter q 2 58:17
Java Inspector 089 Undocumented method 2 83:17
Java Inspector 089 Constructor is not properly documented 2 116:9
Java Inspector 089 Undocumented parameter producer 2 116:9
Java Inspector 089 Undocumented parameter fallBack 2 116:9
Java Inspector 089 Undocumented parameter cleanupInterval 2 116:9
Java Inspector 089 Undocumented method 2 132:9
Java Inspector 089 Undocumented method 2 158:9
Java Inspector 089 Undocumented method 2 178:49
Java Inspector 089 Undocumented method 2 182:49
Java Inspector 089 Undocumented method 2 186:49
Java Inspector 089 Undocumented method 2 218:9
Java Inspector 089 Undocumented method 2 228:9
Java Inspector 089 Undocumented method 2 235:9
Java Inspector 089 Undocumented method 2 250:9
Java Inspector 089 Undocumented method 2 257:9
Java Inspector 089 Undocumented method 2 264:9
Java Inspector 089 Undocumented method 2 290:9
Java Inspector 089 Undocumented method 2 294:9
Java Inspector 089 Undocumented method 2 299:9
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 109:49
Java Inspector 051 It is good practice to call in any case super() in a constructor. 3 76:17

Source code

1/*
2 * hgcommons 9
3 * Hammurapi Group Common Library
4 * Copyright (C) 2003 Hammurapi Group
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
21 * e-Mail: support@hammurapi.biz
22 */
23package biz.hammurapi.cache;
24
25import java.lang.ref.SoftReference;
26import java.util.HashMap;
27import java.util.HashSet;
28import java.util.Iterator;
29import java.util.Map;
30import java.util.Set;
31
32import biz.hammurapi.config.ConfigurationException;
33import biz.hammurapi.util.Acceptor;
34
35
36/**
37 * Memory sensitive cache. Uses soft references to cache objects.
38 * Doesn't create helper threads - housekeepeng happens on every 'cleanupInterval' get() invocation.
39 * @author Pavel Vlasov
40 * @version $Revision: 1.3 $
41 */
42public class PassiveMemoryCache extends AbstractProducer implements Cache {
43 private Map cache=new HashMap();
44 private Producer producer;
45 private Cache fallBack;
46 private int cleanupInterval;
47 private int cleanupCounter;
48
49 private class CacheReference extends SoftReference {
50 private long expires;
51 private long time;
52
53 /**
54 * @param referent
55 * @param q
56 * @param expires
57 */
58 public CacheReference(Object value, long time, long expires) {
59 super(value);
60 this.expires=expires;
61 this.time=time;
62 }
63 }
64
65 /**
66 * Used as entry if fallBack cache is used.
67 * @author Pavel Vlasov
68 * @version $Revision: 1.3 $
69 */
70 private class FallBackEntry {
71 Object value;
72 private long expires;
73 private long time;
74 private Object key;
75
76 FallBackEntry(Object key, Object value, long time, long expires) {
77 this.key=key;
78 this.value=value;
79 this.expires=expires;
80 this.time=time;
81 }
82
83 protected void finalize() throws Throwable {
84 if (fallBack.isActive() && (expires<=0 || System.currentTimeMillis()<expires)) {
85 fallBack.put(key, value, time, expires);
86 }
87
88 super.finalize();
89 }
90 }
91
92 private void cleanup() {
93 long now=System.currentTimeMillis();
94 synchronized (cache) {
95 Iterator it=cache.entrySet().iterator();
96 while (it.hasNext()) {
97 Map.Entry entry=(Map.Entry) it.next();
98 CacheReference cacheReference = (CacheReference) entry.getValue();
99 if (cacheReference.get()==null || (cacheReference.expires>0 && cacheReference.expires<now)) {
100 it.remove();
101 }
102 }
103 }
104 cleanupCounter=0;
105 }
106
107 private void checkShutdown() {
108 if (shutDown) {
109 throw new IllegalStateException("Shut down");
110 }
111 }
112
113 /**
114 *
115 */
116 public PassiveMemoryCache(Producer producer, Cache fallBack, int cleanupInterval) {
117 super();
118
119 this.producer=producer;
120 if (producer!=null) {
121 producer.addCache(this);
122 }
123
124 this.fallBack=fallBack;
125 if (fallBack!=null) {
126 addCache(fallBack);
127 }
128
129 this.cleanupInterval=cleanupInterval;
130 }
131
132 public void put(Object key, Object value, long time, long expirationTime) {
133 checkShutdown();
134 synchronized (cache) {
135 cache.put(key, new CacheReference(toValue(key, value, time, expirationTime), time, expirationTime));
136 }
137 }
138
139 /**
140 * @param key
141 * @param value
142 * @param expirationTime
143 * @return
144 */
145 private Object toValue(Object key, Object value, long time, long expirationTime) {
146 return fallBack==null ? value : new FallBackEntry(key, value, time, expirationTime);
147 }
148
149 private Object fromValue(Object object) {
150 if (object instanceof FallBackEntry) {
151 return ((FallBackEntry) object).value;
152 }
153 return object;
154 }
155
156
157
158 public Entry get(Object key) {
159 checkShutdown();
160 if (cleanupInterval>0 && cleanupCounter++ > cleanupInterval) {
161 cleanup();
162 }
163
164 synchronized (cache) {
165 CacheReference cr=(CacheReference) cache.get(key);
166 long now = System.currentTimeMillis();
167 boolean doFallBack=true;
168 if (cr!=null) {
169 if ((cr.expires>0 && cr.expires<now) || cr.get()==null) {
170 cache.remove(key);
171 doFallBack=false;
172 } else {
173 final Object o=fromValue(cr.get());
174 final long et=cr.expires;
175 final long time=cr.time;
176 return new Entry() {
177
178 public long getExpirationTime() {
179 return et;
180 }
181
182 public long getTime() {
183 return time;
184 }
185
186 public Object get() {
187 return o;
188 }
189
190 };
191 }
192 }
193
194 if (doFallBack && fallBack!=null) {
195 Entry entry = fallBack.get(key);
196 if (entry!=null) {
197 cache.put(key, new CacheReference(toValue(key, entry.get(), entry.getTime(), entry.getExpirationTime()), entry.getTime(), entry.getExpirationTime()));
198 return entry;
199 }
200 }
201
202 if (key instanceof ProducingKey) {
203 Entry entry = ((ProducingKey) key).get();
204 cache.put(key, new CacheReference(toValue(key, entry.get(), entry.getTime(), entry.getExpirationTime()), entry.getTime(), entry.getExpirationTime()));
205 return entry;
206 }
207
208 if (producer!=null) {
209 Entry entry = producer.get(key);
210 cache.put(key, new CacheReference(toValue(key, entry.get(), entry.getTime(), entry.getExpirationTime()), entry.getTime(), entry.getExpirationTime()));
211 return entry;
212 }
213
214 return null;
215 }
216 }
217
218 public void clear() {
219 synchronized (cache) {
220 cache.clear();
221
222 if (fallBack!=null) {
223 fallBack.clear();
224 }
225 }
226 }
227
228 public void remove(Object key) {
229 synchronized (cache) {
230 cache.remove(key);
231 }
232 onRemove(key);
233 }
234
235 public void remove(Acceptor acceptor) {
236 synchronized (cache) {
237 Iterator it=cache.keySet().iterator();
238 while (it.hasNext()) {
239 Object key=it.next();
240 if (acceptor.accept(key)) {
241 it.remove();
242 onRemove(key);
243 }
244 }
245 }
246 }
247
248 private boolean shutDown=false;
249
250 public void stop() {
251 if (!shutDown) {
252 cache.clear();
253 shutDown=true;
254 }
255 }
256
257 protected void finalize() throws Throwable {
258 if (isActive()) {
259 stop();
260 }
261 super.finalize();
262 }
263
264 public Set keySet() {
265 HashSet ret = new HashSet();
266 synchronized (cache) {
267 ret.addAll(cache.keySet());
268 }
269
270 if (producer!=null) {
271 Set pkeys=producer.keySet();
272 if (pkeys!=null) {
273 ret.addAll(pkeys);
274 }
275 }
276
277 if (fallBack!=null) {
278 Set fkeys=fallBack.keySet();
279 if (fkeys!=null) {
280 ret.addAll(fkeys);
281 }
282 }
283
284 return ret;
285 }
286
287 /* (non-Javadoc)
288 * @see biz.hammurapi.cache.Cache#isActive()
289 */
290 public boolean isActive() {
291 return !shutDown;
292 }
293
294 public void start() throws ConfigurationException {
295 // Nothing
296
297 }
298
299 public void setOwner(Object owner) {
300 // Nothing
301
302 }
303}
304