Java, Eclipse and Web programming Tutorials
Follow me on twitter

Eclipse Plugin Development - Tutorial (Eclipse 3.5)

Lars Vogel

Version 1.2

13.07.2009

Revision History
Revision 0.1- 0.401.04.2008Lars Vogel
Created
Revision 0.514.04.2009Lars Vogel
Reworked examples from actions to commands
Revision 0.615.04.2009Lars Vogel
Replaced menu contribution description with link to Eclipse commands tutorial
Revision 0.718.04.2009Lars Vogel
Command contribution to the package explorer
Revision 0.819.04.2009Lars Vogel
Export of plugin updated to Eclipse 3.4 (dropin folder and link to P2 update site article).
Revision 0.920.04.2009Lars Vogel
Creating markers
Revision 1.031.05.2009Lars Vogel
Update to Eclipse 3.5
Revision 1.112.07.2009Lars Vogel
Added export plugin into running target
Revision 1.213.07.2009Lars Vogel
Corrected typoes

Eclipse Plugins

This article describes the basic steps on how to create a Eclipse plugin and how to deploy it. It demonstrates also how to extend the package explorer, how to save additional information on existing resources, how to use JDT (Java Development Tools) and how to create markers in Eclipse.

This article assumes that you are already familiar with using the Eclipse IDE for standard Java development.

This article was developed with Eclipse 3.5 (Eclipse Galileo) and Java 1.6.


Table of Contents

1. Eclipse Plugins
2. Hello World Plugin
3. Menu / toolbar contribution via a plugin
4. Contribute to the Eclipse package explorer
4.1. Create Project
4.2. Create Extensions
4.3. Create the code
4.4. Restrict the extension - Visible When
5. Resources and Marker
5.1. Overview
5.2. Create markers
6. Deploying a plugin
7. Thank you
8. Questions and Discussion
9. Links and Literature
9.1. Source Code
9.2. Other Resources

1. Eclipse Plugins

Eclipse is a powerful, extensible IDE for building general purpose applications. Eclipse has an extensible architecture allowing to extent the Eclipse IDE via Plugins.

Eclipse is build upon the OSGI framework (Equinox). This framework allow a flexible architecture in which so-called bundles can be dynamically loaded. Eclipse calls these Plugins. Via these Plugins / bundles you can extend the Eclipse IDE.

See Introduction to OSGi for details.

2. Hello World Plugin

The following will create a simple plugin which will contribute a menu to the standard Eclipse menu.

Create a plugin project "de.vogella.plugin.first". Select File -> New -> Project -> Plug-in Development and then Plug-in Project.

Select the "Hello, World Command!" template and press Finish.

Switch to the plug-in development perspective.

Select the file "MANIFEST.MF", right click it, select Run-As-> Eclipse Application

A new workbench will start with a new menu entry and a message box which is triggered whenever this button is pressed.

3. Menu / toolbar contribution via a plugin

See Using Eclipse Commands for a description how to add commands to menus, the application and view toolbar, etc. The same way you can add commands to Eclipse RCP works also for Eclipse plugins.

4.  Contribute to the Eclipse package explorer

This chapter explains how to extend the context menu of the package explorer. The context menu is displayed if the user select a file in the package explorer via a right mouse click. We will add an entry in the context menu to create an HTML page for a Java source file.

4.1. Create Project

Select File -> New -> Project -> Plug-in Development and then Plug-in Project. Call your plugin de.vogella.plugin.htmlconverter. Do not use a template.

4.2. Create Extensions

Add the extension point "org.eclipse.ui.menus". Add a menu contribution to "popup:org.eclipse.jdt.ui.PackageExplorer". Set the label to "Create HTML" for this contribution.See Using Eclipse Commands for details.

Tip

How did I find the id of the package explorer view? Check out Source Code Guide of Eclipse

Select the tab "Dependencies" of your plugin.xml. The listed dependencies are required to run your new plugin. As we are using the ICompilationUnit which is part of the JDT (org.eclipse.jdt.core) we have to add this plugin as dependency. Press add on the tab "Dependencies" and add org.eclipse.jdt.core.

Tip

Plugin org.eclipse.jdt.core defines a set of interfaces which represents the elements of a Java Project, e.g. Projects, Packages and Compilationsunits.

Also add org.eclipse.core.resources" to the dependencies, we need this later.

Add the extension point "org.eclipse.ui.handlers" to your project and create a handler. This handler shall define for the commandId "de.vogella.plugin.htmlconverter.convert" the class "de.vogella.plugin.htmlconverter.handler.Convert".

