CompileProtege4PluginInEclipseOneProject
From Protege Wiki
Compile and run a new Plugin from Eclipse
This page describes how to develop a Protege 4 plugin in eclipse. It uses a project (the matrix plugin) from the co-ode project as an example. It assumes that you have already checked out the protege 4 sources and made a project with them as described in downloading and running Protege 4 in eclipse. Also be sure to consult the page writing a plug-in for non-ide related information on plugin development.
Developers who understand the principles of plugin development but who just want to configure their plugin in eclipse can jump to the Compiling and Running Your Plugin in Eclipse page.
Contents |
Developers who only want to get on with the business of getting their plugin to compile can skip the "Anatomy of a plugin section".
Anatomy of a Plugin
In this section we will describe all the parts of a trivially simple plugin. More details to appear. Right now the best documentation can be found at writing a plug-in.
MANIFEST.MF
For a general discussion of manifests see this link. Of particular importance to this discussion is the notion of a continuation. The manifest consists of a set of name value pairs grouped into sections. In the simplest case a name/value pair is represented by one line. But if the value in a name value pair is too long then it can be written out in several lines then the value can be represented on multiple lines by using a continuation which consists of a newline and a space. An example of this is the following name value pair:
Import-Package: org.osgi.framework, org.apache.log4j, org.apache.commons.lang, javax.swing, javax.swing.border, javax.swing.colorchooser, javax.swing.event, javax.swing.filechooser, javax.swing.plaf, javax.swing.plaf.basic, javax.swing.plaf.metal, javax.swing.plaf.multi, javax.swing.plaf.synth, javax.swing.table, javax.swing.text, javax.swing.text.html, javax.swing.text.html.parser, javax.swing.text.rtf, javax.swing.tree, javax.swing.undo, javax.xml.parsers
While the value occurs on several lines it is interpreted as concatenated into one line.
The purpose of the manifest is to provide author and version information, define what resources are required for the plugin to run and to declare what libraries are exported by the plugin. Much of the information in the manifest describes things like the name of the plugin, the developers of the plugin:
Bundle-Name: Example Tab Plugin Bundle-Category: protege Bundle-ContactAddress: p4-feedback@lists.stanford.edu Bundle-DocURL: http://protege.stanford.edu Bundle-Description: A sample tab for learning how to write a plugin Bundle-Vendor: Protege Development Team Bundle-Version: 4.0.8
In addition the manifest describes the symbolic name of the plugin. The symbolic name must be unique for each plugin in Protege so it should include some identification of the organization developing the plugin. Also - by convention - the symbolic name of the plugin is used to name the jar file (org.protege.editor.owl.examples.tab.jar).
Bundle-SymbolicName: org.protege.editor.owl.examples.tab;singleton:=true
The manifest also describes how the class loader finds classes:
Bundle-ClassPath: .,lib/examplelib.jar Import-Package: org.osgi.framework, org.apache.log4j, org.apache.commons.lang, javax.swing, javax.swing.border, javax.swing.colorchooser, javax.swing.event, javax.swing.filechooser, javax.swing.plaf, javax.swing.plaf.basic, javax.swing.plaf.metal, javax.swing.plaf.multi, javax.swing.plaf.synth, javax.swing.table, javax.swing.text, javax.swing.text.html, javax.swing.text.html.parser, javax.swing.text.rtf, javax.swing.tree, javax.swing.undo, javax.xml.parsers Require-Bundle: org.eclipse.equinox.registry, org.eclipse.equinox.common, org.protege.editor.core.application, org.protege.editor.owl, org.semanticweb.owl.owlapi
The Bundle-ClassPath statement says that the class loader should find classes inside the plugin jar file and also inside the examplelib.jar inside the plugin jar file. The Require-Bundle statement says that the class loader should also look for classes in java packages exported by a known collection of required bundles.
Finally the manifest also defines what java packages can be made available to other plugins. Since the current example is a simple example, we do not have any export statements. But this would be useful if the functionality of our plugin was extensible and we expected to see other plugins that would build on our plugin functionality.
plugin.xml
The plugin.xml defines the extensions and extension points that the plugin will add to the existing system. Extensions include such things as views and tabs. The simpler plugins will only define extensions and will not add any extension points. Each extension implemented by a plugin must implement the contract that is defined by an extension point in the existing system.
So our plugin defines two extensions to the Protégé system. Consider the first of these which is declared in the plugin.xml with the following declaration:
<extension
id="ExampleViewComponent"
point="org.protege.editor.core.application.ViewComponent">
<label value="Example View Component"/>
<class value="org.protege.owl.examples.tab.ExampleViewComponent"/>
<category value="@org.protege.ontologycategory"/>
</extension>
The first thee lines of this say that we are creating a ViewComponent which is called ExampleViewComponent. From a user perspective a view component can be defined as a rectangular portion of the screen that has
Compiling and Running Your Plugin in Eclipse
Hopefully these pages will also be useful to developers using development environments other than eclipse. Remember that we are assuming that you have already checked out the protege 4 sources and made a project with them as described in downloading and running Protege 4 in eclipse.
Downloading the example sources
This step assumes that you have Subversion support installed for the Eclipse IDE and that you already know how to use the subversion perspective in eclipse. If you have not done this, we have instructions for doing so on our Wiki. Browse to and checkout protege4/examples/trunk/org.protege.editor.owl.example.tab.
In the next window select "checkout as a project configured using the new project wizard" and click finish.
In the next window "Java Project" is selected, so press next.
In the "Create Java Project" screen give the project a name and click next.
In the "Java Settings" screen change the default output folder to "org.protege.editor.owl.example.tab/build/classes". We are choosing this location because the ant scripts templates that we use have this as an output folder. Then click finish to make the project.
You will be asked to confirm overwriting and the right answer is "OK". You may also be asked if you want to switch to a java perspective and you do.
Building the Plugin
Once the project is created there will still be many compilation errors. To fix these we need to set the build path for the project.
In the "Java Build Path" window, select the Projects tab and add the owleditor project that you configured using downloading and running Protege 4 in eclipse. In the libraries tab add the examplelib.jar file from the lib directory of the org.protege.editor.owl.examples.tab project, the log4j.jar file from the org.protege.common plugin directory of the owleditor project and the owlapi.bin jar from the org.semanticweb.owl.owlapi plugin directory of the owleditor project.
Click ok and now the code should compile (check the problems view).
Running the Plugin
In order to run the plugin, we will need to copy some resources into the matrix/build/classes directory from the org.protege.editor.owl.examples.tab project directory. In particular we will need to copy in the META-INF directory, the lib directory, the viewconfig file and the plugin.xml file. When this is done on an os-x machine the result looks as follows:
Now we can configure a runnable to run Protege 4 and see the plugin sources.
Now we set the main class to be the eclipse startup class. The main method in this class will automatically find the Protege 4 configuration files, the standard Protege 4 plugins and the matrix plugin that we are preparing to debug.
Next we set two jvm arguments. The osgi.clean argument tells eclipse to refresh the class loaders on each run. If this flag was not set then eclipse might not see changes that the developer makes. The second argument (org.protege.plugin.extra) tells eclipse where to find the plugin that we are currently debugging. Note carefully the double quotes around the org.protege.extra.plugin value. On machines where this path has a space (e.g. windows machines) the double quotes ensures that the org.protege.extra.plugin value will be treated as one jvm argument rather than several. Last, change the working directory to ${workspace_loc:owleditor/build/dist/equinox}.
Finally we set the classpath. The only thing that needs to be there is the eclipse OSGi jar. All the other libraries will be found as this starts up. Note that in the next window it is very important that the class path point to the version of the equinox osgi jar file that is in the equinox distribution directory in eclipse. Also the name of this file no longer contains the version information as it does in the snapshot below.
Click apply and click run and hopefully everything will run. There is one more step that you need to do (the first time) if you expect to see your tab). You will need to configure Protege 4 to show the tab as shown below.
Preparing for Distribution
At some point the plugin will be ready to go and you will want to distribute it (and perhaps its sources) to the public. The quick and dirty approach at this point would be to just jar up the files in matrix/build/classes. This jar is then your plugin.
But when you have more time, there should always be a build file (all real open source projects have a build file). Otherwise developers who just want to compile and run your plugin will have to spend a lot of time figuring out how to make the jar and where everything should go.
To use the build file that comes with this example, set the PROTEGE_HOME environment variable to point to your Protege 4 distribution and then run the ant jar or install target. The use of the PROTEGE_HOME environment variable is a convention that is used by many of the Protege build scripts to help the build script find the Protege libraries. If you run ant from inside eclipse, then you can set this environment variable when you create the ant runnable (e.g. see setting up an ant script in eclipse. To do this go to the Environment tab of the "Create, manage, and run configurations" dialog and set the PROTEGE_HOME environment variable as shown below.
If you are developing your own plugin then we have provided a template build file in the etc directory of the protege-standalone project (e.g. in the owleditor directory). For the simplest cases all the developer will need to do to use this build file is to set the name of the plugin:
<property name = "plugin" value = "org.protege.owl.examples.tab"/>
This build file is still a little more complicated than I would like but we will work on that.
Dealing with resources
The template build file has the following line for dealing with resources in the plugin directory:
<target name="copy.resources" depends="build.manifest">
<copy todir="${classes}">
<fileset dir="${src}">
<include name="**/*"/>
<exclude name="**/*.java"/>
<exclude name="**/MANIFEST.MF"/>
<exclude name="**/manifest.mf"/>
</fileset>
</copy>
<copy todir="${classes}/lib">
<fileset dir="${lib}" excludes="junit*.jar"/>
</copy>
<copy todir="${classes}">
<fileset dir="." includes="viewconfig-*.xml,plugin.xml"/>
</copy>
<mkdir dir="${classes}/META-INF"/>
<copy todir="${classes}/META-INF"
file = "${manifest}"/>
</target>
This target handles many common cases without any modification. It handles the manifest, the plugin.xml files and any libraries that the developer might have. If a plugin developer is writing a tab plugin, then this target will handle the viewconfig.xml resources.
However this is not always sufficient. For example if you checkout the co-ode matrix project, you find that they have not yet created a build file for their project. Even after changing the line
<property name = "plugin" value = "org.coode.matrix"/>
the template build.xml file does not quite work. The problem is that in the co-ode matrix project the viewconfig.xml resources have been neatly put in the resources directory (not a bad idea). So the template build file does not find them. To fix this, we just need to add the lines
<copy todir="${classes}">
<fileset dir="./resources"/>
</copy>
to the copy-resources target:
<target name="copy.resources" depends="build.manifest">
<copy todir="${classes}">
<fileset dir="${src}">
<include name="**/*"/>
<exclude name="**/*.java"/>
<exclude name="**/MANIFEST.MF"/>
<exclude name="**/manifest.mf"/>
</fileset>
</copy>
<copy todir="${classes}/lib">
<fileset dir="${lib}" excludes="junit*.jar"/>
</copy>
<copy todir="${classes}">
<fileset dir="." includes="viewconfig-*.xml,plugin.xml"/>
</copy>
<copy todir="${classes}">
<fileset dir="./resources"/>
</copy>
<mkdir dir="${classes}/META-INF"/>
<copy todir="${classes}/META-INF"
file = "${manifest}"/>
</target>
Dealing with Jars inside Jars
In Protege plugin jars (OSGi bundles), sometimes the libraries needed by and exported by the OSGi bundle are to be found inside the jar file as jar files themselves. When Protege starts up, the class loaders find all of these jars in jars and do the right thing. The problem with this configuration is that jars inside jars are not found by java tools like the java compiler. When developing in eclipse in the manner described above, this is also not a problem because the needed jars can be found in the source distribution. But for the build file, these jars inside the jars will need to be pulled out before the compiler can find them.
To help with this process, we have added a target to the template build file that will find jars inside jars. But this stage will need to be configured depending on which jars the developer needs. In the case of the example project above, it needs the log4j.jar file which can be found in the org.protege.common.jar bundle. So the buildlibs target finds that bundle in the Protege distribution and extracts the needed library.
<target name = "buildlibs" depends="init, checkProtegeLibsAndReport">
<unjar dest="${build}"
src="${common.lib}">
<patternset>
<include name = "**/log4j.jar"/>
</patternset>
</unjar>
</target>
We don't expect that it will often be necessary to extend this target but it should be clear what to do.














