/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004, 2005, 2006], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. This program is distributed * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ /* * Created on Jul 17, 2003 * * An extension of HashMap whose entries expire */ package org.hyperic.util.collection; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * */ public class ExpireMap extends HashMap { /** * * This is the class used as value to the ExpireMap class */ public class Value { private Object value; private long expiration; /** * No expiration constructor * @param value the actual value */ public Value(Object value) { // Default expiration in 4 minutes this(value, 4 * 60 * 1000); } /** * Constructor with expiration (offset from current time) * @param value the actual value * @param expiration the offset from current time */ public Value(Object value, long expiration) { this.value = value; this.expiration = System.currentTimeMillis() + expiration; } /** * Check if key has expired * @return true if key has expired */ public boolean hasExpired() { return expiration < System.currentTimeMillis(); } /** * @return the expiration time */ public long getExpiration() { return expiration; } /** * @param l the new expiration time */ public void setExpiration(long l) { expiration = l; } /** * @return the value object */ public Object getValue() { return value; } /** * @param object the new value object */ public void setValue(Object object) { value = object; } } /* This function should not be called directly, as the values * returned are Value objects * @see java.util.Map#entrySet() */ public Set entrySet() { // Throw out the expired value objects Set entries = super.entrySet(); for (Iterator it = entries.iterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry) it.next(); Value value = (Value) entry.getValue(); if (value.hasExpired()) { it.remove(); } } return entries; } /* (non-Javadoc) * @see java.util.Map#get(java.lang.Object) */ public Object get(Object key) { Value value = (Value) super.get(key); if (value != null) { if (value.hasExpired()) { super.remove(key); } else { return value.getValue(); } } return null; } /* (non-Javadoc) * @see java.util.Map#containsKey(java.lang.Object) */ public boolean containsKey(Object key) { return (this.get(key) != null); } /* (non-Javadoc) * @see java.util.Map#keySet() */ public Set keySet() { this.entrySet(); // Clean out the expired values return super.keySet(); } /* (non-Javadoc) * @see java.util.Map#values() */ public Collection values() { Set entries = this.entrySet(); // Clean out the expired values ArrayList values = new ArrayList(); for (Iterator it = entries.iterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry) it.next(); Value value = (Value) entry.getValue(); values.add(value.getValue()); } return values; } /* (non-Javadoc) * @see java.util.Map#put(java.lang.Object, java.lang.Object) */ public Object put(Object key, Object value) { // Create a new value with default expiration of 4 minutes from now return super.put(key, new Value(value)); } /* (non-Javadoc) * @see java.util.Map#put(java.lang.Object, java.lang.Object) */ public Object put(Object key, Object value, long expiration) { return super.put(key, new Value(value, expiration)); } // Test cases public static void main(String[] args) throws Exception { // Add an object to expire in a couple of seconds ExpireMap map = new ExpireMap(); map.put("key", "object", 2000); Thread.sleep(1000); System.out.println("1 sec: Map contains key: " + map.containsKey("key")); Thread.sleep(1000); System.out.println("2 sec: Map contains key: " + map.containsKey("key")); // Make sure the value object is converted correctly map.put("key", "object"); Object obj = map.get("key"); System.out.println("Objects are equal: " + obj.equals("object")); } /** * Get an instance of ExpireMap which is backed by a * synchronized map */ public static ExpireMap getSynchronizedCache() { return (ExpireMap)Collections.synchronizedMap( new ExpireMap()); } }