Listing loaded classes implementing a given interface

J

Julien Lafaye

Hello,

I am working on a plugin sub-system for an application I develop on my own.

Each plugin must be a class implementing a specific interface (say
MyInterface). They must be available, either within the application package
or through third party jars.

When I start-up my system, I want to be able to list all the plugins, i.e.
all the classes implementing MyInterface.

My question: is there a way to list all the class in the classpath of the
running application ?

Thanks in advance.

Julien

PS: I noticed some projects use a configuration file listing all plugin
classes. I wanted to do it automatically.
 
S

Stefan Ram

Julien Lafaye said:
My question: is there a way to list all the class in the
classpath of the running application ?

Then why is the subject »Listing loaded classes«? Either you
want to list loaded classes or classes from the classpath.

A similar operation exists in the library »ram.jar«.
This operation is based on Code by Ralf Ullrich.

One can find all classes of a jar that have any chosen
property, as long as this property can be obtained from the
class reference.

For example, to find all classes implementing »java.util.Map«,
one sets a filter accepting only classes which
»java.util.Map« is assignable from:

public boolean accepts( final java.lang.Class class_ )
{ return java.util.Map.class.isAssignableFrom( class_ ); }

One also needs to provide a starting class to find the jar, which
is done as follows.

public java.lang.String entryPath(){ return "java.lang.Object"; }

The jar containing this type will be chosen for exploration.

However, the client does not need to specify this »entryPath«,
as "java.lang.Object" is the default obtained by extending
»de.dclj.ram.java.lang.reflect.Finder.DefaultSpecification«.

The example client is:

public class Main
{ /* based on an idea and on code by Ralf Ullrich from 2006 */

public static void main( final java.lang.String[] args )
{ new de.dclj.ram.java.lang.reflect.Finder
( new de.dclj.ram.java.lang.reflect.Finder.DefaultSpecification()
{
public boolean isClassFinder(){ return true; }

public boolean accepts( final java.lang.Class class_ )
{ return java.util.Map.class.isAssignableFrom( class_ ); }

}).inspectJar(); }}

class java.lang.ProcessEnvironment
class java.rmi.server.RemoteObjectInvocationHandler$MethodToHash_Maps$1
class java.security.AuthProvider
(...)
class java.util.Properties
class java.util.Hashtable
interface java.util.Map

The library »ram.jar« is an early publication in alpha state,
it is experimental, changing, and mostly undocumented. See:

http://www.purl.org/stefan_ram/pub/ram-jar
 
H

Hosam Aly

I suggest using an easier approach:
1) Make a standard folder for plugins, and load all the classes in it.
2) Register the plugin classes. There are two ways to do this:
a) When loading the classes, check each one of them whether it
implements your interface.
b) Put in the specification of plugins that they have to register
themselves in a class of yours while loading. In other words, every
plugin should call "YourRegisterClass.register(ThePluginClass)", and
your method will validate that they implement the interface, and store
them in a list or something. (I prefer this way.)
 
T

Twisted

I suggest using an easier approach:
1) Make a standard folder for plugins, and load all the classes in it.
2) Register the plugin classes. There are two ways to do this:
a) When loading the classes, check each one of them whether it
implements your interface.
b) Put in the specification of plugins that they have to register
themselves in a class of yours while loading. In other words, every
plugin should call "YourRegisterClass.register(ThePluginClass)", and
your method will validate that they implement the interface, and store
them in a list or something. (I prefer this way.)

My idea is this:
1) Make a standard folder for plugins, and put it on the app's class
path
2) Have a Plugin interface
3) Put each plugin, all its dependencies not in the app's jar or
rt.jar, and a serialized instance with a particular filename extension
in the plugins folder.
4) The app looks for those serialized instances, and reads them. Any
that throw exceptions or otherwise fail are logged and skipped.
5) It casts them to Plugin. Again those that throw ClassCastException
are logged. The rest are put in a collection or something, a
Set<Plugin> say.
6) The objects in the collection may then do all kinds of things. They
might have encode/decode methods if they are codecs. Factory methods
to make a document type and its viewer and editor UI components, or
pluggable GUI controls, or whatever. Provide a Swing PLAF somehow
(likely as a factory). Be a video game level, playable character, or
some such. Whatever. The sky is truly the limit.

No extra config file to mess with; just drop the instance file and the
class files into Plugins. Maybe these should be bundled in jars
dropped in Plugins.

Fail-safe behavior if a plugin install is botched.

Type-safe use of plugins. (Different interfaces for different
pluggable capabilities might be expected in different subdirectories,
such as plugins/codecs and plugins/visualization in an audio player.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,189
Members
46,735
Latest member
HikmatRamazanov

Latest Threads

Top