1 package org.apache.fulcrum.cache;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 /**
23 * The idea of the RefreshableCachedObject is that, rather than removing items
24 * from the cache when they become stale, we'll tell them to refresh themselves
25 * instead. That way they'll always be in the cache, and the code to refresh
26 * them will be run by the background thread rather than by a user request
27 * thread. You can also set a TTL (Time To Live) for the object. This way, if
28 * the object hasn't been touched for the TTL period, then it will be removed
29 * from the cache.
30 *
31 * This extends CachedObject and provides a method for refreshing the cached
32 * object, and resetting its expire time.
33 *
34 * @author <a href="mailto:nissim@nksystems.com">Nissim Karpenstein</a>
35 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
36 * @version $Id$
37 */
38 public class RefreshableCachedObject<T extends Refreshable> extends CachedObject<T>
39 {
40
41 /**
42 * Serialization key
43 */
44 private static final long serialVersionUID = 4072572956381768087L;
45
46 /**
47 * How long to wait before removing an untouched object from the cache.
48 * Negative numbers mean never remove (the default).
49 *
50 * time to live in millisec, getter/setter ({@link #getTTL()}
51 *
52 */
53 private long timeToLive = -1;
54
55 /**
56 * The last time the Object was accessed from the cache.
57 */
58 private long lastAccess;
59
60 /**
61 * Constructor; sets the object to expire in the default time (30 minutes).
62 *
63 * @param object
64 * The object you want to cache.
65 */
66 public RefreshableCachedObject(final T object)
67 {
68 super(object);
69 setLastAccess(System.currentTimeMillis());
70 }
71
72 /**
73 * Constructor.
74 *
75 * @param object
76 * The object to cache.
77 * @param expires
78 * How long before the object expires, in ms, e.g. 1000 = 1
79 * second.
80 */
81 public RefreshableCachedObject(final T object, final long expires)
82 {
83 super(object, expires);
84 setLastAccess(System.currentTimeMillis());
85 }
86
87 /**
88 * Sets the timeToLive value
89 *
90 * @param timeToLive
91 * the new Value in milliseconds
92 */
93 public void setTTL(final long timeToLive)
94 {
95 synchronized(this) {
96 this.timeToLive = timeToLive;
97 }
98 }
99
100 /**
101 * Gets the timeToLive value.
102 *
103 * @return The current timeToLive value (in milliseconds)
104 */
105 public long getTTL()
106 {
107 synchronized(this) {
108 return this.timeToLive;
109 }
110 }
111
112 /**
113 * Sets the last access time to the current time.
114 */
115 public void touch()
116 {
117 synchronized(this) {
118 this.lastAccess = System.currentTimeMillis();
119 }
120 }
121
122 /**
123 * Returns true if the object hasn't been touched in the previous TTL
124 * period.
125 *
126 * @return boolean status of object
127 */
128 public boolean isUntouched()
129 {
130 boolean untouched = false;
131 synchronized(this) {
132 if (this.lastAccess + this.timeToLive < System.currentTimeMillis())
133 {
134 untouched = true;
135 }
136 return untouched;
137 }
138 }
139
140 /**
141 * Refresh the object and the created time.
142 */
143 public void refresh()
144 {
145 final Refreshable refreshable = getContents();
146 synchronized (this)
147 {
148 this.created = System.currentTimeMillis();
149 refreshable.refresh();
150 }
151 }
152
153 public long getLastAccess()
154 {
155 return lastAccess;
156 }
157
158 public void setLastAccess(long lastAccess)
159 {
160 this.lastAccess = lastAccess;
161 }
162 }