This document describes usage of the API provided by the Lookup Library. In this document we assume that someone has already provided us with a lookup implementation (for those seeking how to write a lookup implementation please check the SPI document).
public static Lookup getDefault()The object returned from this method is a global lookup that can serve as a central place for registering services. The default implementation is a lookup that implements the JDK JAR services mechanism and delegates to META-INF/services/name.of.Class files.
If you want to add your class to this lookup just create a file in your
jar file under the META-INF
directory (e.g. META-INF/services/com.my.APIClass)
and let the file contain only one line of text
com.foo.impl.ImplOfTheAPIThe following code will return you a newly created instance of
com.foo.impl.ImplOfTheAPI
:
import org.openide.util.Lookup; return (com.my.APIClass)Lookup.getDefault().lookup(com.my.APIClass.class);
Note: If you use Lookup.Template, the object returned from the lookup is not the object you are looking for but rather a result object (Lookup.Result). You can call methods on such a result object to get the actual results.
Let's examine following example:
import org.openide.util.Lookup; Lookup lookup = ...; Lookup.Template template = new Lookup.Template(MyService.class); Lookup.Result result = lookup.lookup(template); Collection c = result.allInstances(); for (Iterator i = c.iterator(); i.hasNext(); ) { MyService s = (MyService)i.next(); s.callMyService(); }In this example the call to method lookup(...) returns immediately because the result object can be constructed even without real results. The first time you ask for the result object by calling r.allInstances(), the lookup has to supply you the real results and this method can block until the required data are really available.
If you are not interested in all objects as in the previous example, you can use the template to ask for one resulting object (wrapped in special Item instance):
import org.openide.util.Lookup; Lookup lookup = ...; Lookup.Template template = new Lookup.Template(MyService.class); Lookup.Item item = lookup.lookupItem(template); MyService s = (MyService)item.getInstance(); s.callMyService();Again, the Item object can construct the real instance only if you call getInstance. The item can be useful even without calling getInstance - you can get its display name or an unique id. You can use this information, for example, for constructing menu items without the need to instantiate (or even load!) the class implementing the functionality. Only when the real functionality is needed (e.g. the user has selected the menu item) you can call getInstance and call the real meat of the implementation.
So here is some sample code using the listenner:
import org.openide.util.Lookup; import org.openide.util.LookupListener; import org.openide.util.LookupEvent; Lookup lookup = ...; Lookup.Template template = new Lookup.Template(MyService.class); final Lookup.Result result = lookup.lookup(template); result.addLookupListener(new LookupListener() { public void resultChanged(LookupEvent e) { reaction(result); } }); reaction(result); } private static void reaction(Lookup.Result r) { for (Iterator i = r.allInstances().iterator(); i.hasNext(); ) { MyService s = (MyService)i.next(); s.callMyService(); } }Please note that we first attach a listener and then call the reaction method. This ensures that we always get the newest possible state. Also you must be careful in the reaction method since it can be called from two different threads simultaneously (your code has to be prepared for this).