1 19 package org.openide.util.lookup; 20 21 import org.openide.util.Lookup; 22 import org.openide.util.LookupListener; 23 24 import java.util.*; 25 26 27 31 final class ExcludingLookup extends org.openide.util.Lookup { 32 33 private Lookup delegate; 34 35 36 private Object classes; 37 38 42 ExcludingLookup(Lookup delegate, Class [] classes) { 43 this.delegate = delegate; 44 45 if (classes.length == 1) { 46 this.classes = classes[0]; 47 } else { 48 this.classes = classes; 49 } 50 } 51 52 public String toString() { 53 return "ExcludingLookup: " + delegate + " excludes: " + Arrays.asList(classes()); } 55 56 public <T> Result<T> lookup(Template<T> template) { 57 if (template == null) { 58 throw new NullPointerException (); 59 } 60 61 if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) { 62 return Lookup.EMPTY.lookup(template); 64 } 65 66 return new R<T>(template.getType(), delegate.lookup(template)); 67 } 68 69 public <T> T lookup(Class <T> clazz) { 70 if (areSubclassesOfThisClassAlwaysExcluded(clazz)) { 71 return null; 72 } 73 74 T res = delegate.lookup(clazz); 75 76 if (isObjectAccessible(clazz, res, 0)) { 77 return res; 78 } else { 79 return null; 80 } 81 } 82 83 public <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) { 84 if (areSubclassesOfThisClassAlwaysExcluded(template.getType())) { 85 return null; 86 } 87 88 Lookup.Item<T> retValue = delegate.lookupItem(template); 89 90 if (isObjectAccessible(template.getType(), retValue, 2)) { 91 return retValue; 92 } else { 93 return null; 94 } 95 } 96 97 99 private boolean areSubclassesOfThisClassAlwaysExcluded(Class <?> c) { 100 Class <?>[] arr = classes(); 101 102 for (int i = 0; i < arr.length; i++) { 103 if (arr[i].isAssignableFrom(c)) { 104 return true; 105 } 106 } 107 108 return false; 109 } 110 111 113 final Class <?>[] classes() { 114 if (classes instanceof Class []) { 115 return (Class []) classes; 116 } else { 117 return new Class [] { (Class ) classes }; 118 } 119 } 120 121 125 private static boolean isAccessible(Class <?>[] barriers, Class <?> from, Class <?> to) { 126 if ((to == null) || !from.isAssignableFrom(to)) { 127 return false; 129 } 130 131 for (int i = 0; i < barriers.length; i++) { 132 if (to == barriers[i]) { 133 return false; 134 } 135 } 136 137 if (from == to) { 138 return true; 139 } 140 141 if (isAccessible(barriers, from, to.getSuperclass())) { 145 return true; 146 } 147 148 Class [] interfaces = to.getInterfaces(); 149 150 for (int i = 0; i < interfaces.length; i++) { 151 if (isAccessible(barriers, from, interfaces[i])) { 152 return true; 153 } 154 } 155 156 return false; 157 } 158 159 165 private final boolean isObjectAccessible(Class from, Object to, int type) { 166 if (to == null) { 167 return false; 168 } 169 170 return isObjectAccessible(classes(), from, to, type); 171 } 172 173 180 static final boolean isObjectAccessible(Class [] barriers, Class from, Object to, int type) { 181 if (to == null) { 182 return false; 183 } 184 185 switch (type) { 186 case 0: 187 return isAccessible(barriers, from, to.getClass()); 188 189 case 1: 190 return isAccessible(barriers, from, (Class ) to); 191 192 case 2: { 193 Item item = (Item) to; 194 195 return isAccessible(barriers, from, item.getType()); 196 } 197 198 default: 199 throw new IllegalStateException ("Type: " + type); 200 } 201 } 202 203 205 final <E, T extends Collection<E>> T filter( 206 Class <?>[] arr, Class <?> from, T c, int type, T prototype 207 ) { 208 T ret = null; 209 210 211 TWICE: 213 for (;;) { 214 Iterator<E> it = c.iterator(); 215 BIG: 216 while (it.hasNext()) { 217 E res = it.next(); 218 219 if (!isObjectAccessible(arr, from, res, type)) { 220 if (ret == null) { 221 ret = prototype; 224 continue TWICE; 225 } 226 227 continue BIG; 228 } 229 230 if (ret != null) { 231 ret.add(res); 233 } 234 } 235 236 break TWICE; 238 } 239 240 return (ret != null) ? ret : c; 241 } 242 243 245 private final class R<T> extends WaitableResult<T> implements LookupListener { 246 private Result<T> result; 247 private Object listeners; 248 private Class <?> from; 249 250 R(Class <?> from, Result<T> delegate) { 251 this.from = from; 252 this.result = delegate; 253 } 254 255 protected void beforeLookup(Template t) { 256 if (result instanceof WaitableResult) { 257 ((WaitableResult) result).beforeLookup(t); 258 } 259 } 260 261 public void addLookupListener(LookupListener l) { 262 boolean add; 263 264 synchronized (this) { 265 listeners = AbstractLookup.modifyListenerList(true, l, listeners); 266 add = listeners != null; 267 } 268 269 if (add) { 270 result.addLookupListener(this); 271 } 272 } 273 274 public void removeLookupListener(LookupListener l) { 275 boolean remove; 276 277 synchronized (this) { 278 listeners = AbstractLookup.modifyListenerList(false, l, listeners); 279 remove = listeners == null; 280 } 281 282 if (remove) { 283 result.removeLookupListener(this); 284 } 285 } 286 287 public Collection<? extends T> allInstances() { 288 return openCol(result.allInstances(), 0); 289 } 290 291 private <S> Collection<S> openCol(Collection<S> c, int type) { 292 return filter(classes(), from, c, type, new ArrayList<S>(c.size())); 293 } 294 295 public Set<Class <? extends T>> allClasses() { 296 return filter(classes(), from, result.allClasses(), 1, new HashSet<Class <? extends T>>()); 297 } 298 299 public Collection<? extends Item<T>> allItems() { 300 return openCol(result.allItems(), 2); 301 } 302 303 public void resultChanged(org.openide.util.LookupEvent ev) { 304 if (ev.getSource() == result) { 305 collectFires(null); 306 } 307 } 308 309 protected void collectFires(Collection<Object > evAndListeners) { 310 LookupListener[] arr; 311 312 synchronized (this) { 313 if (listeners == null) { 314 return; 315 } 316 317 if (listeners instanceof LookupListener) { 318 arr = new LookupListener[] { (LookupListener) listeners }; 319 } else { 320 ArrayList<?> l = (ArrayList<?>) listeners; 321 arr = l.toArray(new LookupListener[l.size()]); 322 } 323 } 324 325 final LookupListener[] ll = arr; 326 final org.openide.util.LookupEvent newev = new org.openide.util.LookupEvent(this); 327 AbstractLookup.notifyListeners(ll, newev, evAndListeners); 328 } 329 } 330 } 331 | Popular Tags |