Deploying Toolkit Plugins

All of the tutorials that follow ultimately result in components that can or must be packaged as Open Toolkit plugins.

A plugin for the Open Toolkit is simply a directory containing the files that make up the plugin.

To use a plugin with a Toolkit instance you "deploy" the plugin by copying the directory to the plugins directory and running the integrator.xml Ant script included with the Toolkit (see Packaging Document Type Shells and Vocabulary Modules as Toolkit Plugins).

This raises the question of how to actually do the copying, especially during development, where you will be making many changes and wanting to continuously re-deploy your plugin as you develop and test it.

As a general practice you do not want the source code for your plugin to be managed in the directory structure of the Toolkit itself. You want to manage the source in a separate work area and then copy it to the Toolkit as you go.

Another reason to keep your plugin source separate from the Toolkit is that the source file organization may not match how the files need to be organized for use in a plugin. For example, you may need to support one or more editors that expect a specific organizational structure that is different from what you would use in a plugin. Thus you may need to produce several different packagings of the same document type files for use by different tools.

There are, of course, many ways to deploy plugins: you can simply copy the files manually using Windows Explorer or Finder or whatever. You can use a batch or a shell script. Or you can use Ant.

The Open Toolkit is based on Apache Ant, which is a general build process scripting facility. Ant is used very heavily in Java projects to manage compiling and packaging Java code, but Ant is general purpose and can be used for lots of things.

One thing you can do easily with Ant is copy files from one place to another. Thus you can create an Ant script that will copy the source files for your plugins to the appropriate Toolkit and run the integrator.xml Ant script in one go.

The main challenge here is telling the Ant script where the Toolkit is on your local machine.

My practice is to have a file named build.properties (Windows) or .build.properties (Linux or OSX) in my home directory that defines a property named "dita-ot-dir" and sets it to the location of the Toolkit I want to deploy to. In my project-specific build scripts I then include the build.properties file and use the dita-ot-dir property in copy tasks that deploy my Toolkit plugins. Note that the script below defines the property "dita-ot-dir". This definition of the property will be used only if dita-ot-dir is not defined in eitehr .build.properties or build.properties. By the property definition precedence rules in Ant, the first definition of a property wins, so the definition in the main Ant script is ignored if dita-ot-dir is defined in either of the included properties files.

Here is a simple Ant build script (named build.xml by Ant convention) that will deploy a set of Toolkit plugins where the plugin source files are in a directory named toolkit_plugins under the main project directory:
<project name="DITA Tutorials" basedir="." default="deploy-toolkit-plugins">
	
  <property file="build.properties"/>
  <property file="${user.home}/.build.properties"/>
  <property file="${user.home}/build.properties"/>

	
  <property name="dist" location="${basedir}/dist"/>
  <property name="plugin.dist" location="${dist}/plugins"/>
  <property name="dita-ot-dir" location="c:\DITA-OT1.5"/>
  <property name="plugin-src" location="${basedir}/toolkit_plugins"/>
  <property name="plugin-deploy_target" location="${dita-ot-dir}/plugins"/>
  <property name="ot-plugins-base-name" value="com.example.plugins"/>

  <import file="${dita-ot-dir}${file.separator}integrator.xml" optional="yes"/>


  <target name="init">
  <tstamp/>
  </target>

  <tstamp>
	<format property="package.date" pattern="yyyy-MM-dd"/>
  </tstamp>

  <target name="clean">
  </target>
	
	
  <target name="dist-toolkit-plugins" 
      description="Packages the DITA Open Toolkit plugins for deployment to a working Toolkit instance"
	  depends="dist-init"
  >
    <delete includeemptydirs="true" failonerror="false">
      <fileset dir="${plugin.dist}"/>
    </delete>
	<copy todir="${plugin.dist}">
		<fileset dir="${plugin-src}">
		</fileset>
	</copy>
  </target>
	
  <target name="deploy-toolkit-plugins" depends="dist-toolkit-plugins"
     description="Deploy plugins to local DITA Open Toolkit">
    <delete failonerror="true" includeemptydirs="true">
      <fileset dir="${plugin-deploy_target}" includes="${ot-plugins-base-name}.*/**"/>
    </delete>
    <mkdir dir="${plugin-deploy_target}"/>
    <copy todir="${plugin-deploy_target}"> 
      <fileset dir="${plugin.dist}">
        <include name="**/*"/>
      </fileset>
    </copy>
    <!-- Itegrate the deployed plugins: -->
    <antcall target="integrate"/>

  </target>
	
  <target name="dist-init">
    <delete failonerror="false" includeemptydirs="true">
      <fileset dir="${dist}" includes="*/**"/>
    </delete>
	<mkdir dir="${dist}"/>
  </target>

