Edit online

General Configuration of an Oxygen XML Editor Plugin

The Oxygen XML Editor functionality can be extended with plugins that implement a clearly specified API. On the Oxygen XML Editor website, there is an SDK with sample plugins (source and compiled Java code) and the Javadoc API necessary for developing custom plugins.

The minimal implementation of a plugin must provide:

  • A Java class that extends the ro.sync.exml.plugin.Plugin class.
  • A Java class that implements the ro.sync.exml.plugin.PluginExtension interface.
  • A plugin descriptor file called plugin.xml.

A ro.sync.exml.plugin.PluginDescriptor object is passed to the constructor of the subclass of the ro.sync.exml.plugin.Plugin class. It contains the following data items about the plugin:

  • basedir (File object) - The base directory of the plugin.
  • description (String object) - The description of the plugin.
  • name (String object) - The name of the plugin.
  • vendor (String object) - The vendor name of the plugin.
  • version (String object) - The plugin version. The allowed format is: MAJOR.MINOR.PATCH (for example, 1.0.2).
  • id (String object) - A unique identifier.
  • classLoaderType - You can choose between preferOxygenResources (default value) and preferReferencedResources. When choosing preferOxygenResources, the libraries that are referenced in the Oxygen XML Editor lib directory will have precedence over those referenced in the plugin.xml configuration file, if they have the same package names. When choosing preferReferencedResources, the libraries that are referenced in the plugin.xml configuration file will have precedence over those found in the Oxygen XML Editor lib directory, if they have the same package names.

The plugin descriptor is an XML file that defines how the plugin is integrated in Oxygen XML Editor and what libraries are loaded. The structure of the plugin descriptor file is fully described in a DTD grammar located in [OXYGEN_INSTALL_DIR]/plugins/plugin.dtd. Here is a sample plugin descriptor used by the Capitalize Lines sample plugin:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plugin SYSTEM "../plugin.dtd">
<plugin
    name="Capitalize Lines"
    description="Capitalize the first character on each line"
    version="1.0.0"
    vendor="SyncRO"
    class="ro.sync.sample.plugin.caplines.CapLinesPlugin">
    <runtime>
        <library name="lib/caplines.jar"/>
    </runtime>
    <extension type="selectionProcessor" 
    class="ro.sync.sample.plugin.caplines.CapLinesPluginExtension" 
           keyboardShortcut="ctrl shift EQUALS"/>
</plugin>

If your plugin is of the Selection, Document or General types, and thus contributes an action either to the contextual menu or to the main menu of the Text editing mode, then you can assign a keyboard shortcut for it. You can use the @keyboardShortcut attribute for each <extension> element to specify the desired shortcut.

Tip: To compose string representations of the desired shortcut keys you can go to Options > Menu Shortcut Keys, select an action, and click Edit. Then choose the desired key sequence and use the representation that appears in the resulting dialog box.

Referencing Libraries

To reference libraries, use either of the following elements:
  • <library name="path/libraryName"> - To point to specific libraries. Notice that the value of library name includes the path (relative or absolute) to the library.
    Note: You can use the ${oxygenInstallDir} editor variable as part of the value of the @name attribute. You can also use a system variable (${system(var.name)}) or environment variable (${env(VAR_NAME)}).
  • <librariesFolder name="path/libraryFolderPath"> - To point to multiple libraries located in the specified folder. Notice that the value of libraryFolder name includes the path (relative or absolute) to the library folder.
Both elements support the @scope attribute that defines the loading priority. It can have one of the following two values:
  • local - The library is loaded in the plugin's own class loader. This is the default behavior.
  • global - The library is loaded in the main application class loader as the last library in the list (as if it would be present in the application lib directory).

Dependency Injection for Plugins

If you want to share a single instance of a certain class between plugin extensions and custom operations (to prevent instances from being repeated), you can declare a <context> element in your plugin.xml file:
<context class="my.package.ContextClass"/>
Important: The my.package.ContextClass class should have a no-arguments constructor that will be called when the class is instantiated.
This will result in an instance being automatically generated. You can access this instance in an extension class by defining a field of that type and annotated with the ro.sync.exml.plugin.PluginContext annotation:
@PluginContext
ContextClass contextInstance;

The defined field is automatically populated with the single instance.

Tip: By default, an instance of the PluginDescriptor class is also injectable.