@@ -, +, @@ * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun * Microsystems, Inc. All Rights Reserved. */ * to META-INF/services/name.of.class files. * * @author Jaroslav Tulach */ /** a set of all requested classes */ private WeakSet classes = new WeakSet (); /** class loader to use */ private ClassLoader loader; /** Constructor */ public ManifestLookup() { // JST: is there a better way to listen on changes of modules? Lookup.Result res = Lookup.getDefault ().lookup (new Template (ClassLoader.class)); res.addLookupListener( (LookupListener)WeakListener.create (LookupListener.class, this, res) ); // do init right now resultChanged (null); } /** (Re)initilize the lookup. */ public void resultChanged(LookupEvent ev) { ArrayList arr = new ArrayList (); synchronized (this) { loader = (ClassLoader)Lookup.getDefault ().lookup (ClassLoader.class); if (loader == null) { loader = getClass ().getClassLoader (); } Iterator it = classes.iterator (); while (it.hasNext ()) { Class c = (Class)it.next (); search (c, arr); } } setPairs (arr); } /** Tries to load appropriate resources from manifest files. */ protected synchronized final void beforeLookup (Template t) { Class c = t.getType (); if (classes.add (c)) { // added new class, search for it. ArrayList arr = new ArrayList (); search (c, arr); Iterator it = arr.iterator (); while (it.hasNext ()) { Pair p = (Pair)it.next (); addPair (p); } } } /** Finds all pairs and adds them to the collection. * * @param clazz class to find * @param result collection to add Pair to */ private void search (Class clazz, Collection result) { try { String res = "META-INF/services/" + clazz.getName (); Enumeration en = loader.getResources(res); while (en.hasMoreElements ()) { URL url = (URL)en.nextElement (); BufferedReader reader = new BufferedReader (new InputStreamReader (url.openStream ())); for (;;) { String line = reader.readLine (); if (line == null) break; line = line.trim (); if (line.charAt (0) == '#') continue; Class inst = Class.forName(line, false, loader); result.add (new P (inst)); } reader.close (); } } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } } /** Pair that holds name of a class. */ private static final class P extends Pair { /** either Class or Object if the instance has been created */ private Object object; public P (Class clazz) { this.object = clazz; } /** Finds the class. */ private Class clazz () { Object o = object; if (o instanceof Class) { return (Class)o; } else { return o.getClass (); } } public boolean equals (Object o) { if (o instanceof P) { return ((P)o).clazz ().equals (clazz ()); } return false; } public int hashCode () { return clazz ().hashCode (); } /** Tests whether this item can produce object * of class c. */ protected boolean instanceOf(Class c) { return c.isAssignableFrom (clazz ()); } /** Get the implementing class of the instance. * @return the class of the item */ public Class getType() { return clazz (); } /** Get the instance itself. * @return the instance */ public synchronized Object getInstance() { if (object instanceof Class) { try { object = ((Class)object).newInstance (); } catch (Exception ex) { ex.printStackTrace(); // what now? object = ex; } } return object; } /** Get a human presentable name for the item. * This might be used when summarizing all the items found in a * lookup result in some part of a GUI. * @return the string suitable for presenting the object to a user */ public String getDisplayName() { return clazz ().getName (); } /** Get a persistent indentifier for the item. * This identifier should uniquely represent the item * within its containing lookup (and if possible within the * global lookup as a whole). For example, it might represent * the source of the instance as a file name. The ID may be * persisted and in a later session used to find the same instance * as was encountered earlier, by means of passing it into a * lookup template. * * @return a string ID of the item */ public String getId() { return clazz ().getName (); } /** Method that can test whether an instance of a class has been created * by this item. * * @param obj the instance * @return if the item has already create an instance and it is the same * as obj. */ protected boolean creatorOf(Object obj) { return obj == object; } } public static void main (String[] args) throws Exception { Class c = Class.forName ("org.openide.loaders.DataLoader"); System.out.println("now"); long time = System.currentTimeMillis (); ManifestLookup l = new ManifestLookup (); Object obj = l.lookup (c); System.out.println("obj: " + obj); System.out.println("then: " + (System.currentTimeMillis () - time)); Result res = l.lookup (new Template (c)); res.addLookupListener (new LookupListener () { public void resultChanged (LookupEvent ev) { System.out.println("change: " + ev); } }); Thread.sleep (10000); System.out.println("end"); } */