Dynamic Plugin Quickstart
From OpenSimulator
(→Defining Extension Points) |
m (Robot: Replacing 'OpenSim' to 'OpenSimulator', which is the precise name) |
||
(5 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
+ | __NOTOC__ | ||
+ | {{Quicklinks}} | ||
+ | |||
+ | '''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 /> | ||
+ | |||
A quick guide to writing plugins. Please refer to [[How to create a dynamic plugin]] for more in-depth information. | A quick guide to writing plugins. Please refer to [[How to create a dynamic plugin]] for more in-depth information. | ||
− | + | == 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: | 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: | ||
Line 38: | 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 | + | '''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 == | |
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: | 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: | ||
Line 82: | Line 89: | ||
* '''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. | * '''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. | ||
− | + | == Source Code == | |
The relevant code which ends up in <code>OpenSim.Grid.AssetInventoryServer.exe</code> and loads the AssetStorage plugin looks something like this: | The relevant code which ends up in <code>OpenSim.Grid.AssetInventoryServer.exe</code> and loads the AssetStorage plugin looks something like this: |
Latest revision as of 22: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 forOpenSim.Grid.AssetInventoryServer.IAssetStorageProvider
interface, whileOpenSim.Framework.dll
contains a definition forOpenSim.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 forOpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.OpenSimAssetStoragePlugin
, andOpenSim.Framework.dll
contains a definition forOpenSim.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.