This should result in the following plugin.xml.

				
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
   <extension
         point="org.eclipse.ui.menus">
      <menuContribution
            locationURI="popup:org.eclipse.jdt.ui.PackageExplorer">
         <command
               commandId="de.vogella.plugin.htmlconverter.convert"
               label="Create HTML"
               style="push">
         </command>
      </menuContribution>
   </extension>
   <extension
         point="org.eclipse.ui.commands">
      <command
            id="de.vogella.plugin.htmlconverter.convert"
            name="Convert">
      </command>
   </extension>
   <extension
         id="lars"
         name="lars"
         point="org.eclipse.ui.handlers">
      <handler
            class="de.vogella.plugin.htmlconverter.handler.Convert"
            commandId="de.vogella.plugin.htmlconverter.convert">
      </handler>
   </extension>

</plugin>

			

4.3. Create the code

Create the class "de.vogella.plugin.htmlconverter.handler.Convert"

Tip

Eclipse allows to save information on each file in the workspace. You can use the interface IResource and the methods setPersistentProperty and getPersistentProperty. With these functions you can save Strings on files. We use this to save the directory on the Java source files so that we can re-use this directory for the HTML creation.

Create the following class which will the responsible to write the Java class as HTML.

				
package de.vogella.plugin.htmlconverter.handler;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.ui.handlers.HandlerUtil;

public class Convert extends AbstractHandler {
	private QualifiedName path = new QualifiedName("html", "path");

	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {

		IStructuredSelection selection = (IStructuredSelection) HandlerUtil
				.getActiveMenuSelection(event);
		DirectoryDialog fileDialog = new DirectoryDialog(HandlerUtil
				.getActiveShell(event));
		String directory = "";
		Object firstElement = selection.getFirstElement();
		if (firstElement instanceof ICompilationUnit) {
			ICompilationUnit cu = (ICompilationUnit) firstElement;
			IResource res = cu.getResource();
			boolean newDirectory = true;
			directory = getPersistentProperty(res, path);

			if (directory != null && directory.length() > 0) {
				newDirectory = !(MessageDialog.openQuestion(HandlerUtil
						.getActiveShell(event), "Question",
						"Use the previous output directory?"));
			}
			if (newDirectory) {
				directory = fileDialog.open();

			}
			if (directory != null && directory.length() > 0) {
				analyze(cu);
				setPersistentProperty(res, path, directory);
				write(directory, cu);
			}

		} else {
			MessageDialog.openInformation(HandlerUtil.getActiveShell(event),
					"Information", "Please select a Java source file");
		}

		// iterator.next();

		// }
		return null;
	}

	protected String getPersistentProperty(IResource res, QualifiedName qn) {
		try {
			return (String) res.getPersistentProperty(qn);
		} catch (CoreException e) {
			return "";
		}
	}

	// TODO: Include this in the HTML output

	private void analyze(ICompilationUnit cu) {
		// Cool JDT allows you to analyze the code easily
		// I don't see really a use case here but I just wanted to do this here
		// as I consider this as cool and
		// what to have a place where I can store the data
		try {

			IType type = null;
			IType[] allTypes;
			allTypes = cu.getAllTypes();
			/**
			 * Search the public class
			 */
			for (int t = 0; t < allTypes.length; t++) {
				if (Flags.isPublic((allTypes[t].getFlags()))) {
					type = allTypes[t];
					break;
				}
			}

			String classname = type.getFullyQualifiedName();
			IMethod[] methods = type.getMethods();
		} catch (JavaModelException e) {
			e.printStackTrace();
		}

	}

	protected void setPersistentProperty(IResource res, QualifiedName qn,
			String value) {
		try {
			res.setPersistentProperty(qn, value);
		} catch (CoreException e) {
			e.printStackTrace();
		}
	}

