For a program I was writing (GCenter – a productivity tool – saves you time by minimizing the time it takes to load your games), I found it necessary to create a plugin architecture with Java and ClassLoader. (I expect Scout449 to eventually use a similar system, although probably with cleaner code.) My code has several cheap hacks, but remains an effective demonstration of a decent plugin system.
Java lends itself particularly well to plugin systems, since classes are loaded dynamically anyway. The idea of a plugin system is to modify how Java loads things. Normally, Java will load your program from the class files in its directory or jar file. When creating a plugin architecture, you want it to also load classes from different jar files (generally the jar files in a certain directory). The solution is to create your own version of the ClassLoader.
Most of the code below is just to navigate the jar files. In the execution of the application, a PluginReader is created for each jar file in the plugin directory. The read() method is then called (line 39), which first fetches a manifest file named “MANIFEST.GMF” which contains the name the actual plugin class (the class that has information like author’s name, as well as functions for starting the plugin running). This class is then loaded, and the class itself is registered with PluginUtils, so that it shows up as an option on the application screen. Then, all the other classes are loaded via the same method (but they are not registered), so that they can be used by the plugin. Finally, copyFiles is called, which copies the entire contents of the jar file to a temporary directory, so that the plugin can fetch graphics and stuff if it wants (using a path conversion method that takes a jar file path and turns it into a temporary directory path).
The real meat is at the very end: line 206 and on. Here, we define a ClassLoader that takes as an argument to its constructor a JarFile, and can be used to load classes from that JarFile. But the real beauty of the ClassLoader is not simply that we can load classes from a jar file, its that when those classes then want to load more classes or find more resources, it is still done within the context of the jar file. Which means that we don’t have to be 100% thorough, we just have to get the plugin going – Java will be happy to handle the rest for us.
Creating a class is simple. We just have to read in a .class file and call the ClassLoader’s defineClass method – in this instance, using our own createClass method as a proxy (just for convenience).