Hello i want to discover at runtime classes in the classpath which implements a defined interface. ServiceLoader suits well (i think, i haven't used it), but i need do it in Java 1.5.
any ideas?
Hello i want to discover at runtime classes in the classpath which implements a defined interface. ServiceLoader suits well (i think, i haven't used it), but i need do it in Java 1.5.
any ideas?
There is no reliable way to know what classes are in the classpath. According to its documentation, ServiceLoader relies on external files to tell it what classes to load; you might want to do the same. The basic idea is to have a file with the name of the class(es) to load, and then use reflection to instantiate it/them.
There's nothing built into Java 1.5 for this. I implemented it myself; it's not too complicated. However, when we upgrade to Java 6, I will have to replace calls to my implementation with calls to ServiceLoader
. I could have defined a little bridge between the app and the loader, but I only use it in a few places, and the wrapper itself would be a good candidate for a ServiceLoader.
This is the core idea:
public <S> Iterable<S> load(Class<S> ifc) throws Exception {
ClassLoader ldr = Thread.currentThread().getContextClassLoader();
Enumeration<URL> e = ldr.getResources("META-INF/services/" + ifc.getName());
Collection<S> services = new ArrayList<S>();
while (e.hasMoreElements()) {
URL url = e.nextElement();
InputStream is = url.openStream();
try {
BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8"));
while (true) {
String line = r.readLine();
if (line == null)
break;
int comment = line.indexOf('#');
if (comment >= 0)
line = line.substring(0, comment);
String name = line.trim();
if (name.length() == 0)
continue;
Class<?> clz = Class.forName(name, true, ldr);
Class<? extends S> impl = clz.asSubclass(ifc);
Constructor<? extends S> ctor = impl.getConstructor();
S svc = ctor.newInstance();
services.add(svc);
}
}
finally {
is.close();
}
}
return services;
}
Better exception handling is left as an exercise for the reader. Also, the method could be parameterized to accept a ClassLoader of the caller's choosing.
ServiceLoader is quite basic, and has been in use (informally) within the JDK since 1.3. ServiceLoader just finally made it a first class citizen. It simply looks for a resource file named for your interface, which is basically bundled in the META-INF directory of a library jar.
That file contains the name of the class to load.
So, you'd have a file named:
META-INF/services/com.example.your.interface
and inside it is a single line: com.you.your.interfaceImpl.
In lieu of ServiceLoader, I like Netbeans Lookup. It works with 1.5 (and maybe 1.4).
Out of the box, it does the exact same thing as ServiceLoader, and it's trivial to use. But it offers a lot more flexibility.
Here's a link: http://openide.netbeans.org/lookup/
Here's a article about ServiceLoader, but it mentions Netbeans Lookup at the bottom: http://weblogs.java.net/blog/timboudreau/archive/2008/08/simple_dependen.html