001    /*
002     * WeakValueMap.java created on 31.10.2006
003     *
004     * To change this generated comment go to 
005     * Window>Preferences>Java>Code Generation>Code and Comments
006     */
007    package org.codehaus.groovy.runtime;
008    
009    import java.lang.ref.ReferenceQueue;
010    import java.lang.ref.SoftReference;
011    import java.util.ArrayList;
012    import java.util.Collection;
013    import java.util.Iterator;
014    import java.util.Set;
015    import java.util.WeakHashMap;
016    
017    public class ReferenceMap extends WeakHashMap {
018        
019        private static class HardReference extends SoftReference {
020            private Object value;
021            public HardReference(Object arg) {
022                super(null);
023                value = arg;
024            }
025            public Object get() {
026                return value;
027            }        
028        }
029        
030        private ReferenceQueue queue = new ReferenceQueue();
031        
032        public ReferenceMap() {
033            super();
034        }
035    
036        public boolean containsValue(Object value) {
037            throw new UnsupportedOperationException();
038        }
039        
040        public Set entrySet() {
041            throw new UnsupportedOperationException();
042        }
043        
044        public Object get(Object key) {
045            Object ret = super.get(key);
046            if (ret!=null) {
047                SoftReference weak = (SoftReference) ret;
048                ret = weak.get();
049                if (ret==null) remove(key);
050            }        
051            return ret;
052        }
053        
054        public Object put(Object key, Object value) {
055            removeDereferencedEntries();
056            if (value!=null) {
057                value = new SoftReference(value,queue);
058            }        
059            return super.put(key, value);
060        }
061        
062        public Object putStrong(Object key, Object value) {
063            removeDereferencedEntries();
064            if (value!=null) {
065                value = new HardReference(value);
066            }        
067            return super.put(key, value);
068        }
069        
070        public Collection values() {
071            removeDereferencedEntries();
072            Collection origColl = super.values();
073            ArrayList newColl = new ArrayList(origColl.size());
074            for (Iterator iter = origColl.iterator(); iter.hasNext();) {
075                SoftReference element = (SoftReference) iter.next();
076                if (element!=null) {
077                    Object strong = element.get();
078                    if (strong==null) continue;
079                    newColl.add(strong);
080                } else {
081                    newColl.add(null);
082                }            
083            }        
084            return newColl;
085        }
086        
087        private void removeDereferencedEntries(){
088            SoftReference e;
089            while ( (e = (SoftReference) queue.poll()) != null) {
090                Object strong = e.get();
091                if (strong==null) continue;
092                remove(strong);
093            }
094        }
095    }