/** * 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; } } }