Version 2.4
Copyright © 2007, 2008, 2009, 2010, 2011, 2012 Lars Vogel
03.12.2012
| Revision History | |||
|---|---|---|---|
| Revision 0.1 | 01.04.2008 | Lars Vogel |
Created |
| Revision 0.2 - 2.4 | 14.04.2009 - 03.12.2012 | Lars Vogel |
bugfixes and enhancements |
Table of Contents
A software component in Eclipse is called a plug-in.
The Eclipse IDE allows the developer to extend the IDE functionality via plug-ins. For example you can create new menu entries and associated actions via plug-ins.
This tutorial assumes that you are already familiar with using the Eclipse IDE and have experience in developing Java.
To get the required Eclipse tooling for plug-in development you have two options. You can download a special version of Eclipse to develop plug-ins or your can upgrade an existing Eclipse Java IDE.
Both approaches require that you have Java already installed.
Browse to the Eclipse download site and download the Eclipse Classic package.

Extract the downloaded file to your harddisk. Avoid having special characters or spaces in the path to your extract Eclipse.
In case you have downloaded the Eclipse Java IDE (or any other non RCP flavor) distribution you can use the Eclipse update manager to install the plug-ins required for RCP development.
To open the update manager select → .
Install → → from the Eclipse update site for your release. This would be for example http://download.eclipse.org/releases/kepler for the Eclipse 4.3. release. You may have to remove the Group items by category flag to see all available features.

We will create a plug-in which contributes a menu entry to the standard Eclipse menu.
Create a new plug-in project called
com.vogella.plugin.first
via
→ → → → .
Enter the data as depicted in the following screenshots.


Select the Hello, World Command! template and press the Next button.

The last page of the wizard allows you to customize the values of the wizard. You can leave the default values and press the button.

Eclipse may ask you if you want to switch to the plug-in development perspective. Answer Yes if you are prompted.

As result the following project is created.

Eclipse allows you to start a new Eclipse IDE with your plug-in included.
For this, select either your project folder or your
MANIFEST.MF
file, right-click on it and select
→ .

A new Eclipse workbench starts. This runtime Eclipse has your new menu entry included. If you select this menu entry a message box will be displayed.


You have several options to make your plug-in available in your Eclipse IDE. You can:
Install your plug-in directly into your Eclipse installation from your Eclipse IDE
Export your plug-in and copy it into your Eclipse installation
into the
dropins
folder
Create a update site and use the Eclipse update manager to install it from this site
The following describes all approaches.
You can install your plug-in directly into your running Eclipse IDE.
The Eclipse plug-in export wizard has an option for this. Open the export wizard via → → → .

In the export wizard dialog select in this case Install into host. Repository. This is depicted in the following screenshot.

If you export your plug-in locally you can put it into the
Eclipse
dropins
folder of your Eclipse installation. After a restart
of your Eclipse
your plug-in should be available and ready for use.
Open again the export wizard via → → → .
Select the plug-in you want to export and the folder to which this plug-in should get exported.

Press the
button.
This creates a
jar
file with the exported plug-in in the selected directory.
Copy this
jar
to
the
dropins
directory in your Eclipse installation directory and
re-start Eclipse.
After a restart of Eclipse your plug-in is available in your Eclipse installation and ready to be used.
You can also create an update site for your plug-in. An update site consists of static files which can be placed on a fileserver or a webserver. Other users can install Eclipse plug-in from this update site.
This requires that you create a feature project for the plug-in. You can export this feature project and use the Eclipse update manager to install the feature (with the plug-in).
You also need a category as the Eclipse update manager shows by default only features with a category. While the user can de-select this grouping you should always include a category for your exported feature to make it easy for the user to install your feature.
Create a feature project for your plug-in and add your plug-in to this feature. You create a feature project via → → → → .
Create the feature project similar to the following screenshots.


In your feature project create via the menu entry → → → → a new category definition.

Press the button and create a category with a name which describes your functionality. Add your feature to this category.


You can create an update site for your feature in a local directory on your machine. For this, select → → .


