1 19 package org.netbeans.modules.timers; 20 21 import java.lang.ref.Reference ; 22 import java.lang.ref.ReferenceQueue ; 23 import java.lang.ref.WeakReference ; 24 import java.util.ArrayList ; 25 import java.util.Collection ; 26 import java.util.Iterator ; 27 import java.util.LinkedList ; 28 import java.util.List ; 29 import java.util.concurrent.ExecutorService ; 30 import java.util.concurrent.Executors ; 31 import javax.swing.event.ChangeEvent ; 32 import javax.swing.event.ChangeListener ; 33 34 38 public class InstanceWatcher { 39 40 private List <Reference <Object >> references; 41 private ReferenceQueue <Object > queue; 42 private static ExecutorService executor = Executors.newSingleThreadExecutor(); 43 44 private transient List <WeakReference <ChangeListener >> changeListenerList; 45 46 47 48 public InstanceWatcher() { 49 references = new ArrayList <Reference <Object >>(); 50 queue = new ReferenceQueue <Object >(); 51 new FinalizingToken(); 52 } 53 54 public synchronized void add( Object instance ) { 55 if ( ! contains( instance ) ) { 56 references.add( new WeakReference <Object >( instance, queue ) ); 57 } 58 } 59 60 private synchronized boolean contains( Object o ) { 61 for( Reference r : references ) { 62 if ( r.get() == o ) { 63 return true; 64 } 65 } 66 return false; 67 } 68 69 public synchronized int size() { 70 removeNulls(); 71 return references.size(); 72 } 73 74 public Collection <?> getInstances() { 75 List <Object > l = new ArrayList <Object >(references.size()); 76 for (Reference wr : references) { 77 Object inst = wr.get(); 78 if (inst != null) l.add(inst); 79 } 80 return l; 81 } 82 83 88 89 94 public synchronized void addChangeListener(javax.swing.event.ChangeListener listener) { 95 if (changeListenerList == null ) { 96 changeListenerList = new ArrayList <WeakReference <ChangeListener >>(); 97 } 98 changeListenerList.add(new WeakReference <ChangeListener >( listener ) ); 99 } 100 101 105 public synchronized void removeChangeListener(ChangeListener listener) { 106 107 if ( listener == null ) { 108 return; 109 } 110 111 if (changeListenerList != null ) { 112 for( WeakReference <ChangeListener > r : changeListenerList ) { 113 if ( listener.equals( r.get() ) ) { 114 changeListenerList.remove( r ); 115 } 116 } 117 } 118 119 } 120 121 123 private static <T> void cleanAndCopy( List <? extends Reference <T>> src, List <? super T> dest ) { 124 for( int i = src.size() - 1; i >= 0; i-- ) { 125 T o = src.get(i).get(); 126 if( o == null ) { 127 src.remove(i); 128 } 129 else if ( dest != null ) { 130 dest.add( 0, o ); 131 } 132 } 133 } 134 135 136 private synchronized void removeNulls() { 137 cleanAndCopy( references, null ); 138 } 139 140 private boolean cleanQueue() { 141 boolean retValue = false; 142 143 while( queue.poll() != null ) { 144 retValue = true; 145 } 146 147 return retValue; 148 } 149 150 private void refresh() { 151 if ( cleanQueue() ) { 152 removeNulls(); 153 fireChangeListenerStateChanged(); 154 } 155 156 new FinalizingToken(); 157 } 158 159 private void fireChangeListenerStateChanged() { 160 List <ChangeListener > list = new LinkedList <ChangeListener >(); 161 synchronized (this) { 162 if (changeListenerList == null) { 163 return; 164 } 165 cleanAndCopy( changeListenerList, list ); 166 } 167 168 ChangeEvent e = new ChangeEvent ( this ); 169 for (ChangeListener ch : list ) { 170 ch.stateChanged (e); 171 } 172 } 173 174 176 private class FinalizingToken implements Runnable { 177 178 public void finalize() { 179 executor.submit( this ); 180 } 181 182 public void run() { 183 refresh(); 184 } 185 186 } 187 188 } 189 | Popular Tags |