Introduction
Plugins are software programs that can be dynamically added to existing programs to add / enhance functionality. They are also called Add-ons or Bundles (the OSGi term). In IGB, plug-ins are also called "Apps." You may have seen plugins in the software that you use, such as internet browsers, text/graphics editors, games, etc. Examples include Chrome extensions and countless Photoshop filters. Users can search for plugins and choose ones that address their needs. Users can add or remove plugins at will without having to re-install the base application. Plugins can also be updated dynamically when the author(s) make changes.
IGB uses OSGi to implement plug-able Apps
OSGi is specification and framework for building modular applications in java. In addition to the framework specification, it also contains a specification for dynamically installing and running plug-ins. The OSGi term for a Plugin is Bundle. They mean the same thing.
An OSGi bundle is a nothing but a jar file with some OSGi-specific headers included in the its MANIFEST.MF file. The OSGi framework uses these headers to manage how the bundle interacts with other bundles within the same framework. The OSGi framework also use the headers to manage transitions between lifecycle states for a bundle - installed, resolved, starting, active, stopping, and uninstalled.
An OSGi bundle can (usually will) have a special java class called an Activator. This class must extend org.osgi.framework.BundleActivator
, and implement the start()
and stop()
methods. The activator class is specified in the Bundle-Activator MANIFEST.MF header (see below). These methods are called when the bundle is started and stopped.
When a program is running with OSGi, the OSGi framework dynamically handles installing / uninstalling, activating (starting), deactivating (stopping), and upgrading bundles.
OSGi caches bundles, saving them to a directory called the "bundle cache" on the local hard disk, so that they don't need to be downloaded every time. So you can work offline after you have loaded IGB. IGB stores the App bundles alongside core IGB platform bundles in a folder called "bundles" in an IGB-specific directory called ".igb." The bundles directory contains subdirectories for specific IGB versions.
There are several implementations of OSGi, including:
- Apache Felix (http://felix.apache.org/)
- Eclipse Equinox (http://www.eclipse.org/equinox/)
- Knoplerfish (http://www.knopflerfish.org/)
The implementations are (for the most part) interchangeable and are free. The implementations allow the user to run OSGi from a command line tool or to start it within a program.
IGB uses the Apache Felix implementation from within the com.affymetrix.igb.main.OSGiHandler class.
There are several tutorials for OSGi, including:
- How to get Started with OSGi (http://www.osgi.org/About/HowOSGi)
- Apache Felix OSGi Tutorial (https://felix.apache.org/documentation/tutorials-examples-and-presentations/apache-felix-osgi-tutorial.html)
- OSGi for Beginners (http://www.theserverside.com/news/1363825/OSGi-for-Beginners)
- OSGi with Eclipse Equinox - Tutorial (http://www.vogella.de/articles/OSGi/article.html)
IGB uses OBR (http://felix.apache.org/site/apache-felix-osgi-bundle-repository.html) to find and load bundles from web servers (repositories). The web servers need to use OBR to create the repository.xml file listing all the available bundles.
Users can add / remove bundle repositories by choosing File>Preferences , Plugin Repositories tab.
IGB uses OSGi Services to allow bundles to add new implementations of existing IGB elements. The new implementations will show up as soon as the bundle is started. Examples include IGB tabs and graph manipulation functions.
Extension Points
IGB has several "extension points" designed for Apps. These are interfaces or abstract classes that are implemented or extended by App classes. Usually the Activator for the App will register the App as a service in its start() method:
bundleContext.registerService(<extension point>.class.getName(), <plugin implementation>, new Properties());
Some of the available extension points include:
- com.affymetrix.genometryImpl.operator.Operator - operates on a selection of tracks from the GraphAdjuster tab or popup menu
- com.affymetrix.genometryImpl.parsers.FileTypeHandler - process a file type (by the file extension)
- com.affymetrix.igb.shared.TrackClickListener - called when the user clicks on the label portion of a track
- com.affymetrix.igb.shared.GlyphProcessor - called when IGB creates a glyph
- com.affymetrix.igb.shared.MapViewGlyphFactoryI - a new way to display a track
- com.affymetrix.igb.search.mode.ISearchMode - a new search method option on the Search View tab
- com.affymetrix.igb.osgi.service.IGBTabPanel - a tab in the JTabbedPane at the bottom and sides of IGB
- com.affymetrix.genometryImpl.util.ServerTypeI - a server type
- com.affymetrix.igb.osgi.service.IStopRoutine - a routine to be run when IGB terminates
- com.affymetrix.igb.prefs.IPrefEditorComponent - a Preferences window to let users enter preferences
IGB-specific MANIFEST.MF requirements
To install an App into IGB, the MANIFEST.MF file needs to include the standard OSGi headers, which you should not have to manually add. You should use the BND tool to create these. Of these, two are specifically required by IGB to install and manage Apps. These are:
- Bundle-SymbolicName - used by IGB to uniquely identify an App and its various versions, e.g., "super-simple-igb-app." Users typcally do not see this name; however, App Store uses this to form URLs to App-specific pages, e.g., https://apps.bioviz.org/apps/org.lorainelab.igb.protannot
- Bundle-Version - used by IGB to distinguish different versions, called "releases", of the same App, e.g., "0.0.1." An App's version should always look like x.y.z, where x, y, and z are non-negative integers. It is important to not include suffix tags so that IGB can distinguish higher from lower versions of the same App.
IGB also recognizes and uses two optional MANIFEST.MF headers. These are:
- Bundle-Name - a user-facing, display name for an App, e.g., "Super Simple IGB App." This appears in App Manager and also on IGB App Store pages.
- Bundle-Description - base64-encoded markdown text describing the App. IGB App Manager and IGB App Store pages display the decoded, rendered Markdown to users. We provide a maven plugin (bundle-markdown-encoder) for developers to include this header in their bundle's MANIFEST.MF file.