To use your category, switch to the
Options
tab and select the path to your
category.xml
file in the
Categorize repository
option.

Use the Eclipse update manager via → to install this new feature into your Eclipse IDE.
Use the update manager and point to your local directory and select and install your feature. In case you don't see your feature, try deselecting the Group items by category flag. In this case you have forgotten to use your category during the export.



Restart the Eclipse IDE after the installation. After a restart of Eclipse your plug-in should now be available in your Eclipse installation and ready to be used.

Create a feature project for your
com.vogella.plugin.first
plug-in and export it as Eclipse update site.
Use the Eclipse update manager to install the new feature into your Eclipse IDE.
In this example we will add a new context menu entry to the Package Explorer part. The context menu is displayed if the user select a file in the package explorer via a right mouse click. We will offer the option to create a HTML page from a Java source file.
To contribute to an existing menu or toolbar you need to know the corresponding ID. This ID can be found via the Menu Spy. See Eclipse Source Code Guide for details.
This tutorial uses Eclipse Commands. See Eclipse Commands Tutorial to learn how to work with commands.
Create a new plug-in project called de.vogella.plugin.htmlconverter. Do not use a template.
Select the
Dependencies
tab of the file
plugin.xml
and add the following dependencies to your plug-in.
org.eclipse.jdt.core
org.eclipse.core.resources
org.eclipse.core.runtime
org.eclipse.core.resources
org.eclipse.core.expressions
Add a command with the ID
de.vogella.plugin.htmlconverter.convert
and
the default handler
de.vogella.plugin.htmlconverter.handler.ConvertHandler
to your plug-in.
Add
this command to the menu via the extension point
org.eclipse.ui.menus
and use as the "locationURI"
popup:org.eclipse.jdt.ui.PackageExplorer. Set the label to "Create HTML" for this contribution.
The resulting file
plugin.xml
should look like the following.
<?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 defaultHandler="de.vogella.plugin.htmlconverter.handler.ConvertHandler" id="de.vogella.plugin.htmlconverter.convert" name="Convert"> </command> </extension> </plugin>
Eclipse allows to
save additional information for each file. You
can
use the
IResource
interface and the
setPersistentProperty()
and
getPersistentProperty()
methods. With these functions you can save Strings on files.
We use
these functions to save a directory for Java source
files which
already were exported via HTML.
Create the following
ConvertHandler
class.
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.ICompilationUnit; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.handlers.HandlerUtil; public class ConvertHandler extends AbstractHandler { private QualifiedName path = new QualifiedName("html", "path"); @Override public Object execute(ExecutionEvent event) throws ExecutionException { Shell shell = HandlerUtil.getActiveShell(event); ISelection sel = HandlerUtil.getActiveMenuSelection(event); IStructuredSelection selection = (IStructuredSelection) sel; Object firstElement = selection.getFirstElement(); if (firstElement instanceof ICompilationUnit) { createOutput(shell, firstElement); } else { MessageDialog.openInformation(shell, "Info", "Please select a Java source file"); } return null; } private void createOutput(Shell shell, Object firstElement) { String directory; ICompilationUnit cu = (ICompilationUnit) firstElement; IResource res = cu.getResource(); boolean newDirectory = true; directory = getPersistentProperty(res, path); if (directory != null && directory.length() > 0) { newDirectory = !(MessageDialog.openQuestion(shell, "Question", "Use the previous output directory?")); } if (newDirectory) { DirectoryDialog fileDialog = new DirectoryDialog(shell); directory = fileDialog.open(); } if (directory != null && directory.length() > 0) { setPersistentProperty(res, path, directory); write(directory, cu); } } protected String getPersistentProperty(IResource res, QualifiedName qn) { try { return res.getPersistentProperty(qn); } catch (CoreException e) { return ""; } } 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("\\."); String htmlFile = dir + "\\" + name[0] + ".html"; 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(); } } }
If you start this plug-in you should be able to create HTML output from a Java source file.

