Welcome, Guest! Log In | Create Account

Getting started with JabRef plugin development

From jabref

Jump to: navigation, search

Contents

Getting started with JabRef plugin development

Plugins are a way to extend JabRef with additional functionality. Plugins can be distributed separately from JabRef itself, and are loaded when you start JabRef.

1. What must a plugin contain?

A plugin must be packaged as a Jar file. The Jar file must contain in its root a file called plugin.xml. This XML file refers to a specific Java class, and this class and all its supporting classes and resources must be included in the Jar.

2. Extension points

JabRef's plugins system offers a set of Extension points, and each plugin should attach to one or more of these. Each Extension point is in Java terms a specific interface that the plugin must implement, and in practical terms is a type of functionality that can be added. If you take a look at JabRef's source code tree, you will find the definition of all extension points in the file src/plugins/net.sf.jabref.core/plugin.xml, and these definitions also include all parameters that can or must be defined for plugins attaching to the extension points.

ImportFormat

This extension point lets you add an import filter to JabRef, appearing in the file type dropdown menu in the file dialog when importing.

ExportFormat

EntryFetcher

This extension point lets you add a so-called Entry fetcher to JabRef, appearing under the Web search menu.

PushToApplication

This extension points lets you add options to insert selected entries into external applications, such as is already available for LyX, WinEdt and other applications.

LayoutFormatter

An example plugin

We will in the following develop a simple plugin as an example of how it can be done. We will build the plugin with Apache Ant.

The plugin will be of the PushToApplication type, offering to call a configurable shell/dos command embedding the list of BibTeX keys for the selected entries. Such a plugin can be configured to duplicate several of the existing push-to-features (e.g. Emacs, Lyx and Vim).

The Java source of the plugin will be contained in the file PushToX.java. This file defines the class example.PushToX, which implements the interface net.sf.jabref.external.PushToApplication. We will get back to the contents of the Java source later on. First we will take a look at the plugin.xml file.

The plugin.xml file

The plugin.xml file will look like this: [file:plugin.xml]

Apart from the header, the XML file contains three important parts:

<requires>
<import plugin-id="net.sf.jabref.core"/>
</requires>

This part is necessary because all plugins extend the so-called core plugin which is defined by JabRef's own plugin file.

<runtime>
<library type="code" path="classes/" id="code"/>
</runtime>

This part defines where to find the plugin's code. In our plugin there are no resources apart from the code, and the <library> tag defines that the plugin code resides in the classes directory within the Jar file. Specifically, this means that the example.PushToX class is found in the file classes/example/PushToX.class within the Jar file.

<extension id="PushToX" plugin-id="net.sf.jabref.core" point-id="PushToApplication">
<parameter id="pushToApp" value="example.PushToX" />
<parameter id="name" value="Push to external application" />
<parameter id="description" value="Configurable plugin for pushing citations to external application" />
</extension>

This part defines how the plugin attaches to the extension point. The first line gives our plugin the id PushToX, and states that it extends the core plugin at the extension point PushToApplication.

The second line defines the parameter pushToApp which needs to be given a value for all PushToApplication plugins. The parameter should point to the name of the class implementing the required interface, namely net.sf.jabref.external.PushToApplication.

The third and fourth lines give the name and a description of the plugin.

The Ant build.xml file

The Ant build file will look like this: [file:build.xml]

The Ant build file has the task of compiling and packaging our plugin. In order to compile it, we need a JabRef build to provide the necessary classes, and we have opted to put a JabRef jar file in a directory called lib below the plugin source code root directory. We create a directory called plugins below the lib directory, and want the Ant build to place the packaged plugin in this directory. This will result in the plugin being automatically loaded when we run JabRef from the jar in the lib directory.

<path id="classpath">
<fileset dir="${jabref.build.dir}">
<include name="JabRef-2.4.jar"/>
</fileset>
</path>

<target name="compile">
<mkdir dir="${build.classes}"/>
<javac debug="on" deprecation="on" destdir="${build.classes}" source="1.5" target="1.5">
<src path="."/>
<classpath refid="classpath"/>
</javac>

The first part defines a classpath for compilation, containing the JabRef jar file. If the plugin relied on other libraries, they would need to be included here.

The second part performs the compile using the <javac> task. The target directory ${build.classes} is specified, along with the classpath and the location of the source classes - which is the root of the plugin's source tree.

<target name="jar" depends="compile">
<jar destfile="${jar}">
<fileset dir=".">
<include name="plugin.xml"/>
'<include name="classes/\'"/>
</fileset>
</jar>
</target>

The jar target depends on compile, which means that running jar forces the compile target to run first. The jar target creates a jar file for the plugin, including all classes built in the classes directory, and the plugin.xml file. The resulting jar file is the completed plugin.

The PushToX.java file

The PushToX.java file looks like this: [file:PushToX.java]

The Java code contains a lot of code that we won't cover in detail. The most important point is that this Java class - which has been declared in the plugins.xml file to attach to the PushToApplication extension point, needs to implement the interface net.sf.jabref.external.PushToApplication.

The interface looks like this: [file:PushToApplication.java]

PushToX.java must of course implement all methods of the interface in order to compile. The first five methods define the name, tooltip, icon and keyboard shortcut of the plugin - in other words how the PushToX feature will appear in the JabRef GUI.

The remaining five methods contain the actual implementation of the feature. When the user calls this push-to-feature, JabRef may call the requiresBibtexKeys() method in order to ensure that BibTeX keys are defined if required. The pushEntries() method is then called with a set of arguments providing information about the BibTeX entries to push. Note that this method is called in a background thread, meaning that it is not allowed to do any GUI related work. After the pushEntries() method returns, JabRef will call the operationCompleted() method on the event dispatch thread, and this method can display messages and do other GUI related operations.

A PushToApplication plugin may need to offer a settings panel, available by right-clicking the icon button in JabRef's toolbar. If a settings panel is needed, the implementing class needs only to return such a panel from the getSettingsPanel() method, and JabRef will display it as needed by the user. If the user has opened the settings panel and finished by clicking Ok**, JabRef will call the plugin's storeSettings() method. It is then the task of the plugin implementation to look up the user's choices in the settings panel and update preferences accordingly. Look at the PushToX.java file for an example of using a settings panel.