</project>

If you're not familiar with Ant this may look a lot more complicated than it really is.

Each <target> element represents a separate callable part of the script. In this script the main target is named "deploy-toolkit-plugins". It's also set as the default target so that if you simply run the script without specifying a target it will run the deploy-toolkit-plugins target automatically. Likewise, the Ant command looks for a file named build.xml by default, so from a command line, if you are in the directory containing the build.xml file, you can just type "ant" and it should work (assuming the "ant" command is on your path):
c:\workspace\myproject> ant
Buildfile: build.xml

dist-init:

dist-toolkit-plugins:

...

BUILD SUCCEEDED
You can see what targets are available in the script by using the -projecthelp parameter:
c:\workspace\myproject> ant -projecthelp
Buildfile: build.xml

Main targets:

 deploy-toolkit-plugins  Deploy plugins to local DITA Open Toolkit
 dist-toolkit-plugins    Packages the DITA Open Toolkit plugins for deployment to a working Toolkit instance
Default target: deploy-toolkit-plugins
c:\workspace\myproject> 

The targets listed are those with @description attributes.

This script breaks the deployment into two steps:
  1. dist-toolkit-plugins copies all the files to a "distribution" directory
  2. deploy-toolkit-plugins then copies the files from the distribution directory to the Toolkit plugins directory. It also runs the integrator.xml script that is part of the Toolkit itself.

This two-step process allows you the opportunity to pull files together from different source locations into a single set of files to be deployed. For example, my normal practice is to manage all my vocabulary modules and document type shells in a source directory called doctypes and all my Toolkit plugins in a directory called toolkit_plugins. In the toolkit_plugins directory I have directories for each distinct document type plugin with just the files that are Toolkit-specific (usually just the plugin.xml file). I then have my dist-toolkit-plugins Ant target merge the files from the toolkit_plugins directory with the files from the doctypes directories to create complete Toolkit plugins.

The Ant property ot-plugins-base-name holds the common directory name prefix for all of the plugins managed by this Ant script, which makes it easy to delete existing deployed plugins and otherwise copy only the files you want. You would set this property to match whatever you've used for your plugins (I recommend the Java-style reverse domain name convention, e.g. "com.example.myproject").

One you get this sort of pattern set up it becomes easy to replicate.

Once you have the Ant script working you can run it in a couple of different ways.

An easy way is to start a Toolkit command-line shell using the startcmd.bat or startcmd.sh scripts that are part of the full Toolkit installation. These scripts set up a command line environment with everything set up correctly so you can run the Toolkit Ant scripts.

For example, to run your Ant script to deploy your plugins, you might do something like this:
c:\> cd c:\DITA-OT
c:\DITA-OT> startcmd
{stuff happens here}
c:\DITA-OT> cd c:\workspace\myproject
c:\workspace\myproject> ant
Buildfile: build.xml

dist-init:
    [mkdir] Created dir: /workspace/myproject/dist

dist-toolkit-plugins:

 ...

integrate:
[integrate] Using XERCES.

BUILD SUCCESSFUL
Total time: 2 seconds

Once you've run startcmd you can come back to the command window and rerun the deploy script just by hitting the up arrow and enter.

If you use Eclipse as your development environment you can run the Ant script from within Eclipse once you do a one-time setup of Ant with the Open Toolkit's java libraries. See Setting Up Your Development Environment.

You can also set up a standalone batch or shell script that sets up the execution environment as startcmd does and then runs your Ant script. That may be the most convenient approach if you expect other people to run this process with minimal setup.

Note also that you can set Ant properties on the command line. So for example if you had two different Toolkit instances that you wanted to deploy to you could set the value of the dita-ot-dir Ant property on the command line like so:
ant -Ddita-ot-dir=/Applications/oxygen_12_beta/frameworks/dita/DITA-OT/