Plugin system

From OpenRocket wiki
Revision as of 14:31, 26 September 2012 by Plaa (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

The Problem

There are many cases where it is desirable to add a feature to openrocket which is useful in a specific context, but not really appropriate for inclusion in openrocket core. For this reason it is desirable to have some kind of plugin framework, as is found in many other applications.

In our case we refer to plugins as something that is installed onto the user's computer which is found by OR and provides additional functionality. The functionality might be simulation listeners, new motor types etc.

Type of plugins

A list of different use-cases for plugins which have different kinds of requirements:

  • Simulation listeners: Tied to a specific simulation, possible to select from a menu and configurable via a UI. Configuration needs to be stored/loaded from the ORK file.
  • Auxilliary tools: Plugin adds options to some menu on the main window. Plugin may interact or modify the rocket. (Similar to rocket optimization)
  • Optimization modifiers/targets: Defining new types of optimization targets or parameters.
  • Startup tips: New startup tip types. (Not implemented yet)
  • New motor types
  • New simulation / aerodynamic computation engines

Some of these may be singletons, others contain state and need to be instantiated properly.


Requirements

  • Configuration
 * Some plugins need configuration via a UI
 * How to distinguish what is part of core and what is a plugin?
  • Automatic discovery
 * Drop a JAR to the plugin folder and it will be used.
  • Localisation support
  • Dependency management
 * Some plugins may depend on others and be able to automatically load them. This in turn requires that plugins have a consistent identifier / URI and version number.
 * I don't think we need plugin dependency management in the foreseeable future, and such a system may complicate things considerably. -Sampo
  • Plugins implemented in other languages
 * Should be possible to create a plugin that allows writing other plugins in scripting languages (e.g. JavaScript/Ruby)
  • Simplified access to openrocket document / software state
 * E.g. currently selected component

Anti requirements

(Discuss)

Implementation

Plugin frameworks

Various plug-in frameworks exist for java, and may significantly reduce the time required to implement the plugin feature.

Directly coding the plug-in just requires the new interface to extend the Plugin interface and to add the annotations to the implementation class. This is a simple and light-weight solution which may well be quite suitable.

Of the alternative plug-in frameworks which exist, the most interesting is JSPF (http://code.google.com/p/jspf/). Here you can just say "load all JAR files from this directory as plug-ins" and "add all plug-ins from the current classpath". You can then query for plug-ins using a variety of methods. It seems very simple to use, it uses pojos and pure interfaces, and plug-ins themselves are made just by implementing the interface and adding some annotations.

JSPF also seems to work on Android, though the discovery system is somewhat dysfunctional, and you need to list all of the plug-in classes explicitly (http://code.google.com/p/jspf/wiki/RunningOnAndroid). This should be okay, we just need to have an additional implementation for Android that lists the necessary plug-ins for the basic functionality. I don't see it as a problem if some of the extensibility is missing on Android.

Other frameworks that have been considered:

  • ServiceLoader class + startup scripting. Simple, built-in, but we

need to implement the plug-in system ourselves.

configurable than JSPF, but not sure do we need the extra muscle. Looks functional, but last activity was in 2007.

service discovery mechanism, similar to (or used by) Eclipse plug-in system.

  • Java Module System (JSR 277), slated for inclusion to Java 7, but

wasn't. Seems pretty inactive (early draft from 2006) and seems to include language changes.

A Rough Design (from a plugin writers point of view)

General operation:

The name for each plugin will correspond to an item in the plugins menu. Subitems of each item in the plugins menu will be automatically generated as follows:

  • About plugin : makes an about box, present for all plugins.
  • for each 'enableable' modifier, a check box of the form [X] Enable ModifierName will be generated. When enabled, the enable method of the modifier will be called. This would then do what is necessary to modify OR to always run the plugin code, for example: make the simulation always load the simulation modifier.
  • for each 'configurable' modifier, an item which opens the configuration window
  • any additional menu items as defined in each modifier. For example, a rocket modifier might have an item which changes the selected component in some way.

Code design:

interface Plugin:
 - name, version, URI, date, author, licence, description
 - list of dependent plugin URI's and versions
 - list of conflicting plugin URI's and versions
 - list of modifiers
abstract class AbstractPlugin implements Plugin:
 * everything required for loading, setting menu, translations etc
 - getSetting(key), setSetting(key, value) : a simple mechanism for locally storing various settings
 - getFile(name), storeFile(file), rmfile(name) : a simple mechanism for locally storing cache files etc
static class MyPlugin extends AbstractPlugin:
 * the users implementation
files:
 messages_?.properties : translations to use, inside plugin jar
interface Modifier:
 - plugin this modifier is a member of
 - enableable boolean
 - enable(), disable()
 - configurable boolean
 - configurator
 - additional menu items and actions
abstract class RocketModifier implements Modifier:
 - enable(), disable() : 
 - getSelectedComponent() : returns currently selected rocket component
 - onChange() : called when a component is changed
 * various other helper methods as necessary
static class MyRocketModifier:
 * the users implementation of something that works with or modifies the rocket design
abstract class SimulationModifier implements Modifier:
 * basically everything currently in simulation listeners, possibly simplified (do we need 3 separate interfaces?)
static class MySimulationModifier extends AbstractSimulationModifier:
 * the users implementation
abstract class configurator:
 a class which automatically generates a standardised configuration dialog box based on just a simple list of variables and selectors.
 Variables would be saved automatically when the OK button is clicked using plugin setSettings().