1 19 20 package org.netbeans.api.debugger; 21 22 import java.io.BufferedReader ; 23 import java.io.IOException ; 24 import java.io.InputStream ; 25 import java.io.InputStreamReader ; 26 import java.lang.reflect.Constructor ; 27 import java.lang.reflect.InvocationTargetException ; 28 import java.lang.reflect.Method ; 29 import java.net.URL ; 30 import java.util.ArrayList ; 31 import java.util.Collection ; 32 import java.util.Collections ; 33 import java.util.Enumeration ; 34 import java.util.HashMap ; 35 import java.util.HashSet ; 36 import java.util.Iterator ; 37 import java.util.LinkedHashMap ; 38 import java.util.List ; 39 import java.util.Map ; 40 import java.util.Set ; 41 42 import org.netbeans.spi.debugger.ContextProvider; 43 import org.openide.ErrorManager; 44 45 46 50 abstract class Lookup implements ContextProvider { 51 52 public Object lookupFirst (String folder, Class service) { 53 List l = lookup (folder, service); 54 if (l.isEmpty ()) return null; 55 return l.get (0); 56 } 57 58 public abstract List lookup (String folder, Class service); 59 60 61 private static boolean verbose = 62 System.getProperty ("netbeans.debugger.registration") != null; 63 64 65 static class Instance extends Lookup { 66 private Object [] services; 67 68 Instance (Object [] services) { 69 this.services = services; 70 } 71 72 public List lookup (String folder, Class service) { 73 ArrayList l = new ArrayList (); 74 int i, k = services.length; 75 for (i = 0; i < k; i++) 76 if (service.isAssignableFrom (services [i].getClass ())) { 77 l.add (services [i]); 78 if (verbose) 79 System.out.println("\nR instance " + services [i] + 80 " found"); 81 } 82 return l; 83 } 84 85 } 86 87 static class Compound extends Lookup { 88 private Lookup l1; 89 private Lookup l2; 90 91 Compound (Lookup l1, Lookup l2) { 92 this.l1 = l1; 93 this.l2 = l2; 94 setContext (this); 95 } 96 97 public List lookup (String folder, Class service) { 98 List l = new LookupList(null); 99 l.addAll (l1.lookup (folder, service)); 100 l.addAll (l2.lookup (folder, service)); 101 return l; 102 } 103 104 void setContext (Lookup context) { 105 if (l1 instanceof Compound) ((Compound) l1).setContext (context); 106 if (l1 instanceof MetaInf) ((MetaInf) l1).setContext (context); 107 if (l2 instanceof Compound) ((Compound) l2).setContext (context); 108 if (l2 instanceof MetaInf) ((MetaInf) l2).setContext (context); 109 } 110 } 111 112 static class MetaInf extends Lookup { 113 114 private static final String HIDDEN = "-hidden"; 116 private String rootFolder; 117 private HashMap registrationCache = new HashMap (); 118 private HashMap instanceCache = new HashMap (); 119 private Lookup context; 120 121 122 MetaInf (String rootFolder) { 123 this.rootFolder = rootFolder; 124 } 125 126 void setContext (Lookup context) { 127 this.context = context; 128 } 129 130 public List lookup (String folder, Class service) { 131 List l = list (folder, service); 132 133 Set s = null; 134 int i, k = l.size (); 135 for (i = 0; i < k; i++) { 136 String className = (String ) l.get (i); 137 if (className.endsWith(HIDDEN)) { 138 if (s == null) { 139 s = new HashSet (); 140 } 141 s.add(className.substring(0, className.length() - HIDDEN.length())); 142 } 143 } 144 145 LookupList ll = new LookupList (s); 146 for (i = 0; i < k; i++) { 147 String className = (String ) l.get (i); 148 if (className.endsWith(HIDDEN)) continue; 149 if (s != null && s.contains (className)) continue; 150 Object instance = null; 151 instance = instanceCache.get (className); 152 if (instance == null) { 153 instance = createInstance (className); 154 instanceCache.put (className, instance); 155 } 156 if (instance != null) 157 ll.add (instance, className); 158 } 159 return ll; 160 } 161 162 private List list (String folder, Class service) { 163 String name = service.getName (); 164 String resourceName = "META-INF/debugger/" + 165 ((rootFolder == null) ? "" : rootFolder + "/") + 166 ((folder == null) ? "" : folder + "/") + 167 name; 168 if (!registrationCache.containsKey (resourceName)) 169 registrationCache.put (resourceName, loadMetaInf (resourceName)); 170 return (List ) registrationCache.get (resourceName); 171 } 172 173 177 private ArrayList loadMetaInf ( 178 String resourceName 179 ) { 180 ArrayList l = new ArrayList (); 181 try { 182 ClassLoader cl = (ClassLoader ) org.openide.util.Lookup. 183 getDefault ().lookup (ClassLoader .class); 184 String v = "\nR lookup " + resourceName; 185 Enumeration e = cl.getResources (resourceName); 186 while (e.hasMoreElements ()) { 187 URL url = (URL ) e.nextElement(); 188 InputStream is = url.openStream (); 189 if (is == null) continue; 190 BufferedReader br = new BufferedReader ( 191 new InputStreamReader (is) 192 ); 193 for (String s = br.readLine(); s != null; s = br.readLine()) { 194 if (s.startsWith ("#")) continue; 195 if (s.length () == 0) continue; 196 if (verbose) 197 v += "\nR service " + s + " found"; 198 199 l.add (s); 200 } 201 } 202 if (verbose) 203 System.out.println (v); 204 return l; 205 } catch (IOException e) { 206 e.printStackTrace (); 207 } 208 throw new InternalError ("Can not read from Meta-inf!"); 209 } 210 211 private Object createInstance (String service) { 212 try { 213 ClassLoader cl = (ClassLoader ) org.openide.util.Lookup. 214 getDefault ().lookup (ClassLoader .class); 215 String method = null; 216 if (service.endsWith("()")) { 217 int lastdot = service.lastIndexOf('.'); 218 if (lastdot < 0) { 219 ErrorManager.getDefault().log("Bad service - dot before method name is missing: " + 220 "'" + service + "'."); 221 return null; 222 } 223 method = service.substring(lastdot + 1, service.length() - 2).trim(); 224 service = service.substring(0, lastdot); 225 } 226 Class cls = cl.loadClass (service); 227 228 Object o = null; 229 if (method != null) { 230 Method m = null; 231 if (context != null) { 232 try { 233 m = cls.getDeclaredMethod(method, new Class [] { Lookup.class }); 234 } catch (NoSuchMethodException nsmex) {} 235 } 236 if (m == null) { 237 try { 238 m = cls.getDeclaredMethod(method, new Class [] { }); 239 } catch (NoSuchMethodException nsmex) {} 240 } 241 if (m != null) { 242 o = m.invoke(null, (m.getParameterTypes().length == 0) 243 ? new Object [] {} : new Object [] { context }); 244 } 245 } 246 if (o == null && context != null) { 247 Constructor [] cs = cls.getConstructors (); 248 int i, k = cs.length; 249 for (i = 0; i < k; i++) { 250 Constructor c = cs [i]; 251 if (c.getParameterTypes ().length != 1) continue; 252 try { 253 o = c.newInstance (new Object [] {context}); 254 } catch (IllegalAccessException e) { 255 if (verbose) { 256 System.out.println("\nservice: " + service); 257 e.printStackTrace (); 258 } 259 } catch (IllegalArgumentException e) { 260 if (verbose) { 261 System.out.println("\nservice: " + service); 262 e.printStackTrace (); 263 } 264 } 265 } 266 } 267 if (o == null) 268 o = cls.newInstance (); 269 if (verbose) 270 System.out.println("\nR instance " + o + 271 " created"); 272 return o; 273 } catch (ClassNotFoundException e) { 274 ErrorManager.getDefault().notify( 275 ErrorManager.getDefault().annotate( 276 e, 277 "The service "+service+" is not found.") 278 ); 279 } catch (InstantiationException e) { 280 ErrorManager.getDefault().notify( 281 ErrorManager.getDefault().annotate( 282 e, 283 "The service "+service+" can not be instantiated.") 284 ); 285 } catch (IllegalAccessException e) { 286 ErrorManager.getDefault().notify( 287 ErrorManager.getDefault().annotate( 288 e, 289 "The service "+service+" can not be accessed.") 290 ); 291 } catch (InvocationTargetException ex) { 292 ErrorManager.getDefault().notify( 293 ErrorManager.getDefault().annotate( 294 ex, 295 "The service "+service+" can not be created.") 296 ); 297 } catch (ExceptionInInitializerError ex) { 298 ErrorManager.getDefault().notify( 299 ErrorManager.getDefault().annotate( 300 ex, 301 "The service "+service+" can not be initialized.") 302 ); 303 } 304 return null; 305 } 306 307 } 308 309 313 private static final class LookupList extends ArrayList { 314 315 private Set hiddenClassNames; 316 private LinkedHashMap instanceClassNames = new LinkedHashMap (); 317 318 public LookupList(Set hiddenClassNames) { 319 this.hiddenClassNames = hiddenClassNames; 320 } 321 322 void add(Object instance, String className) { 323 super.add(instance); 324 instanceClassNames.put(instance, className); 325 } 326 327 public boolean addAll(Collection c) { 328 if (c instanceof LookupList) { 329 LookupList ll = (LookupList) c; 330 Set newHiddenClassNames = ll.hiddenClassNames; 331 if (newHiddenClassNames != null) { 332 for (Iterator it = newHiddenClassNames.iterator(); it.hasNext(); ) { 334 String className = (String ) it.next(); 335 if (instanceClassNames.containsValue(className)) { 336 for (Iterator ii = instanceClassNames.keySet().iterator(); it.hasNext(); ) { 337 Object instance = ii.next(); 338 if (className.equals(instanceClassNames.get(instance))) { 339 remove(instance); 340 instanceClassNames.remove(instance); 341 break; 342 } 343 } 344 } 345 } 346 if (hiddenClassNames != null) { 347 hiddenClassNames.addAll(newHiddenClassNames); 348 } else { 349 hiddenClassNames = newHiddenClassNames; 350 } 351 } 352 ensureCapacity(size() + ll.size()); 353 boolean addedAnything = false; 354 for (Iterator it = ll.iterator(); it.hasNext(); ) { 355 Object instance = it.next(); 356 String className = (String ) ll.instanceClassNames.get(instance); 357 if (hiddenClassNames == null || !hiddenClassNames.contains(className)) { 358 add(instance, className); 359 addedAnything = true; 360 } 361 } 362 return addedAnything; 363 } else { 364 return super.addAll(c); 365 } 366 } 367 368 } 369 370 } 371 | Popular Tags |