001: /* Copyright 2001 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.utils;
007:
008: import java.util.HashMap;
009: import java.util.Iterator;
010:
011: /**
012: * The SmartCache class is used to store objects in memory for
013: * a specified amount of time. The time should be specified in seconds.
014: * If the time is specified as a negative value, it will be cahced indefinitely.
015: * @author Ken Weiner, kweiner@unicon.net
016: * @version $Revision: 34797 $
017: */
018: public class SmartCache extends HashMap {
019: protected int iExpirationTimeout = 3600000; // default to 1 hour
020:
021: /**
022: * Instantiate a new SmartCache. Usually instances of SmartCache are
023: * declared as static. When retrieving a value from SmartCache, it will
024: * be null if the value has expired. It is up to the client to then
025: * retrieve the value and put it in the cache again.
026: * Example:
027: * <code>
028: * import org.jasig.portal.utils.SmartCache;
029: *
030: * public class CacheClient {
031: * private static SmartCache cache = new SmartCache(3600); // This cache's values will expire in one hour
032: *
033: * public static void main (String[] args) {
034: * // Try to get a value from the cache
035: * String aKey = "exampleKey";
036: * String aValue = (String)cache.get(aKey);
037: *
038: * if (aValue == null) {
039: * // If we are here, the value has either expired or not in the cache
040: * // so we will get the value and stuff it in the cache
041: * String freshValue = someMethodWhichReturnsAString();
042: *
043: * // Make sure it isn't null before putting it into the cache
044: * if (freshValue != null) {
045: * cache.put(aKey, freshValue);
046: * aValue = freshValue;
047: * }
048: * }
049: *
050: * System.out.println ("Got the value: " + aValue);
051: * }
052: * }
053: * </code>
054: * @param iExpirationTimeout specified in seconds
055: */
056: public SmartCache(int iExpirationTimeout) {
057: super ();
058: this .iExpirationTimeout = iExpirationTimeout * 1000;
059: }
060:
061: /**
062: * Instantiate SmartCache with a default expiration timeout of one hour.
063: */
064: public SmartCache() {
065: super ();
066: }
067:
068: /**
069: * Add a new value to the cache. The value will expire in accordance with the
070: * cache's expiration timeout value which was set when the cache was created.
071: * @param key the key, typically a String
072: * @param value the value
073: * @return the previous value of the specified key in this hashtable, or null if it did not have one.
074: */
075: public synchronized Object put(Object key, Object value) {
076: ValueWrapper valueWrapper = new ValueWrapper(value);
077: return super .put(key, valueWrapper);
078: }
079:
080: /**
081: * Add a new value to the cache
082: * @param key the key, typically a String
083: * @param value the value
084: * @param lCacheInterval an expiration timeout value, in seconds, which will
085: * override the default cache value just for this item. If a negative timeout
086: * value is specified, the value will be cached indefinitely.
087: * @return the cached object
088: */
089: public synchronized Object put(Object key, Object value,
090: long lCacheInterval) {
091: ValueWrapper valueWrapper = new ValueWrapper(value,
092: lCacheInterval);
093: return super .put(key, valueWrapper);
094: }
095:
096: /**
097: * Get an object from the cache.
098: * @param key the key, typically a String
099: * @return the value to which the key is mapped in this cache; null if the key is not mapped to any value in this cache.
100: */
101: public synchronized Object get(Object key) {
102: ValueWrapper valueWrapper = (ValueWrapper) super .get(key);
103: if (valueWrapper != null) {
104: // Check if value has expired
105: long creationTime = valueWrapper.getCreationTime();
106: long cacheInterval = valueWrapper.getCacheInterval();
107: long currentTime = System.currentTimeMillis();
108: if (cacheInterval >= 0
109: && creationTime + cacheInterval < currentTime) {
110: remove(key);
111: return null;
112: }
113: return valueWrapper.getValue();
114: } else
115: return null;
116: }
117:
118: /**
119: * Removes from the cache values which have expired.
120: */
121: protected void sweepCache() {
122: for (Iterator keyIterator = keySet().iterator(); keyIterator
123: .hasNext();) {
124: Object key = keyIterator.next();
125: ValueWrapper valueWrapper = (ValueWrapper) super .get(key);
126: long creationTime = valueWrapper.getCreationTime();
127: long cacheInterval = valueWrapper.getCacheInterval();
128: long currentTime = System.currentTimeMillis();
129: if (cacheInterval >= 0
130: && creationTime + cacheInterval < currentTime) {
131: remove(key);
132: }
133: }
134: }
135:
136: private class ValueWrapper {
137: private long lCreationTime = System.currentTimeMillis();
138: private long lCacheInterval = iExpirationTimeout;
139: private Object oValue;
140:
141: protected ValueWrapper(Object oValue) {
142: this .oValue = oValue;
143: }
144:
145: protected ValueWrapper(Object oValue, long lCacheInterval) {
146: this .oValue = oValue;
147: this .lCacheInterval = lCacheInterval * 1000;
148: }
149:
150: protected Object getValue() {
151: return oValue;
152: }
153:
154: protected void setValue(Object oValue) {
155: this .oValue = oValue;
156: }
157:
158: protected long getCreationTime() {
159: return lCreationTime;
160: }
161:
162: protected void setCreationTime(long lCreationTime) {
163: this .lCreationTime = lCreationTime;
164: }
165:
166: protected long getCacheInterval() {
167: return lCacheInterval;
168: }
169:
170: protected void setCacheInterval(long lCacheInterval) {
171: this.lCacheInterval = lCacheInterval;
172: }
173: }
174: }
|