Tuesday, 3 February 2009

Real World Eclipse Plugins in 2 minutes..

During a job interview if anyone asks you which IDE would you prefer, most probably your reply would be eclipse. If you are asked why, then like anyone who is at least a moderate level developer you would answer how eclipse is extensible, how it supports plugins, how productive it is.. etc. but so few of those above moderate developers go in to coding plugins although it is both fun and easy.

When I first interested in developing eclipse plugins, I googled to see some tutorials and examples. However I end up with many hello world examples which pops up messages or other actions which probably you won't care to do in a plugin. So here is a Real (not hello) World example in 2 minutes.

When I was a child my favourite toys were my lego building blocks. I used to have a star fleet with several stations over the house. The lego components are all open to extension. A cargo unit can be added to the extension point of a starship adding the cargo capabilities and that cargo unit can still let the ship to dock to the docking station. The system is quite simple ech peace has either small bulge or a hole which fit each other.

Eclipse is not much different, in eclipse universe the ide offers some extension points which you can connect and interact with eclipse ecosystem. Meanwhile you can also let others use your extension points to interact with your plugin or the other plugins you have been interacting with. Eclipse SDK has more 200 extension points which you can find in Eclipse Documentation. However it might be a little confusing at the begining, thanksfully eclipse offers some wizards to build some basic plugins on mostly used extension points.

Eclipse runs on an osgi implementation named Equinox. Equinox is the secret under the hood, how so many extensions and plugins can work together in coordination. In brief, OSGi technology provides a service-oriented plug-in-based platform for application development.

As I mentioned this won't be a hello world application. So to have a real world plugin we need a real world problem. If you ever developed multi language applications you may have noticed some languages have non standart characters which may become problem in your resource bundles. Although I already have been using a great resource bundle plugin, my current company wants to organise the resource bundles alphabetically on the value, not the key. However, the current resource bundle plugin organises according to key. Since we can not use this plugin every developer had different ways to convert those chars. One had an html page with a jscript, an other build a swing application, one other pasted the unicode values somewhere he can lookup.

To make everyones life easier lets built a plugin for this problem. Our aim is to interact with the resource bundle properties file as soon as it is saved and validate the content by replacing the non standart letters with the unicode values and finally save the file.
**Attention the method below may not be the most efficient and best algorithm but a quick and easy fix for daily problem and a basic tutorial for eclipse plugins.**

To build a plugin we need to find the extension points we need, however, luckily eclipse has some plugin templates which uses some the most common extension points. All we need is to browse and find one then modify the code to our needs.

First lets open a new plugin project.

Enter a name for the project and choose eclipse version.

Enter plugin content details and click next. Here is a list of prebuilt templates for plugins. Browse throught the list, you will notice each template uses different extension points to enable different kind of interacions with the ide. There is one template called "Plug-in with a incremental project builder" which actually registers a builder for the project and validates the file which is actually what we also aim to do.

Next enter the details about the plugin and the builder and click finish.

If you navigate through the genareted files you will find 4 classes and when you examine the code you will realise ResourceBundleBuilder is the one triggered to validate the file.
First we need to find where the file is processed. In line 126 of ResourceBundleBuilder.java we find the method responsible for checking the xml.
void checkXML(IResource resource) {
if (resource instanceof IFile && resource.getName().endsWith(".xml")) {

All we need is to edit this method to handle our properties files to change the characters. Lets delete all the code inside this method and replace it with the following;

void checkXML(IResource resource) {
if (resource instanceof IFile && resource.getName().endsWith(".properties")) {
IFile file = (IFile) resource;

This code will process the file only if the extension of the file is "properties" and will send the file to changeTrChars method.

Now we need to read the contents of the file, change the characters and then save it.

private void changeTrChars(IFile file) {
InputStream is = null;
DataOutputStream out = null;
try {
is = file.getContents();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = null;
String finalLine = "";
while ((line = reader.readLine()) != null) {
//concanate the lines
finalLine += line + "\n";
//we are done with the input stream
//convert chars
String toOut = convertTr(finalLine);
//if any chars have been changed
if (!toOut.equals(finalLine)) {
File fileTo = new File(file.getProject().getLocation().toPortableString() + "/" + file.getProjectRelativePath().toPortableString());
out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(fileTo)));
//save the file
} catch (Exception e) {
} finally {


In this method we read the string from the inputStream we get from the file. Then send the string to convertTr method to change the chars and finally if the string changed we save on the same file. Since we are working on the same file we close the input stream whenever we are done to be able to use the outputStream on the same file.

Next method is convertTr which is only responsible for replacing the characters in the string with the unicode values.
private String convertTr(String nativeText) {
Map charMap = new HashMap();
charMap.put("ç", "\\\\u00e7");
charMap.put("Ç", "\\\\u00c7");
charMap.put("ğ, "\\\\u011f");
charMap.put("Ğ, "\\\\u011e");
charMap.put("ş, "\\\\u015f");
charMap.put("Ş, "\\\\u015e");
charMap.put("ı, "\\\\u0131");
charMap.put("İ, "\\\\u0130");
charMap.put("ö", "\\\\u00f6");
charMap.put("Ö", "\\\\u00d6");
charMap.put("ü", "\\\\u00fc");
charMap.put("Ü", "\\\\u00dc");
String asciiText = "";
if (nativeText != null) {
asciiText = new String(nativeText);
Set keySet = charMap.keySet();
Iterator it = keySet.iterator();
while (it.hasNext()) {
String nativeChar = (String) it.next();
String asciiChar = (String) charMap.get(nativeChar);
asciiText = asciiText.replaceAll(nativeChar, asciiChar);
return asciiText;

Since our code ready now we can clean unnecessary codes. we modified the template from xml to properties reader so we can delete everything about xmls. First delete the XMLErrorHandler inner class. Also delete parserFactory, marker methods and finally the getParser method.

Rest of the code in this class is reponsible for monitoring project and launching the code when any change occurs. ResourceBundleNature class is the class registering and enabling our plugin as a builder for the desired project. ToggleNatureAction class is the aclionListener for the right menu click which adds the builder nature to the project. Those classes are all using extension points to interact with the user interface and environment of eclipse IDE. You may examine the rest of the code to see how extension points work and have more knowledge about them but this template enabled us to build the desired plugin just in 2 minutes.

Just right click your plugin project and run it as an eclipse application.
A new eclipse instance with your plugin enabled will popup. You can open a new project and enable the nature with a right click (add nature). If you just type anything in a property file in this project you will see your plugin running and converting the given characters in to unicode. When you are done testing right click and export your plugin and copy into plugins folder of any eclipse installiation you want to run on.

Of course it is nice to know how equinox and extension points work in detail but it is not an excuse not to know for not coding plugins. As you can see you can develop plugins without even knowing the secrets of the platform. Just find the template suitable for you and when you are done, examine the generated code. So in short time you will also master what's under the hood.

Later I will try to post more about details on extansion points, so stay tuned...