Dynamic Plugin Quickstart

From OpenSimulator

(Difference between revisions)
Jump to: navigation, search
m (Removed 'Template:' prefix from template includings and/or changed external-link into internal-link)
m (Robot: Replacing 'OpenSim' to 'OpenSimulator', which is the precise name)
 
(One intermediate revision by one user not shown)
Line 2: Line 2:
 
{{Quicklinks}}
 
{{Quicklinks}}
  
'''NOTE: This tutorial now refers to a very old OpenSim and so is only partially useful. See [[IRegionModule]] for something more up to date.'''
+
'''NOTE: This tutorial now refers to a very old OpenSimulator and so is only partially useful. See [[IRegionModule]] for something more up to date.'''
  
 
<br />
 
<br />
Line 45: Line 45:
 
At this stage, all that is needed is <code>OpenSim.Grid.AssetInventoryServer.IAssetStorageProvider</code> defined and present in <code>OpenSim.Grid.AssetInventoryServer.exe</code>.
 
At this stage, all that is needed is <code>OpenSim.Grid.AssetInventoryServer.IAssetStorageProvider</code> defined and present in <code>OpenSim.Grid.AssetInventoryServer.exe</code>.
  
'''PLEASE NOTE''': embedding XML manifests in .exe assemblies doesn't work. The .addin.xml file must reside in a directory that Mono.Addins will scan for plugins. Currently in OpenSim this is the current working directory (<code>bin/</code>). Ideally all applications would consist of an .exe assembly and a .dll assembly which contains the embedded XML manifest.
+
'''PLEASE NOTE''': embedding XML manifests in .exe assemblies doesn't work. The .addin.xml file must reside in a directory that Mono.Addins will scan for plugins. Currently in OpenSimulator this is the current working directory (<code>bin/</code>). Ideally all applications would consist of an .exe assembly and a .dll assembly which contains the embedded XML manifest.
  
 
== Defining Extensions ==
 
== Defining Extensions ==

Latest revision as of 23:21, 3 March 2012

NOTE: This tutorial now refers to a very old OpenSimulator and so is only partially useful. See IRegionModule for something more up to date.


A quick guide to writing plugins. Please refer to How to create a dynamic plugin for more in-depth information.

[edit] Defining Extension Points

Extension points describe the location in the program where external modules can be plugged-in at runtime. Extension points can be defined in one of two ways:

  • decorating interfaces, classes or methods with attributes in the source code
  • embedding an XML file, called a manifest, as a resource in an assembly

In OpenSim, the preferred method is to embed an XML manifest in the assembly. Below is an example manifest defining one extension point in the AssetInventoryServer:

<Addin id="OpenSim.Grid.AssetInventoryServer" isroot="true" version="0.1">
    <Runtime>
        <Import assembly="OpenSim.Grid.AssetInventoryServer.exe" />
        <Import assembly="OpenSim.Framework.dll" />
    </Runtime>
    <ExtensionPoint path="/OpenSim/AssetInventoryServer/AssetStorageProvider">
        <ExtensionNode name="Plugin"
                       type="OpenSim.Framework.PluginExtensionNode"
                       objectType="OpenSim.Grid.AssetInventoryServer.IAssetStorageProvider" />
    </ExtensionPoint>
</Addin>

This manifest contains the following elements:

  • Addin
    • id: an identifier describing this addin, used for dependencies in other addins.
    • isroot: set to true if this manifest does not define any extension nodes, otherwise can be left out completely.
    • version: a version number, also used for dependencies in other addins.
  • Runtime: a list of assemblies that need to be imported by Mono.Addins as it builds the plugin repository. In the example, the OpenSim.Grid.AssetInventoryServer.exe assembly contains the definition for OpenSim.Grid.AssetInventoryServer.IAssetStorageProvider interface, while OpenSim.Framework.dll contains a definition for OpenSim.Framework.PluginExtensionNode.
  • ExtensionPoint
    • path: the location of the extension point in the extension point tree (see Extension Paths).
  • ExtensionNode
    • name: a name describing this extension node.
    • type: a class that handles plugin loading, this should probably be OpenSim.Framework.PluginExtensionNode unless you know what you're doing.
    • objectType: an instance of this object will be loaded into this extension point at runtime. This is probably what your plugin will instantiate/subclass/implement.

