How Eclipse Plugin Works – Analysis of a Simple Menu

By using the Eclipse plugin wizard, it takes no time to get a working sample plugin. Here is one I did for getting a menu.

How an eclipse plugin works can be illustrated in this simple example.

Activator class is the start point of the plugin. Activator class is loaded initially and if you look into the hierarchy of the Activator class, it extends the AbstractUIPlugin, which tells the Eclipse Run-time that this Plugin is someway related to the Eclipse Platform UI.

The method getDefault() will be called by the Eclipse run-time to return the Plugin instance. Since there is only one instance of the Plugin class, the Activator class is maintained as a Singleton Class by having a shared static variable of type Activator.

package simplemenu;
 
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
 
/**
 * The activator class controls the plug-in life cycle
 */
public class Activator extends AbstractUIPlugin {
 
	// The plug-in ID
	public static final String PLUGIN_ID = "SimpleMenu";
 
	// The shared instance
	private static Activator plugin;
 
	/**
	 * The constructor
	 */
	public Activator() {
	}
 
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
	 */
	public void start(BundleContext context) throws Exception {
		super.start(context);
		plugin = this;
	}
 
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) throws Exception {
		plugin = null;
		super.stop(context);
	}
 
	/**
	 * Returns the shared instance
	 *
	 * @return the shared instance
	 */
	public static Activator getDefault() {
		return plugin;
	}
 
	/**
	 * Returns an image descriptor for the image file at the given
	 * plug-in relative path
	 *
	 * @param path the path
	 * @return the image descriptor
	 */
	public static ImageDescriptor getImageDescriptor(String path) {
		return imageDescriptorFromPlugin(PLUGIN_ID, path);
	}
}

Plugin.xml file is used to initialize plugin for the process above.

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
 
   <extension
         point="org.eclipse.ui.actionSets">
      <actionSet
            label="Sample Action Set"
            visible="true"
            id="SimpleMenu.actionSet">
         <menu
               label="Sample &amp;Menu"
               id="sampleMenu">
            <separator
                  name="sampleGroup">
            </separator>
         </menu>
         <action
               label="&amp;Sample Action"
               icon="icons/sample.gif"
               class="simplemenu.actions.SampleAction"
               tooltip="Hello, Eclipse world"
               menubarPath="sampleMenu/sampleGroup"
               toolbarPath="sampleGroup"
               id="simplemenu.actions.SampleAction">
         </action>
      </actionSet>
   </extension>
 
</plugin>

Here is the code implenting an action. It's hierarchy is as following:

IWorkbenchWindowActionDelegate is the one implemented here, but other kind of action may implement other interface, e.g. IObjectActionDelegate.

Notice that run() is the callback method which will be called by its proxy. Callback is a concept in observer design pattern.

package simplemenu.actions;
 
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.jface.dialogs.MessageDialog;
 
/**
 * Our sample action implements workbench action delegate.
 * The action proxy will be created by the workbench and
 * shown in the UI. When the user tries to use the action,
 * this delegate will be created and execution will be 
 * delegated to it.
 * @see IWorkbenchWindowActionDelegate
 */
public class SampleAction implements IWorkbenchWindowActionDelegate {
	private IWorkbenchWindow window;
	/**
	 * The constructor.
	 */
	public SampleAction() {
	}
 
	/**
	 * The action has been activated. The argument of the
	 * method represents the 'real' action sitting
	 * in the workbench UI.
	 * @see IWorkbenchWindowActionDelegate#run
	 */
	public void run(IAction action) {
		MessageDialog.openInformation(
			window.getShell(),
			"SimpleMenu",
			"Hello, Eclipse world"+ action.toString());
	}
 
	/**
	 * Selection in the workbench has been changed. We 
	 * can change the state of the 'real' action here
	 * if we want, but this can only happen after 
	 * the delegate has been created.
	 * @see IWorkbenchWindowActionDelegate#selectionChanged
	 */
	public void selectionChanged(IAction action, ISelection selection) {
	}
 
	/**
	 * We can use this method to dispose of any system
	 * resources we previously allocated.
	 * @see IWorkbenchWindowActionDelegate#dispose
	 */
	public void dispose() {
	}
 
	/**
	 * We will cache window object in order to
	 * be able to provide parent shell for the message dialog.
	 * @see IWorkbenchWindowActionDelegate#init
	 */
	public void init(IWorkbenchWindow window) {
		this.window = window;
	}
}
Category >> Architecture & Design  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>