OBO-Edit: Writing Plugins for OBO-Edit 2.0

From GO Wiki
Jump to navigation Jump to search

The master copy of this text is now in the OBO-Edit2 Help Guide under the Tools and Plugins section

It's very simple to write plugins for OBO-Edit 2.0. In OBO-Edit, a plugin can be anything. Tasks, gui components, data adapters, menu items, button icons, it doesn't matter.

When Plugins are Loaded

Plugin loading is almost the very first step of the OBO-Edit startup process. Plugins are loaded after the preferences directories are initialized and logging is configured, but before any other step in the process, including the initialization of default data adapters, gui components, or tasks.

Some plugins may need to execute later in the startup process. For example, a plugin that needs to disable some default gui component may need to execute after the default gui components have been created. Plugins like this should install a GUITask using the method GUIManager.installStartupTask. Startup tasks are executed after the default startup routine has completed, but before the application gui appears on the screen.

Where OBO-Edit Looks for Plugins

OBO-Edit plugins must be archived in a jar file whose name ends with the ".jar" suffix. OBO-Edit looks for jars in two places:

  1. The path <OBO-Edit Installation Dir>/extensions
  2. The path ~/.oboedit/extensions
    • Note that on Windows, the path ~ usually resolves to C:\Documents and Settings\<your user name>
    • Also note that beta versions of OBO-Edit use the directory ~/.oboeditbeta/extensions, because OBO-Edit beta releases store all their settings in ~/.oboeditbeta

Note that other BBOP framework applications (like Phenote 2) use a similar plugin system, but may look for their plugins in different locations. For example, Phenote 2 looks for plugins in the ~/.phenote/extensions directory.

The Easy Way to Write 99% of Plugins

Most plugins will do one of the following:

  • Create a task that does something at startup
  • Create a task that listens for some kind of event as the program runs
  • Add a new gui component
  • Add a new data adapter
  • Add a new search criterion
  • Add a new renderer field

If your plugin does one of these things, all you have to do is include the plugin classes in a jar file, and you're done. OBO-Edit will analyze the contents of the jar and automatically install all the classes it recognizes.

There's only one rule your plugin has to follow: it must have a public, zero-argument constructor.

If your plugin requires additional libraries, put those libraries in a directory called "lib" and zip them right into the jar file with the rest of the classes.

For example, let's say your plugin contains one class called org.bbop.plugin.DatabasePlugin which relies on mysql.jar. Your jar file will contain the following files:

  • org/bbop/plugin/DatabasePlugin.class
  • lib/mysql.jar

OBO-Edit will handle the rest automagically.

What OBO-Edit Does with Plugins

When OBO-Edit finds a plugin jar, it creates a special classloader for that jar and attaches it to the larger OBO-Edit classloader tree. (Each jar gets its own classloader to prevent name clashes between plugins). If the jar contains library jars in the lib/ directory, they are unzipped to a temporary directory and also added to the classpath.

OBO-Edit then examines the .class files in the jar, and creates a catalog of the classes included in each jar.

When PluginManager.instantiateAll(Class) is called (usually by OBO-Edit's startup routine), all the plugin classes of a given type are instantiated and returned to the calling method. The calling method then typically does whatever is required to install those classes.

Getting More Specific About What to Load

Sometimes, you may not want OBO-Edit to load every class in your plugin that it recognizes. For example, if your plugin only installs a new GUIComponent under certain circumstances, you won't want that component to be loaded automatically - instead, you'll probably want to install a single GUITask that can recognizes the circumstances where the new component should be installed, and have that task do the installation when appropriate.

If you only want certain classes to be loaded, place a file called install.xml in the root directory of your jar file. install.xml should contain an XML encoded Java bean that instantiates the class PluginManager.InstallerConfig. InstallerConfig returns a list of classes and libraries that should be automatically installed when the plugin is loaded. Any classes that are not explicitly mentioned will be loaded by the classloader (and will thus be available to any plugin classes that depend on them), but will not be automatically installed. Any libraries that are not explicitly mentioned will be ignored.

For example, imagine that we want to install a single class called MyTask and a single library located in mylibs/log4j.jar. The following code will generate the installer.xml file that should be placed in the plugin jar.

 PluginManager.InstallerConfig config = new PluginManager.InstallerConfig();
 Collection<String> classes = new ArrayList<String>();
 Collection<String> libs = new ArrayList<String>();
 try {
   XMLEncoder encoder = new XMLEncoder("installer.xml");
 } catch (Exception ex) {
  // do something with exception

Shared Libraries

If many plugins end up using the same libraries, you may wish to save space by sharing the library amongst all the plugins, rather than packaging the library inside each plugin jar.

Shared libraries may be placed within the shared/ subdirectory of any directory from which plugins are loaded (for example, in OBO-Edit a shared library may be placed in ~/.oboedit/extensions/shared or installationdir/extensions/shared.