001    
002    package org.objectweb.jac.util;
003    
004    import java.lang.ref.Reference;
005    import java.lang.ref.ReferenceQueue;
006    import java.lang.ref.WeakReference;
007    import java.util.AbstractList;
008    import java.util.ArrayList;
009    import java.util.List;
010    import org.apache.log4j.Logger;
011    
012    public class WeakList extends AbstractList {
013        static Logger logger = Logger.getLogger("weak.collections");
014    
015        /**
016         * Reference queue for cleared weak references
017         */
018        private final ReferenceQueue queue = new ReferenceQueue();
019       
020        private final List list=new ArrayList();
021    
022        public boolean add(Object o) {
023            expungeStaleEntries();
024            return list.add(new ListEntry(o,queue));
025        }
026    
027        public Object get(int i) {
028            expungeStaleEntries();
029            return ((Reference)list.get(i)).get();
030        }
031    
032        public int size() {
033            //new Exception().printStackTrace();
034            expungeStaleEntries();
035            return list.size();
036        }
037    
038        public Object remove(int index) {
039            return ((ListEntry)list.remove(index)).get();
040        }
041    
042        /**
043         * Expunge stale entries from the list.
044         */
045        private void expungeStaleEntries() {
046            Object r;
047            while ( (r = queue.poll()) != null) {
048                ListEntry e = (ListEntry)r;
049                int i=list.indexOf(r);
050                if(i!=-1) {
051                    logger.debug("removing from list "+r+" ("+i+")");
052                    list.remove(i);
053                }
054            }
055        }
056    
057        private static class ListEntry extends WeakReference {
058            String objectString;
059            public ListEntry(Object o,ReferenceQueue queue) {
060                super(o,queue);
061                objectString=o.toString();
062            }
063            public boolean equals(Object o) {
064                if(o==null) {
065                    return false;
066                } else {
067                    if((o instanceof ListEntry)) {
068                        return o.hashCode()==this.hashCode();
069                    } else {
070                        if(this.get()==null) return false;
071                        return this.get().equals(o);
072                    }
073                }
074            }
075            public String toString() {
076                if(this.get()==null) {
077                    return "'entry "+objectString+" <GARBAGED>'";
078                } else {
079                    return "'entry "+this.get()+"'";
080                }
081            }
082          
083        }
084    }