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.ImplOfTheAPI
(This is more easily done using the @ServiceProvider annotation.)
com.foo.impl.ImplOfTheAPI:
import org.openide.util.Lookup; return 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).