1 19 package org.openide.util.lookup; 20 21 import java.lang.ref.Reference ; 22 import java.lang.ref.WeakReference ; 23 import org.openide.util.Lookup; 24 import org.openide.util.LookupEvent; 25 import org.openide.util.LookupListener; 26 27 import java.util.*; 28 29 30 36 final class SimpleProxyLookup extends org.openide.util.Lookup { 37 38 private Provider provider; 39 40 41 private Lookup delegate; 42 43 44 private WeakHashMap<Template<?>,Reference <ProxyResult<?>>> results; 45 46 49 SimpleProxyLookup(Provider provider) { 50 this.provider = provider; 51 } 52 53 54 private Lookup checkLookup() { 55 Lookup l = provider.getLookup(); 56 57 Iterator<Reference <ProxyResult<?>>> toCheck = null; 59 60 synchronized (this) { 61 if (l != delegate) { 62 this.delegate = l; 63 64 if (results != null) { 65 toCheck = new ArrayList<Reference <ProxyResult<?>>>(results.values()).iterator(); 66 } 67 } 68 } 69 70 if (toCheck != null) { 71 ArrayList<Object > evAndListeners = new ArrayList<Object >(); 73 for (Iterator<Reference <ProxyResult<?>>> it = toCheck; it.hasNext(); ) { 74 java.lang.ref.Reference <ProxyResult<?>> ref = it.next(); 75 if (ref == null) { 76 continue; 77 } 78 79 ProxyResult<?> p = ref.get(); 80 81 if (p != null && p.updateLookup(l)) { 82 p.collectFires(evAndListeners); 83 } 84 } 85 86 for (Iterator it = evAndListeners.iterator(); it.hasNext(); ) { 87 LookupEvent ev = (LookupEvent)it.next(); 88 LookupListener ll = (LookupListener)it.next(); 89 ll.resultChanged(ev); 90 } 91 } 92 93 return delegate; 94 } 95 96 @SuppressWarnings ("unchecked") 97 private static <T> ProxyResult<T> cast(ProxyResult<?> p) { 98 return (ProxyResult<T>)p; 99 } 100 101 public <T> Result<T> lookup(Template<T> template) { 102 synchronized (this) { 103 if (results == null) { 104 results = new WeakHashMap<Template<?>,Reference <ProxyResult<?>>>(); 105 } else { 106 Reference <ProxyResult<?>> ref = results.get(template); 107 108 if (ref != null) { 109 ProxyResult<?> p = ref.get(); 110 111 if (p != null) { 112 return cast(p); 113 } 114 } 115 } 116 117 ProxyResult<T> p = new ProxyResult<T>(template); 118 Reference <ProxyResult<?>> ref = new WeakReference <ProxyResult<?>>(p); 119 results.put(template, ref); 120 121 return p; 122 } 123 } 124 125 public <T> T lookup(Class <T> clazz) { 126 if (clazz == null) { 127 checkLookup(); 128 return null; 129 } 130 return checkLookup().lookup(clazz); 131 } 132 133 public <T> Item<T> lookupItem(Template<T> template) { 134 return checkLookup().lookupItem(template); 135 } 136 137 142 private final class ProxyResult<T> extends WaitableResult<T> implements LookupListener { 143 144 private Template<T> template; 145 146 147 private Lookup.Result<T> delegate; 148 149 150 private javax.swing.event.EventListenerList listeners; 151 private LookupListener lastListener; 152 153 154 ProxyResult(Template<T> template) { 155 this.template = template; 156 } 157 158 160 private Result<T> checkResult() { 161 updateLookup(checkLookup()); 162 163 return this.delegate; 164 } 165 166 169 public boolean updateLookup(Lookup l) { 170 Collection<? extends Item<T>> oldPairs = (delegate != null) ? delegate.allItems() : null; 171 172 LookupListener removedListener; 173 174 synchronized (this) { 175 if ((delegate != null) && (lastListener != null)) { 176 removedListener = lastListener; 177 delegate.removeLookupListener(lastListener); 178 } else { 179 removedListener = null; 180 } 181 } 182 183 Lookup.Result<T> res = l.lookup(template); 185 186 synchronized (this) { 187 if (removedListener == lastListener) { 188 delegate = res; 189 lastListener = new WeakResult<T>(this, delegate); 190 delegate.addLookupListener(lastListener); 191 } 192 } 193 194 if (oldPairs == null) { 195 return false; 197 } 198 199 Collection<? extends Item<T>> newPairs = delegate.allItems(); 200 201 if (!(oldPairs instanceof List)) { 203 if (oldPairs == Collections.EMPTY_SET) { 204 oldPairs = Collections.emptyList(); 206 } else { 207 oldPairs = new ArrayList<Item<T>>(oldPairs); 208 } 209 } 210 211 if (!(newPairs instanceof List)) { 212 newPairs = new ArrayList<Item<T>>(newPairs); 213 } 214 215 return !oldPairs.equals(newPairs); 216 } 217 218 public synchronized void addLookupListener(LookupListener l) { 219 if (listeners == null) { 220 listeners = new javax.swing.event.EventListenerList (); 221 } 222 223 listeners.add(LookupListener.class, l); 224 } 225 226 public synchronized void removeLookupListener(LookupListener l) { 227 if (listeners != null) { 228 listeners.remove(LookupListener.class, l); 229 } 230 } 231 232 public java.util.Collection <? extends T> allInstances() { 233 return checkResult().allInstances(); 234 } 235 236 public Set<Class <? extends T>> allClasses() { 237 return checkResult().allClasses(); 238 } 239 240 public Collection<? extends Item<T>> allItems() { 241 return checkResult().allItems(); 242 } 243 244 protected void beforeLookup(Lookup.Template t) { 245 Lookup.Result r = checkResult(); 246 247 if (r instanceof WaitableResult) { 248 ((WaitableResult) r).beforeLookup(t); 249 } 250 } 251 252 256 public void resultChanged(LookupEvent anEvent) { 257 collectFires(null); 258 } 259 260 protected void collectFires(Collection<Object > evAndListeners) { 261 javax.swing.event.EventListenerList l = this.listeners; 262 263 if (l == null) { 264 return; 265 } 266 267 Object [] listeners = l.getListenerList(); 268 269 if (listeners.length == 0) { 270 return; 271 } 272 273 LookupEvent ev = new LookupEvent(this); 274 AbstractLookup.notifyListeners(listeners, ev, evAndListeners); 275 } 276 } 277 private final class WeakResult<T> extends WaitableResult<T> implements LookupListener { 279 private Lookup.Result source; 280 private Reference <ProxyResult<T>> result; 281 282 public WeakResult(ProxyResult<T> r, Lookup.Result<T> s) { 283 this.result = new WeakReference <ProxyResult<T>>(r); 284 this.source = s; 285 } 286 287 protected void beforeLookup(Lookup.Template t) { 288 ProxyResult r = (ProxyResult)result.get(); 289 if (r != null) { 290 r.beforeLookup(t); 291 } else { 292 source.removeLookupListener(this); 293 } 294 } 295 296 protected void collectFires(Collection<Object > evAndListeners) { 297 ProxyResult<T> r = result.get(); 298 if (r != null) { 299 r.collectFires(evAndListeners); 300 } else { 301 source.removeLookupListener(this); 302 } 303 } 304 305 public void addLookupListener(LookupListener l) { 306 assert false; 307 } 308 309 public void removeLookupListener(LookupListener l) { 310 assert false; 311 } 312 313 public Collection<T> allInstances() { 314 assert false; 315 return null; 316 } 317 318 public void resultChanged(LookupEvent ev) { 319 ProxyResult r = (ProxyResult)result.get(); 320 if (r != null) { 321 r.resultChanged(ev); 322 } else { 323 source.removeLookupListener(this); 324 } 325 } 326 327 public Collection<? extends Item<T>> allItems() { 328 assert false; 329 return null; 330 } 331 332 public Set<Class <? extends T>> allClasses() { 333 assert false; 334 return null; 335 } 336 } } 338 | Popular Tags |