KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > opensymphony > oscache > base > CacheEntry


1 /*
2  * Copyright (c) 2002-2003 by OpenSymphony
3  * All rights reserved.
4  */

5 package com.opensymphony.oscache.base;
6
7 import com.opensymphony.oscache.web.filter.ResponseContent;
8
9 import java.io.Serializable JavaDoc;
10
11 import java.util.Collection JavaDoc;
12 import java.util.HashSet JavaDoc;
13 import java.util.Set JavaDoc;
14
15 /**
16  * A CacheEntry instance represents one entry in the cache. It holds the object that
17  * is being cached, along with a host of information about that entry such as the
18  * cache key, the time it was cached, whether the entry has been flushed or not and
19  * the groups it belongs to.
20  *
21  * @version $Revision: 1.1 $
22  * @author <a HREF="mailto:mike@atlassian.com">Mike Cannon-Brookes</a>
23  * @author <a HREF="mailto:tgochenour@peregrine.com">Todd Gochenour</a>
24  * @author <a HREF="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
25  */

26 public class CacheEntry implements Serializable JavaDoc {
27     /**
28      * Default initialization value for the creation time and the last
29      * update time. This is a placeholder that indicates the value has
30      * not been set yet.
31      */

32     private static final byte NOT_YET = -1;
33
34     /**
35      * Specifying this as the refresh period for the
36      * {@link #needsRefresh(int)} method will ensure
37      * an entry does not become stale until it is
38      * either explicitly flushed or a custom refresh
39      * policy causes the entry to expire.
40      */

41     public static final int INDEFINITE_EXPIRY = -1;
42
43     /**
44      * The entry refresh policy object to use for this cache entry. This is optional.
45      */

46     private EntryRefreshPolicy policy = null;
47
48     /**
49      * The actual content that is being cached. Wherever possible this object
50      * should be serializable. This allows <code>PersistenceListener</code>s
51      * to serialize the cache entries to disk or database.
52      */

53     private Object JavaDoc content = null;
54
55     /**
56      * The set of cache groups that this cache entry belongs to, if any.
57      */

58     private Set JavaDoc groups = null;
59
60     /**
61      * The unique cache key for this entry
62      */

63     private String JavaDoc key;
64
65     /**
66      * <code>true</code> if this entry was flushed
67      */

68     private boolean wasFlushed = false;
69
70     /**
71      * The time this entry was created.
72      */

73     private long created = NOT_YET;
74
75     /**
76      * The time this emtry was last updated.
77      */

78     private long lastUpdate = NOT_YET;
79
80     /**
81      * Construct a new CacheEntry using the key provided.
82      *
83      * @param key The key of this CacheEntry
84      */

85     public CacheEntry(String JavaDoc key) {
86         this(key, null);
87     }
88
89     /**
90      * Construct a CacheEntry.
91      *
92      * @param key The unique key for this <code>CacheEntry</code>.
93      * @param policy Object that implements refresh policy logic. This parameter
94      * is optional.
95      */

96     public CacheEntry(String JavaDoc key, EntryRefreshPolicy policy) {
97         this(key, policy, null);
98     }
99
100     /**
101      * Construct a CacheEntry.
102      *
103      * @param key The unique key for this <code>CacheEntry</code>.
104      * @param policy The object that implements the refresh policy logic. This
105      * parameter is optional.
106      * @param groups The groups that this <code>CacheEntry</code> belongs to. This
107      * parameter is optional.
108      */

109     public CacheEntry(String JavaDoc key, EntryRefreshPolicy policy, String JavaDoc[] groups) {
110         this.key = key;
111
112         if (groups != null) {
113             this.groups = new HashSet JavaDoc(groups.length);
114
115             for (int i = 0; i < groups.length; i++) {
116                 this.groups.add(groups[i]);
117             }
118         }
119
120         this.policy = policy;
121         this.created = System.currentTimeMillis();
122     }
123
124     /**
125      * Sets the actual content that is being cached. Wherever possible this
126      * object should be <code>Serializable</code>, however it is not an
127      * absolute requirement when using a memory-only cache. Being <code>Serializable</code>
128      * allows <code>PersistenceListener</code>s to serialize the cache entries to disk
129      * or database.
130      *
131      * @param value The content to store in this CacheEntry.
132      */

133     public synchronized void setContent(Object JavaDoc value) {
134         content = value;
135         lastUpdate = System.currentTimeMillis();
136         wasFlushed = false;
137     }
138
139     /**
140      * Get the cached content from this CacheEntry.
141      *
142      * @return The content of this CacheEntry.
143      */

144     public Object JavaDoc getContent() {
145         return content;
146     }
147
148     /**
149      * Get the date this CacheEntry was created.
150      *
151      * @return The date this CacheEntry was created.
152      */

153     public long getCreated() {
154         return created;
155     }
156
157     /**
158      * Sets the cache groups for this entry.
159      *
160      * @param groups A string array containing all the group names
161      */

162     public synchronized void setGroups(String JavaDoc[] groups) {
163         if (groups != null) {
164             this.groups = new HashSet JavaDoc(groups.length);
165
166             for (int i = 0; i < groups.length; i++) {
167                 this.groups.add(groups[i]);
168             }
169         } else {
170             this.groups = null;
171         }
172
173         lastUpdate = System.currentTimeMillis();
174     }
175
176     /**
177      * Sets the cache groups for this entry
178      *
179      * @param groups A collection containing all the group names
180      */

181     public void setGroups(Collection JavaDoc groups) {
182         if (groups != null) {
183             this.groups = new HashSet JavaDoc(groups);
184         } else {
185             this.groups = null;
186         }
187
188         lastUpdate = System.currentTimeMillis();
189     }
190
191     /**
192      * Gets the cache groups that this cache entry belongs to.
193      * These returned groups should be treated as immuatable.
194      *
195      * @return A set containing the names of all the groups that
196      * this cache entry belongs to.
197      */

198     public Set JavaDoc getGroups() {
199         return groups;
200     }
201
202     /**
203      * Get the key of this CacheEntry
204      *
205      * @return The key of this CacheEntry
206      */

207     public String JavaDoc getKey() {
208         return key;
209     }
210
211     /**
212      * Set the date this CacheEntry was last updated.
213      *
214      * @param update The time (in milliseconds) this CacheEntry was last updated.
215      */

216     public void setLastUpdate(long update) {
217         lastUpdate = update;
218     }
219
220     /**
221      * Get the date this CacheEntry was last updated.
222      *
223      * @return The date this CacheEntry was last updated.
224      */

225     public long getLastUpdate() {
226         return lastUpdate;
227     }
228
229     /**
230      * Indicates whether this CacheEntry is a freshly created one and
231      * has not yet been assigned content or placed in a cache.
232      *
233      * @return <code>true</code> if this entry is newly created
234      */

235     public boolean isNew() {
236         return lastUpdate == NOT_YET;
237     }
238
239     /**
240      * Get the size of the cache entry in bytes (roughly).<p>
241      *
242      * Currently this method only handles <code>String<code>s and
243      * {@link ResponseContent} objects.
244      *
245      * @return The approximate size of the entry in bytes, or -1 if the
246      * size could not be estimated.
247      */

248     public int getSize() {
249         // a char is two bytes
250
int size = (key.length() * 2) + 4;
251
252         if (content.getClass() == String JavaDoc.class) {
253             size += ((content.toString().length() * 2) + 4);
254         } else if (content instanceof ResponseContent) {
255             size += ((ResponseContent) content).getSize();
256         } else {
257             return -1;
258         }
259
260         //add created, lastUpdate, and wasFlushed field sizes (1, 8, and 8)
261
return size + 17;
262     }
263
264     /**
265      * Flush the entry from cache.
266      * note that flushing the cache doesn't actually remove the cache contents
267      * it just tells the CacheEntry that it needs a refresh next time it is asked
268      * this is so that the content is still there for a <usecached />.
269      */

270     public void flush() {
271         wasFlushed = true;
272     }
273
274     /**
275      * Check if this CacheEntry needs to be refreshed.
276      *
277      * @param refreshPeriod The period of refresh (in seconds). Passing in
278      * {@link #INDEFINITE_EXPIRY} will result in the content never becoming
279      * stale unless it is explicitly flushed, or expired by a custom
280      * {@link EntryRefreshPolicy}. Passing in 0 will always result in a
281      * refresh being required.
282      *
283      * @return Whether or not this CacheEntry needs refreshing.
284      */

285     public boolean needsRefresh(int refreshPeriod) {
286         boolean needsRefresh;
287
288         // needs a refresh if it has never been updated
289
if (lastUpdate == NOT_YET) {
290             needsRefresh = true;
291         }
292         // Was it flushed from cache?
293
else if (wasFlushed) {
294             needsRefresh = true;
295         } else if (refreshPeriod == 0) {
296             needsRefresh = true;
297         }
298         // check what the policy has to say if there is one
299
else if (policy != null) {
300             needsRefresh = policy.needsRefresh(this);
301         }
302         // check if the last update + update period is in the past
303
else if ((refreshPeriod >= 0) && (System.currentTimeMillis() >= (lastUpdate + (refreshPeriod * 1000L)))) {
304             needsRefresh = true;
305         } else {
306             needsRefresh = false;
307         }
308
309         return needsRefresh;
310     }
311 }
312
Popular Tags