001: // ***************************************************************
002: // * *
003: // * File:TimeBoundHashMap.java *
004: // * *
005: // * Copyright (c) 2001 Sun Microsystems, Inc. *
006: // * All rights reserved. *
007: // * *
008: // * *
009: // * Date - Dec/17/2001 *
010: // * Author - alejandro.abdelnur@sun.com *
011: // * *
012: // ***************************************************************
013:
014: package com.sun.portal.common.collection;
015:
016: import java.util.Map;
017: import java.util.HashMap;
018: import java.util.Set;
019: import java.util.Iterator;
020:
021: /**
022: * TimeBoundHashMap is a HashMap sub class that purges entries using
023: * a last accessed time mechanism.
024: * <P>
025: * The time out control is done when using the accessor methods of the Map,
026: * no extra Thread is used for it.
027: * <P>
028: * This class is not Thread-safe, if a TimeBoundHashMap instance is to be
029: * used in a multithreaded fashion it should be wrapped with a synchronized
030: * Map (see the Collections.synchronizedMap() method).
031: * <P>
032: *
033: * @author <A HREF="mailto:alejandro.abdelnur@sun.com">Alejandro Abdelnur</A>
034: *
035: */
036: public class TimeBoundHashMap extends HashMap {
037: private long _timeOut;
038: private long _lastCheck;
039: private Map _lastAccess;
040:
041: /**
042: * Creates an empty TimeBoundHashMap with a given last accessed time out.
043: * <P>
044: *
045: * @param timeOut last accessed time out in seconds.
046: *
047: */
048: public TimeBoundHashMap(int timeOut) {
049: super ();
050: init(timeOut);
051: }
052:
053: /**
054: * Creates an empty TimeBoundHashMap with a specific initial capacity
055: * and a given last accessed time out.
056: * <P>
057: *
058: * @param initialCapacity initial capacity of the Map.
059: *
060: * @param timeOut last accessed time out in seconds.
061: *
062: */
063: public TimeBoundHashMap(int initialCapacity, int timeOut) {
064: super (initialCapacity);
065: init(timeOut);
066: }
067:
068: /**
069: * Creates an empty TimeBoundHashMap with a specific initial capacity,
070: * a given load factor and a given last accessed time out.
071: * <P>
072: *
073: * @param initialCapacity initial capacity of the Map.
074: *
075: * @param loadFactor load factor for the Map.
076: *
077: * @param timeOut last accessed time out in seconds.
078: *
079: */
080: public TimeBoundHashMap(int initialCapacity, float loadFactor,
081: int timeOut) {
082: super (initialCapacity, loadFactor);
083: init(timeOut);
084: }
085:
086: /**
087: * Adds time out control and delegates to HashMap.put() method.
088: *
089: */
090: public Object put(Object key, Object value) {
091: long currentTime = System.currentTimeMillis();
092: _lastAccess.put(key, new Long(currentTime));
093: purge();
094: return super .put(key, value);
095: }
096:
097: /**
098: * Adds time out control and delegates to HashMap.get() method.
099: *
100: */
101: public Object get(Object key) {
102: Object obj = super .get(key);
103: if (obj != null) {
104: long currentTime = System.currentTimeMillis();
105: _lastAccess.put(key, new Long(currentTime));
106: }
107: purge();
108: return obj;
109: }
110:
111: /**
112: * Adds time out control and delegates to HashMap.remove() method.
113: *
114: */
115: public Object remove(Object key) {
116: _lastAccess.remove(key);
117: return super .remove(key);
118: }
119:
120: /**
121: * Adds time out control and delegates to HashMap.entrySet() method.
122: *
123: */
124: public Set entrySet() {
125: Set set = super .entrySet();
126: Iterator i = _lastAccess.keySet().iterator();
127: Long currentTime = new Long(System.currentTimeMillis());
128: while (i.hasNext()) {
129: _lastAccess.put(i.next(), currentTime);
130: }
131: return set;
132: }
133:
134: /**
135: * Initialized the instance attributes, called from the constructors.
136: *
137: * @param timeOut last accessed time out in seconds.
138: *
139: */
140: private void init(int timeOut) {
141: _timeOut = timeOut * 1000;
142: _lastCheck = System.currentTimeMillis();
143: _lastAccess = new HashMap();
144: }
145:
146: /**
147: * Removes entries that have expired.
148: *
149: */
150: private void purge() {
151: long currentTime = System.currentTimeMillis();
152: if ((currentTime - _lastCheck) > (_timeOut / 8)) {
153: Iterator i = _lastAccess.keySet().iterator();
154: while (i.hasNext()) {
155: Object key = i.next();
156: long lastTime = ((Long) _lastAccess.get(key))
157: .longValue();
158: if ((currentTime - lastTime) > _timeOut) {
159: i.remove();
160: super.remove(key);
161: }
162: }
163: _lastCheck = currentTime;
164: }
165: }
166:
167: }
|