Clover coverage report - Coverage timestamp: do jan 22 2004 21:12:32 CET FRAMES NO FRAMES |
file stats: | LOC: | 312 |  | Methods: | 16
| NCLOC: | 113 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
CacheEntry.java | 58,3% | 68% | 81,2% | 67,8% |

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;
10 |  |
11 |  |
     import java.util.Collection;
12 |  |
     import java.util.HashSet;
13 |  |
     import java.util.Set;
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 {
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 content = null;
54 |  |
55 |  |
         /**
56 |  |
          * The set of cache groups that this cache entry belongs to, if any.
57 |  |
          */
58 |  |
         private Set groups = null;
59 |  |
60 |  |
         /**
61 |  |
          *  The unique cache key for this entry
62 |  |
          */
63 |  |
         private String 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 | 21 |
         public CacheEntry(String key) {
86 | 21 |
             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 | 212 |
         public CacheEntry(String key, EntryRefreshPolicy policy) {
97 | 212 |
             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 | 212 |
         public CacheEntry(String key, EntryRefreshPolicy policy, String[] groups) {
110 | 212 |
             this.key = key;
111 |  |
112 | 212 |
             if (groups != null) {
113 | 0 |
                 this.groups = new HashSet(groups.length);
114 |  |
115 | 0 |
                 for (int i = 0; i < groups.length; i++) {
116 | 0 |
                     this.groups.add(groups[i]);
117 |  |
                 }
118 |  |
             }
119 |  |
120 | 212 |
             this.policy = policy;
121 | 212 |
             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 | 213 |
         public synchronized void setContent(Object value) {
134 | 213 |
             content = value;
135 | 213 |
             lastUpdate = System.currentTimeMillis();
136 | 213 |
             wasFlushed = false;
137 |  |
         }
138 |  |
139 |  |
         /**
140 |  |
          * Get the cached content from this CacheEntry.
141 |  |
          *
142 |  |
          * @return The content of this CacheEntry.
143 |  |
          */
144 | 297 |
         public Object getContent() {
145 | 297 |
             return content;
146 |  |
         }
147 |  |
148 |  |
         /**
149 |  |
          * Get the date this CacheEntry was created.
150 |  |
          *
151 |  |
          * @return The date this CacheEntry was created.
152 |  |
          */
153 | 3 |
         public long getCreated() {
154 | 3 |
             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 | 201 |
         public synchronized void setGroups(String[] groups) {
163 | 201 |
             if (groups != null) {
164 | 54 |
                 this.groups = new HashSet(groups.length);
165 |  |
166 | 54 |
                 for (int i = 0; i < groups.length; i++) {
167 | 87 |
                     this.groups.add(groups[i]);
168 |  |
                 }
169 |  |
             } else {
170 | 147 |
                 this.groups = null;
171 |  |
             }
172 |  |
173 | 201 |
             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 | 0 |
         public void setGroups(Collection groups) {
182 | 0 |
             if (groups != null) {
183 | 0 |
                 this.groups = new HashSet(groups);
184 |  |
             } else {
185 | 0 |
                 this.groups = null;
186 |  |
             }
187 |  |
188 | 0 |
             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 | 324 |
         public Set getGroups() {
199 | 324 |
             return groups;
200 |  |
         }
201 |  |
202 |  |
         /**
203 |  |
          * Get the key of this CacheEntry
204 |  |
          *
205 |  |
          * @return The key of this CacheEntry
206 |  |
          */
207 | 191 |
         public String getKey() {
208 | 191 |
             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 | 0 |
         public void setLastUpdate(long update) {
217 | 0 |
             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 | 3 |
         public long getLastUpdate() {
226 | 3 |
             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 | 360 |
         public boolean isNew() {
236 | 360 |
             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 | 0 |
         public int getSize() {
249 |  |
             // a char is two bytes
250 | 0 |
             int size = (key.length() * 2) + 4;
251 |  |
252 | 0 |
             if (content.getClass() == String.class) {
253 | 0 |
                 size += ((content.toString().length() * 2) + 4);
254 | 0 |
             } else if (content instanceof ResponseContent) {
255 | 0 |
                 size += ((ResponseContent) content).getSize();
256 |  |
             } else {
257 | 0 |
                 return -1;
258 |  |
             }
259 |  |
260 |  |
             //add created, lastUpdate, and wasFlushed field sizes (1, 8, and 8)
261 | 0 |
             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 | 48 |
         public void flush() {
271 | 48 |
             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 | 386 |
         public boolean needsRefresh(int refreshPeriod) {
286 | 386 |
             boolean needsRefresh;
287 |  |
288 |  |
             // needs a refresh if it has never been updated
289 | 386 |
             if (lastUpdate == NOT_YET) {
290 | 27 |
                 needsRefresh = true;
291 |  |
             }
292 |  |
             // Was it flushed from cache?
293 | 359 |
             else if (wasFlushed) {
294 | 74 |
                 needsRefresh = true;
295 | 285 |
             } else if (refreshPeriod == 0) {
296 | 63 |
                 needsRefresh = true;
297 |  |
             }
298 |  |
             // check what the policy has to say if there is one
299 | 222 |
             else if (policy != null) {
300 | 6 |
                 needsRefresh = policy.needsRefresh(this);
301 |  |
             }
302 |  |
             // check if the last update + update period is in the past
303 | 216 |
             else if ((refreshPeriod >= 0) && (System.currentTimeMillis() >= (lastUpdate + (refreshPeriod * 1000L)))) {
304 | 0 |
                 needsRefresh = true;
305 |  |
             } else {
306 | 216 |
                 needsRefresh = false;
307 |  |
             }
308 |  |
309 | 386 |
             return needsRefresh;
310 |  |
         }
311 |  |
     }
312 |  |