Module PlugMan
In: src/PlugMan.rb

PlugMan is the Plugin Manager for the plugin architecture for ruby applications.

PlugMan is the main interface to the plugin architecture, it manages a register of plugins and also allows plugins to discover other plugins that attached to extension points.

Plugins can:

  1. know about eachother explicitly, via the dependency mechanism (e.g. plugin_A knows about plugin_B and requires its services; plugin_A knows about plugin_B at design time and explicitly invokes it.)
  2. discover plugins via the extension points mechanism (e.g. plugin_X defines an extension point(s) that other plugins implement (extend), plugin_X only finds out about these at run time and executes them; there may be multiple plugins extending plugin_X‘s extension point(s) and plugin_X does not need to know about them at design time.)

More information on how this hangs together can be found in the Plugin class’ documentation.

PlugMan defines a convenient "root" plugin that may (or may not) be used as the base plugin for an application. It has a single extension point and doesn‘t do anything else really. You are free to ignore the root plugin or make your own base plugin if that suits.

If any plugins are defined without a parent plugin, they will be assigned the root plugin as a "required" plugin. This ensures no plugins are orphaned and by stopping the root plugin, all other plugins in the system will also be stopped. (Although it is possible to have no plugins attached to root, so this isn‘t enforced with any vigor…)

The PlugMan.define method is used to register each plugin. You don‘t actually create classes that extend Plugin, you create a proc that is a parameter to PlugMan.define that is used to create an instance of Plugin for you.

Typically all the plugins will live in a subdirectory tree and will be loaded early in the application‘s lifecycle using the PlugMan.load_plugins(PLUGIN_DIR) method, but plugins can also be loaded at any time in an application‘s lifecycle.

PlugMan assumes that plugin files have the extension .rb and PlugMan.load_plugins will attempt to load and register all .rb files in the drectory tree. Each .rb file should have the format

  PlugMan.define :plugin_name do
    ... see rdoc for Plugin for more details on how to define a plugin's guts
  end

PlugMan also includes the Observable module. Listeners can be informed whenever a plugin is started/stopped. It is currently a simple mechansim where the name and new state of the plugin are passed to the listeners. Currently the states a plugin can be in are :stopped, :started or :error.

An example of observer use is:

  # add observer somewhere in your code
  def do_something
    PlugMan.add_observer(self)
  end

  ## the callback method is update
  def update(state, plugin)
    puts "Plugin #{plugin.name.inspect} changed state to #{state.inspect}"
  end

  ## remove observer somewhere
  def do_another_thing
    PlugMan.delete_observer(self)
  end

Methods

Classes and Modules

Class PlugMan::Plugin
Class PlugMan::PluginError

Constants

ROOT_PLUGIN = :root   Root plugin, any orphan plugins will be automatically belonged to here.
ROOT_EXTENSION_POINT = :root   Root extension point, in case you want to use the root plugin and extension point for convenience. Can be safely ignored.
PLUGMAN_VERSION = "0.0.3"   Version information for PlugMan

Public Class methods

Registers a plugin. See Plugin for more information about defining a plugin.

Do not create plugins using Plugin.new as they won‘t be registered with PlugMan.

The plug_name must be unique amongst plugins and it will be converted to a symbol. &block is the actual code that will make up the plugin (once again, see Plugin for more details.)

Once a plugin is defined, it will be available using PlugMan.registered_plugins[:plug_name] and any plugins that extend it can be discovered using PlugMan.extensions(:plug_name, ext_point)

If a plugin is declared more than once, the instance with the greatest version number will be used (any older version will be discarded.)

When a plugin is initially defined, it is put into the :stopped state.

Gets all the plugins that a plugin requires (a combination of :requires and :extends plugins)

Given a plugin and extension point names, returns all the plugins that use that extension point.

Load all the plugins in plugin_dir

Gets a hash of all the registered plugins, key is a plugin name (as a symbol), value is the Plugin object.

Gets all the plugins that depend on the named plugin (the plugins that decare plugin_name as :required or :extends)

Gets the plugins attached to the root plugin and extension point.

Starts all plugins that are registered.

Starts a plugin and the plugins it requires. When a plugin is started, any observers are notified of the change.

If a plugin isn‘t started correctly, a PluginError(:start_failed) exception is raised.

Stops all plugins that are registered.

Stops a plugin and the plugins that depend on it. When a plugin is stopped, any observers are notified of the change.

If a plugin isn‘t stopped correctly, a PluginError(:stop_failed) exception is raised.

[Validate]