	private void write(String dir, ICompilationUnit cu) {
		try {
			cu.getCorrespondingResource().getName();
			String test = cu.getCorrespondingResource().getName();
			// Need
			String[] name = test.split("\\.");
			System.out.println(test);
			System.out.println(name.length);
			String htmlFile = dir + "\\" + name[0] + ".html";

			System.out.println(htmlFile);
			FileWriter output = new FileWriter(htmlFile);
			BufferedWriter writer = new BufferedWriter(output);
			writer.write("<html>");
			writer.write("<head>");
			writer.write("</head>");
			writer.write("<body>");
			writer.write("<pre>");
			writer.write(cu.getSource());
			writer.write("</pre>");
			writer.write("</body>");
			writer.write("</html>");
			writer.flush();
		} catch (JavaModelException e) {
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
}

			

Finished. If you run your plugin you should be able to create HTML output from a Java source code file.

4.4. Restrict the extension - Visible When

The above example is semi-optimal. It would be better if the command if only display if a Source file is selected. We will improve this.

Select again plugin.xml and the extension tab. Select the command in the menu contribution. Using the right mouse add the condition to the command that it should only be visible if a org.eclipse.jdt.core.ICompilationUnit is selected. This is a class which can be compiled.

This will result in the following XML in the extensions in plugin.xml (tab source to the editor).

				
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
   <extension
         point="org.eclipse.ui.menus">
      <menuContribution
            locationURI="popup:org.eclipse.jdt.ui.PackageExplorer">
         <command
               commandId="de.vogella.plugin.htmlconverter.convert"
               label="Create HTML"
               style="push">
            <visibleWhen>
               <with
                     variable="activeMenuSelection">
                  <iterate>
                     <adapt
                           type="org.eclipse.jdt.core.ICompilationUnit">
                     </adapt>
                  </iterate>
               </with>
        </visibleWhen>
         </command>
      </menuContribution>
   </extension>
   <extension
         point="org.eclipse.ui.commands">
      <command
            id="de.vogella.plugin.htmlconverter.convert"
            name="Convert">
      </command>
   </extension>
   <extension
         id="lars"
         name="lars"
         point="org.eclipse.ui.handlers">
      <handler
            class="de.vogella.plugin.htmlconverter.handler.Convert"
            commandId="de.vogella.plugin.htmlconverter.convert">
      </handler>
   </extension>

</plugin>

			

5. Resources and Marker

5.1.  Overview

Eclipse represents Resources like Projects, Files, Folders, Packages as IResource.

Marker represent additional informations for resources, e.g. an error marker. Every marker can have attributes (key / value combination). Markers can be displayed in the standard view, e.g. the Task, Bookmark or the problems view. To be displayed in these views you have to use predefined attributes.

The following will demonstrate how to create marker for a selected resource.

5.2. Create markers

Create a plug-in project "de.vogella.plugin.markers". Add the dependency to org.eclipse.core.resources", "org.eclipse.jdt.core" and "org.eclipse.jdt.ui". Create the command "de.vogella.plugin.markers.AddMarker" with the default handler "de.vogella.plugin.markers.handler.AddMarker" and add this command to the menu.

Create the following code.

				
package de.vogella.plugin.markers.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.handlers.HandlerUtil;

public class AddMarker extends AbstractHandler {

	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {
		IStructuredSelection selection = (IStructuredSelection) HandlerUtil
				.getActiveSite(event).getSelectionProvider().getSelection();
		if (selection == null) {
			return null;
		}
		Object firstElement = selection.getFirstElement();
		if (firstElement instanceof IJavaProject) {
			IJavaProject type = (IJavaProject) firstElement;
			try {
				IResource resource = type.getUnderlyingResource();
				IMarker marker = resource.createMarker(IMarker.TASK);
				marker.setAttribute(IMarker.MESSAGE, "This a a task");
				marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
			} catch (Exception e) {
				e.printStackTrace();
			}

		}
		return null;
	}
}

			

If you run you can create a marker in the TODO list if you select a Java project and click your menu entry.

6. Deploying a plugin

To use your plugins in your standard Eclipse installation you can export your plugin and put it into the Eclipse "dropin" folder.

Select your plugin.xml and select the tab overview. Press the hyperlink "Export Wizard".

Select the plugin you want to export.

This will create a jar in the directory plugin. Copy this jar to the "dropin" directory in your Eclipse installation directory and re-start Eclipse. Your plugin should now be available.

Tip

During export you can also select "Install into host. Repository". This will export your plugin into the selected directory (Repository) and install it directly into the running Eclipse.

Tip

You can also provide a plugin via an update site. For creation of a Eclipse p2 update site see Eclipse P2

7. Thank you

Thank you for practicing with this tutorial.

Please note that I maintain this website in my private time. If you like the information I'm providing please help me by donating.

8. Questions and Discussion

For questions and discussion around this article please use the www.vogella.de Google Group. Also if you note an error in this article please post the error and if possible the correction to the Group.

I believe the following is a very good guideline for asking questions in general and also for the Google group How To Ask Questions The Smart Way.

9. Links and Literature

9.1. Source Code

http://www.vogella.de/code/codeeclipse.html Source Code of Examples