Currently our context menu is always displayed. We would like to show it only if a source file is selected. For this we will use a "visible-when" definition.
Add the
org.eclipse.core.expressions
plug-in as dependency to your plug-in. Select your menu
contribution.
Using the right mouse add the condition to the
command that it should
only be visible if a file is selected
which represents a
ICompilationUnit
from the
org.eclipse.jdt.core
package.
For this exercise you use the
predefined variable
activeMenuSelection
which contains the selection in the menu and iterate over
it. If the
selection can get adapted to
ICompilationUnit
then the contribution will be visible.
This will 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"> <visibleWhen checkEnabled="false"> <with variable="activeMenuSelection"> <iterate ifEmpty="false" operator="or"> <adapt type="org.eclipse.jdt.core.ICompilationUnit"> </adapt> </iterate> </with> </visibleWhen> </command> </menuContribution> </extension> <extension point="org.eclipse.ui.commands"> <command defaultHandler="de.vogella.plugin.htmlconverter.handler.Convert" id="de.vogella.plugin.htmlconverter.convert" name="Convert"> </command> </extension> </plugin>
If you now start your plug-in, the menu entry should only be visible if at least one compilation unit has been selected.
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.
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
AddMarkerHandler
in the
de.vogella.plugin.markers.handler
class 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; writeMarkers(type); } return null; } private void writeMarkers(IJavaProject type) { 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(); } } }
If you run you can create a marker in the TODO list if you select a Java project and click your menu entry.

Adapters help to display information about objects in view without having to adjust the existing views. In this example we will create a small view which allows to select objects and use the properties view to display them.
Adapters are used on several places for example you can use an adapter to display your data in the outline view. See Outline View Example for an example how to do this.
We will simple use an adapter to show our data in the property view. Create a new plug-in project "de.vogella.plugin.adapter". Use the "Plug-in with a view" template with the following settings.

