/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the License at the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apereo.portal.utils;
import java.util.HashMap;
import java.util.Iterator;
/**
* The SmartCache class is used to store objects in memory for a specified amount of time. The time
* should be specified in seconds. If the time is specified as a negative value, it will be cahced
* indefinitely.
*
*/
public class SmartCache extends HashMap {
protected int iExpirationTimeout = 3600000; // default to 1 hour
/**
* Instantiate a new SmartCache. Usually instances of SmartCache are declared as static. When
* retrieving a value from SmartCache, it will be null if the value has expired. It is up to the
* client to then retrieve the value and put it in the cache again. Example: <code>
* import org.apereo.portal.utils.SmartCache;
*
* public class CacheClient {
* private static SmartCache cache = new SmartCache(3600); // This cache's values will expire in one hour
*
* public static void main (String[] args) {
* // Try to get a value from the cache
* String aKey = "exampleKey";
* String aValue = (String)cache.get(aKey);
*
* if (aValue == null) {
* // If we are here, the value has either expired or not in the cache
* // so we will get the value and stuff it in the cache
* String freshValue = someMethodWhichReturnsAString();
*
* // Make sure it isn't null before putting it into the cache
* if (freshValue != null) {
* cache.put(aKey, freshValue);
* aValue = freshValue;
* }
* }
*
* System.out.println ("Got the value: " + aValue);
* }
* }
* </code>
*
* @param iExpirationTimeout specified in seconds
*/
public SmartCache(int iExpirationTimeout) {
super();
this.iExpirationTimeout = iExpirationTimeout * 1000;
}
/** Instantiate SmartCache with a default expiration timeout of one hour. */
public SmartCache() {
super();
}
/**
* Add a new value to the cache. The value will expire in accordance with the cache's expiration
* timeout value which was set when the cache was created.
*
* @param key the key, typically a String
* @param value the value
* @return the previous value of the specified key in this hashtable, or null if it did not have
* one.
*/
public synchronized Object put(Object key, Object value) {
ValueWrapper valueWrapper = new ValueWrapper(value);
return super.put(key, valueWrapper);
}
/**
* Add a new value to the cache
*
* @param key the key, typically a String
* @param value the value
* @param lCacheInterval an expiration timeout value, in seconds, which will override the
* default cache value just for this item. If a negative timeout value is specified, the
* value will be cached indefinitely.
* @return the cached object
*/
public synchronized Object put(Object key, Object value, long lCacheInterval) {
ValueWrapper valueWrapper = new ValueWrapper(value, lCacheInterval);
return super.put(key, valueWrapper);
}
/**
* Get an object from the cache.
*
* @param key the key, typically a String
* @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.
*/
public synchronized Object get(Object key) {
ValueWrapper valueWrapper = (ValueWrapper) super.get(key);
if (valueWrapper != null) {
// Check if value has expired
long creationTime = valueWrapper.getCreationTime();
long cacheInterval = valueWrapper.getCacheInterval();
long currentTime = System.currentTimeMillis();
if (cacheInterval >= 0 && creationTime + cacheInterval < currentTime) {
remove(key);
return null;
}
return valueWrapper.getValue();
} else return null;
}
/** Removes from the cache values which have expired. */
protected void sweepCache() {
for (Iterator keyIterator = keySet().iterator(); keyIterator.hasNext(); ) {
Object key = keyIterator.next();
ValueWrapper valueWrapper = (ValueWrapper) super.get(key);
long creationTime = valueWrapper.getCreationTime();
long cacheInterval = valueWrapper.getCacheInterval();
long currentTime = System.currentTimeMillis();
if (cacheInterval >= 0 && creationTime + cacheInterval < currentTime) {
remove(key);
}
}
}
private class ValueWrapper {
private long lCreationTime = System.currentTimeMillis();
private long lCacheInterval = iExpirationTimeout;
private Object oValue;
protected ValueWrapper(Object oValue) {
this.oValue = oValue;
}
protected ValueWrapper(Object oValue, long lCacheInterval) {
this.oValue = oValue;
this.lCacheInterval = lCacheInterval * 1000;
}
protected Object getValue() {
return oValue;
}
protected void setValue(Object oValue) {
this.oValue = oValue;
}
protected long getCreationTime() {
return lCreationTime;
}
protected void setCreationTime(long lCreationTime) {
this.lCreationTime = lCreationTime;
}
protected long getCacheInterval() {
return lCacheInterval;
}
protected void setCacheInterval(long lCacheInterval) {
this.lCacheInterval = lCacheInterval;
}
}
}