At this stage, all that is needed is OpenSim.Grid.AssetInventoryServer.IAssetStorageProvider defined and present in OpenSim.Grid.AssetInventoryServer.exe.

PLEASE NOTE: embedding XML manifests in .exe assemblies doesn't work. The .addin.xml file must reside in a directory that Mono.Addins will scan for plugins. Currently in OpenSimulator this is the current working directory (bin/). Ideally all applications would consist of an .exe assembly and a .dll assembly which contains the embedded XML manifest.

[edit] Defining Extensions

Extensions that implement extension points are defined in a similar way. Below is an example corresponding XML file describing a plugin for the above extension point:

<Addin id="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim" version="0.1">
    <Runtime>
        <Import assembly="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll" />
        <Import assembly="OpenSim.Data.dll" />
    </Runtime>
 
    <Dependencies>
        <Addin id="OpenSim.Grid.AssetInventoryServer" version="0.1" />
    </Dependencies>
 
    <ExtensionPoint path = "/OpenSim/AssetData">
        <ExtensionNode name="Plugin"
                       type="OpenSim.Framework.PluginExtensionNode"
                       objectType="OpenSim.Data.IAssetDataPlugin" />
    </ExtensionPoint>
 
    <Extension path="/OpenSim/AssetInventoryServer/AssetStorageProvider">
        <Plugin id="OpenSimAssetStorage"
                provider="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll"
                type="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.OpenSimAssetStoragePlugin" />
    </Extension>
</Addin>

The elements (not in the same order as in the file) are:

  • Addin
    • id: a string identifying this plugin, can be used for dependencies in other plugins.
    • version: a version of this plugin, also used for dependencies in other plugins.
  • Runtime: a list of assemblies to import at runtime while Mono.Addins builds up the plugin registry. In this case, OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll contains the definition for OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.OpenSimAssetStoragePlugin, and OpenSim.Framework.dll contains a definition for OpenSim.Framework.PluginExtensionNode.
  • Dependencies: describes other addin(s) required to be loaded before this addin can be loaded. The id and version is used.
  • Extension
    • path: the path along the extension point tree to the extension point which this extension implements.
    • Plugin
      • id: a string identifying this particular extension. Pretty much an arbitrary string.
      • provider: another property of the extension, which can be an arbitrary string. In OpenSim, the convention seems to be to place the assembly name here which contains this plugin.
      • type: the fully qualified class name to be instantiated which implements the extension. In the code, this class will inherit from/implement the class/interface specified in objectType attribute of the ExtensionPath.
  • NOTE: this XML file also defines another extension point, meaning that this plugin also takes another plugin. Note the isroot attribute in the topmost Addin element is omitted.

[edit] Source Code

The relevant code which ends up in OpenSim.Grid.AssetInventoryServer.exe and loads the AssetStorage plugin looks something like this:

private IAssetStorageProvider LoadAssetStorageProvider(string addinPath)
{
    PluginLoader<IAssetStorageProvider> loader = new PluginLoader<IAssetStorageProvider>();
    loader.Add(addinPath);
 
    try
    {
        loader.Load();
    }
    catch (PluginNotInitialisedException e)
    {
        // log the error, clean up, exit if needed, etc
    }
 
    return loader.Plugin;
}
 
// Then, from elsewhere in the code:
IAssetStorageProvider StorageProvider = LoadAssetStorageProvider("/OpenSim/AssetInventoryServer/AssetStorageProvider");

The PluginLoader class lives in OpenSim.Framework; have a look through the code for more plugin loading options.

Personal tools
General
About This Wiki