Add the dependency "org.eclipse.ui.views" in tab dependencies of plugin.xml.
Create the following data model.
package de.vogella.plugin.adapter.model; public class Todo { private String summary; private String description; public String getSummary() { return summary; } public void setSummary(String summary) { this.summary = summary; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
Change the code of SampleView.java to the following. After this change you should be able to run your project, open your view and see your todo items.
package de.vogella.plugin.adapter.views; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; import de.vogella.plugin.adapter.model.Todo; public class SampleView extends ViewPart { public static final String ID = "de.vogella.plugin.adapter.views.SampleView"; private TableViewer viewer; class ViewLabelProvider extends LabelProvider implements ITableLabelProvider { public String getColumnText(Object obj, int index) { Todo todo = (Todo) obj; return todo.getSummary(); } public Image getColumnImage(Object obj, int index) { return getImage(obj); } public Image getImage(Object obj) { return PlatformUI.getWorkbench().getSharedImages() .getImage(ISharedImages.IMG_OBJ_ELEMENT); } }/** * This is a callback that will allow us to create the viewer and initialize * it. */public void createPartControl(Composite parent) { viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); viewer.setContentProvider(new ArrayContentProvider()); viewer.setLabelProvider(new ViewLabelProvider()); getSite().setSelectionProvider(viewer); viewer.setInput(getElements()); }/** * Passing the focus request to the viewer's control. */public void setFocus() { viewer.getControl().setFocus(); } // Build up a simple data model private Todo[] getElements() { Todo[] todos = new Todo[2]; Todo todo = new Todo(); todo.setSummary("First Todo"); todo.setDescription("A very good description"); todos[0] = todo; todo = new Todo(); todo.setSummary("Second Todo"); todo.setDescription("Second super description"); todos[1] = todo; return todos; } }
To displays its values in the property view, add the extension point "org.eclipse.core.runtime.adapters" to your project. The data of the extension point should be like the following.
<extension
point="org.eclipse.core.runtime.adapters">
<factory
adaptableType="de.vogella.plugin.adapter.model.Todo"
class="de.vogella.plugin.adapter.TodoAdapterFactory">
<adapter
type="org.eclipse.ui.views.properties.IPropertySource">
</adapter>
</factory>
</extension>
Implement the factory and the new class "TodoPropertySource" which implements "IPropertySource".
package de.vogella.plugin.adapter; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.ui.views.properties.IPropertySource; import de.vogella.plugin.adapter.model.Todo; public class TodoAdapterFactory implements IAdapterFactory { @Override public Object getAdapter(Object adaptableObject, Class adapterType) { if (adapterType== IPropertySource.class && adaptableObject instanceof Todo){ return new TodoPropertySource((Todo) adaptableObject); } return null; } @Override public Class[] getAdapterList() { return new Class[] { IPropertySource.class }; } }
package de.vogella.plugin.adapter; import org.eclipse.ui.views.properties.IPropertyDescriptor; import org.eclipse.ui.views.properties.IPropertySource; import org.eclipse.ui.views.properties.TextPropertyDescriptor; import de.vogella.plugin.adapter.model.Todo; public class TodoPropertySource implements IPropertySource { private final Todo todo; public TodoPropertySource(Todo todo) { this.todo = todo; } @Override public boolean isPropertySet(Object id) { return false; } @Override public Object getEditableValue() { return this; } @Override public IPropertyDescriptor[] getPropertyDescriptors() { return new IPropertyDescriptor[] { new TextPropertyDescriptor("summary", "Summary"), new TextPropertyDescriptor("description", "Description") }; } @Override public Object getPropertyValue(Object id) { if (id.equals("summary")) { return todo.getSummary(); } if (id.equals("description")) { return todo.getDescription(); } return null; } @Override public void resetPropertyValue(Object id) { } @Override public void setPropertyValue(Object id, Object value) { String s = (String) value; if (id.equals("summary")) { todo.setSummary(s); } if (id.equals("description")) { todo.setDescription(s); } } }
If you run your workbench and open your View via Windows -> Show View -> Others -> Sample Category -> Sample View and the property view you should be able to view your data.

You can register
IResourceChangeListener
on resources in Eclipse. For example if you have a project you can add
or remove a resource listener to or from it.
// Add listener project.getWorkspace().addResourceChangeListener(listener); // Remove listener project.getWorkspace().removeResourceChangeListener(listener); // Example resource listener private IResourceChangeListener listener = new IResourceChangeListener() { public void resourceChanged(IResourceChangeEvent event) { if (event.getType() == IResourceChangeEvent.PRE_CLOSE || event.getType() == IResourceChangeEvent.PRE_DELETE) { if (event.getResource().equals(project)) { // Project deleted or closed // Do something } return; } if (resource == null) return; IResourceDelta delta = event.getDelta().findMember(new Path(resource.getURI().toPlatformString(false))); if (delta == null) { return; } if (delta.getKind() == IResourceDelta.REMOVED) { // Resource delete // Do something } } };
It's a comprehensive tool suite to debug, spy, spider, inspect and navigate Eclipse based application GUIs (Workbench or RCP). http://sourceforge.net/projects/yari/
VisualVM is a debugging tool which can be integrated into Eclipse. http://visualvm.java.net/eclipse-launcher.html
JVM Monitor is a Java profiler integrated with Eclipse to monitor CPU, threads and memory usage of Java applications. http://www.jvmmonitor.org/index.html
Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.com Google Group. I have created a short list how to create good questions which might also help you.
http://wiki.eclipse.org/Eclipse_Plug-in_Development_FAQ Eclipse Plug-in Development FAQ
http://www.eclipse.org/articles/article.php?file=Article-Adapters/index.html Adapters in Eclipse
http://www.eclipse.org/articles/Article-Resource-deltas/resource-deltas.html How to react to Eclipse resource deltas
Using markers, annotations, and decorators in Eclipse (IBM) .
vogella Training Android and Eclipse Training from the vogella team
Android Tutorial Introduction to Android Programming
GWT Tutorial Program in Java and compile to JavaScript and HTML
Eclipse RCP Tutorial Create native applications in Java
JUnit Tutorial Test your application
Git Tutorial Put everything you have under distributed version control system