001: /*
002: ItsNat Java Web Application Framework
003: Copyright (C) 2007 Innowhere Software Services S.L., Spanish Company
004: Author: Jose Maria Arranz Santamaria
005:
006: This program is free software: you can redistribute it and/or modify
007: it under the terms of the GNU Affero General Public License as published by
008: the Free Software Foundation, either version 3 of the License, or
009: (at your option) any later version. See the GNU Affero General Public
010: License for more details. See the copy of the GNU Affero General Public License
011: included in this program. If not, see <http://www.gnu.org/licenses/>.
012: */
013:
014: package org.itsnat.impl.core.util;
015:
016: import java.lang.ref.Reference;
017: import java.lang.ref.ReferenceQueue;
018: import java.lang.ref.WeakReference;
019: import java.util.HashMap;
020: import java.util.Map;
021: import java.util.Set;
022: import java.util.WeakHashMap;
023:
024: /**
025: * http://www.javaworld.com/javaworld/jw-01-2002/jw-0104-java101.html?page=3
026: *
027: * @author jmarranz
028: */
029: public class WeakMapPluggable {
030: protected Map weakMap = new WeakHashMap();
031: protected Map weakRefMap = new HashMap();
032: protected ReferenceQueue queue = new ReferenceQueue();
033: protected ExpungeListener listener;
034:
035: /** Creates a new instance of NodeCache */
036: public WeakMapPluggable(ExpungeListener listener) {
037: this .listener = listener;
038: }
039:
040: public Object remove(Object key) {
041: cleanUnused();
042:
043: KeyValuePair pair = (KeyValuePair) weakMap.remove(key);
044: if (pair == null)
045: return null;
046: WeakReference weakRef = pair.getKey();
047: weakRefMap.remove(weakRef);
048: return pair.getValue();
049: }
050:
051: public Object get(Object key) {
052: cleanUnused();
053:
054: KeyValuePair pair = (KeyValuePair) weakMap.get(key);
055: if (pair == null)
056: return null;
057:
058: return pair.getValue();
059: }
060:
061: public Object put(Object key, Object value) {
062: cleanUnused();
063:
064: WeakReference weakRef = new WeakReference(key, queue);
065: KeyValuePair pair = new KeyValuePair(weakRef, value);
066:
067: KeyValuePair oldPair = (KeyValuePair) weakMap.put(key, pair);
068: weakRefMap.put(weakRef, pair);
069:
070: if (oldPair == null)
071: return null;
072:
073: return oldPair.getValue();
074: }
075:
076: public void cleanUnused() {
077: // System.gc(); // ralentiza muchísimo y no es imprescindible
078:
079: Reference weakRef = queue.poll();
080: while (weakRef != null) {
081: KeyValuePair pair = (KeyValuePair) weakRefMap
082: .remove(weakRef);
083: if ((pair != null) && (listener != null))
084: listener.processExpunged(pair.getValue());
085:
086: weakRef = queue.poll();
087: }
088: }
089:
090: public boolean isEmpty() {
091: cleanUnused();
092:
093: boolean res = weakMap.isEmpty();
094: if (res != weakRefMap.isEmpty())
095: throw new RuntimeException("INTERNAL ERROR");
096: return res;
097: }
098:
099: public Set entrySet() {
100: return weakMap.entrySet();
101: }
102:
103: public static class KeyValuePair {
104: protected WeakReference key;
105: protected Object value;
106:
107: public KeyValuePair(WeakReference key, Object value) {
108: this .key = key;
109: this .value = value;
110: }
111:
112: public WeakReference getKey() {
113: return key;
114: }
115:
116: public Object getValue() {
117: return value;
118: }
119: }
120:
121: public interface ExpungeListener {
122: public void processExpunged(Object value);
123: }
124:
125: /*
126: public static void main(String[] args)
127: {
128: ExpungeListener listener = new ExpungeListener()
129: {
130: public int counter = 0;
131: public void expunged(Object value)
132: {
133: counter++;
134: System.out.println(value + " " + counter);
135: }
136: };
137:
138: WeakMapPluggable map = new WeakMapPluggable(listener);
139: for(int i = 0; i < 6000; i++)
140: {
141: map.put(new Integer(i),Integer.toString(i));
142: }
143: }
144: **/
145: }
|