Chapter 46.  Adding Grahical User Interfaces and Eclipse Plugins

46.1. Architecture and documentation

IC2D is composed of several plugins:

  • org.objectweb.proactive.ic2d : This plugin is the "frame" which contains the other plugins. It is only needed in the standalone version.

  • org.objectweb.proactive.ic2d.monitoring : provides graphical representation of hosts, runtimes, virtual nodes and active objects topology, also displaying communications between active objects.

  • org.objectweb.proactive.ic2d.jobmonitoring : provides tree-based representation of hosts, runtimes , virtual nodes and active objects.

  • org.objectweb.proactive.ic2d.launcher : initiates application deployment using deployment descriptors

  • org.objectweb.proactive.ic2d.lib : provides Java archives (jar) required by the other plugins which are not provided by the Eclipse like ProActive.jar, log4j.jar, etc.

  • org.objectweb.proactive.ic2d.console : provides logging capability through the Eclipse console.

46.1.1. org.objectweb.proactive.ic2d.monitoring

The aim of this plugin is to provide the essential features for monitoring of ProActive applications. Monitorable entities are

Figure 46.1, “Graphical representation of the data” shows the graphical representation of hosts, virtual nodes, runtimes (ProActive JVM), nodes, and active objects.

Graphical representation of the data

Figure 46.1. Graphical representation of the data

46.1.1.1. Class Diagrams

The diagram Figure 46.2, “Class diagram” describes relationships between Java classes:

  • The AOObject class represents an Active Object.

  • The NodeObject class represents a node. Nodes contain Active Objects.

  • The VMObject represents a runtime. Runtimes contain nodes

  • The VNObject class represents a virtual node. The virtual node is a logical entity which has no real existence at runtime. When using Deployment Descriptors, it is the mapping of a virtual node on a runtime that leads to the creation of one or more nodes on this runtime. Virtual nodes can be mapped on more than one runtime, thus as shown in the figure, a node is bound to both a runtime and a virtual node.

  • The HostObject class represents the hardware that hosts the runtime, it is possible to coallocate several runtimes on the same host

  • The WorldObject class is a "special" object that allows to gather hosts and virtual nodes under a common root.

Class diagram

Figure 46.2. Class diagram

46.1.1.2. Monitoring in detail

When IC2D is used to monitor a host, it looks for any available runtimes on the host, then enumerates any nodes, virtual nodes and active objects contained within each runtime.

In order to do this, it grabs the URL entered by the user, then creates a new HostObject and add it to the WorldObject. Next, a thread starts and regularly queries the WorldObject to explore itself. The following sequence diagram explains how a WorldObject explores itself for the first time (Figure 46.3, “The world exploring itself for the first time”).

  • The WorldObject queries its HostObjects to explore themselves

  • Each HostObject looks for ProActive Runtimes on the current host then creates VMObject s corresponding to the newly discovered runtimes

  • Each VMObject explores itself, looking for Nodes contained within its ProActiveRuntime. Each Node is mapped into a NodeObject

  • Each NodeObject looks for contained active objects asking it to the ProActiveRuntime of its parent (VMObject) and creates the corresponding AOObject s.

The world exploring itself for the first time

Figure 46.3. The world exploring itself for the first time

Now all objects are found. And these operation will be regularly repeated until the user stops monitoring.

46.1.1.3. Model View Controller (MVC) -- The Graphical Editing Framework (GEF)

The Graphical Editing Framework (GEF) allows developers to take an existing application model and quickly create a rich graphical interface.

GEF employs an MVC (Model View Controller) architecture which enables simple changes to be applied to the model from the view.

This section introduces the needed to the comprehension of GEF. For more details about GEF go to the Section 46.1.1.4, “Links” .

We describe here the implementation of the MVC pattern used within IC2D:

The Models

Figure 46.4. The Models

The Controllers and the factory

Figure 46.5. The Controllers and the factory

The Views

Figure 46.6. The Views

Three things to not forget

In blue, the data which we use with GEF. As you can see it, they are organized in a tree structure.

The data strucure of the monitoring plugin

Figure 46.7.  The data strucure of the monitoring plugin

Description of the creation of the controllers and the figures step by step :

  1. We indicate to GEF the root element of the tree, and the factory.

  2. GEF queries the factory to create the controller corresponding to the root.

  3. GEF queries the obtained controller to create the figure corresponding to the model.

  4. GEF queries the root to provide it its sons.

  5. On each one of these children, GEF do the same process.

  6. GEF queries the factory to create the controller corresponding to the first child.

  7. GEF queries the obtained controller to create the figure corresponding to the model.

  8. GEF queries the model to provide it its sons.

  9. etc...

46.1.1.4. Links

The official site of GEF: http://www.eclipse.org/gef/

A web page referring a lot of very interesting links about GEF: http://eclipsewiki.editme.com/GEF

A detailed description of GEF : http://eclipse-wiki.info/GEFDescription

A tutorial : 'Building a GEF-based Eclipse editor' : Part 0 , Part 1 , Part 2 , Part 3 .

Somes GEF examples : http://eclipse-wiki.info/GEFExamples

46.1.1.5. Observer/Observable

The pattern Observer/Observable is used to update the figures when the model changes.

In the Figure 46.8, “Observable objects” you can see all the observable objects with methods which can call notifyObservers .

Observable objects

Figure 46.8. Observable objects

In the Figure 46.9, “Observer objects” , you can see all the observer objects and where the method update is overriden.

Observer objects

Figure 46.9. Observer objects

In the Table 46.1, “Observable and Observer objects” , you can see each observable with their observers.

Observable

Observer

WorldObject

WorldEditPart

MonitorThread

VirtualNodesGroup

HostObject

HostEditPart

VMObject

VMEditPart

NodeObject

NodeEditPart

AOObject

AOEditPart

Table 46.1. Observable and Observer objects

46.1.1.6. The espionage of the active objects

In the following diagram, you can see all classes necessary to the espionage of the active objects.

Spy classes

Figure 46.10. Spy classes

When a node is found for the first time, IC2D put a spy in the node.

46.1.1.7. How an event of a proactive object arrive to the monitoring plugin?

Once the spy is in the node, it regularly asks to the SpyEventManager to provide all the events. The next step is explained in the Figure 46.11, “Active Objects' events management”.

Active Objects' events management

Figure 46.11. Active Objects' events management

  1. Then the Spy transmits all these events to the SpyListener .

  2. For the each event, the SpyListener calls the corresponding method on SpyEventListener

  3. The SpyEventListener searches the AOObject concerned with this event (thanks to the Node attribut of his class). And it modifies the state of this object.

  4. The AOObject notify its observers.

  5. The AOEditPart , which is an AOObject observer, update the view of this Active Object.

46.1.1.8. When a new Spy is created?

A new spy is created each time that a new Node is found.

46.1.1.9. How a new Spy is created?

The NodeObject calls its "addSpy()" method :

  1. This method creates a SpyEventListener with the NodeObject in parameter.

  2. It creates also a SpyListener with the SpyEventListener in parameter.

  3. Next,it turns active the previous SpyListener.

  4. And creates a new Active Object (with the ProActive.newActive method) which is the spy with 2 parameters : the turned active object (SpyListener) , and the node . (This node is given in parameter at the constructor of the NodeObject)

46.1.1.10.  How an active object is added to the objects to monitor?

  1. When an active object is found for the first time, we ask to the NodeObject to provide us the spy.

  2. We call the ' addMessageEventListener ' method on the Spy .

  3. The Spy calls on its SpyEventManager the ' addMessageEventListener ' method.

  4. The SpyEventManager adds a MessageEvent listener to the body of the active object.

46.1.1.11. How to create and use filters

In some cases, you may want to hide some objects to the users, i.e. don't monitor some internal objects. For example, spy objects used by IC2D for monitoring JVMs. That's why we introduce the concept of filtering in the monitoring plugin.

The package org.objectweb.proactive.monitoring.filters contains:

  • Filter : an abstract class, which has to be extended by all filter classes. This class provides the method filter (AbstractDataObject) that returns true if it matches the filter, otherwise false.

  • FilterProcess : provides the method filter (AbstractDataObject object).This is the first method called when a new object is discovered. It applies all filters on the object and if at least one filter returns true the object is not monitored.

46.1.2. org.objectweb.proactive.ic2d.console

This plugin provides several methods to log in the console :

  • log (String message)

  • warn (String message)

  • err (String message)

  • logException (Throwable e)

  • debug (String message)

  • debug (Throwable e)

You can have several different consoles. For example, the plugin monitoring logs in a console named "Monitoring", all the log4j messages are logged in the console "Log4j", ...

If you want to add your own console, you must choose a unique name. and call the method Console. getInstance (String yourUniqueName) to obtain the console (if it didn't exist it is created). Then you can call the methods above on your console.

46.1.3. org.objectweb.proactive.ic2d.lib

This plugin contains all jar (which are not provided by Eclipse) necessary to the other plugins (like ProActive.jar, log4j.jar, ...). So if you modify the code and need a new jar, you have to add it to the plugin lib. And if you create a new plugin which needs a jar which is in the plugin lib, it must be dependent of this plugin.

46.2. Extending IC2D

46.2.1. How to checkout IC2D

Here is the IC2D SVN repository : svn://scm.gforge.inria.fr/svn/proactive/branches/proactive_newIC2D

You have to checkout :

  • org.objectweb.proactive.ic2d

  • org.objectweb.proactive.ic2d.monitoring

  • org.objectweb.proactive.ic2d.lib

  • org.objectweb.proactive.ic2d.console

  • org.objectweb.proactive.ic2d.launcher

If you are using Eclipse and its plugin Subclipse , open the SVN Repository perspective and checkout all those folders as new Java projects .

SVN Repository

Figure 46.12. SVN Repository

You'll maybe have to replace the proactive.jar file in the plugin org.objectweb.proactive.ic2d.lib, it depends on your ProActive version.

Now, you can run IC2D clicking on the link Launch the product in ic2d.product in the org.objectweb.proactive.ic2d project.

ic2d.product

Figure 46.13. ic2d.product

46.2.2. How to implement a plug-in for IC2D

IC2D is a Rich Client Platform (RCP) based on the familiar Eclipse plug-in architecture .

46.2.2.1.  Create a project with the plug-in project wizard

If you want to create a plug-in for IC2D, you have to use the Eclipse's Plug-in Development Environment (PDE) . This is a complete environment that Eclipse provides for plug-in development. The PDE adds a new perspective and several views and wizards that help you create, maintain, and publish plug-ins. The PDE creates boilerplate starter code that you can use to build your plug-in. This section explains how to use the plug-in project wizard to create your plug-in.

  1. Select File > New > Project from the menu bar to open the new project wizard.

  2. Select Plug-in Project in Plug-in Development .

Create a new project

Figure 46.14. Create a new project

  1. Click Next .

  2. In the Project name field, enter a name for the plug-in. For example, we chose org.objectweb.proactive.ic2d.example. You must use the fully-qualified name to ensure its uniqueness.

  3. In the Project contents pane, accept the default directory value.

  4. Make sure the Create a Java project option is selected since we want our project to contain Java files. Accept the default values of the other options.

  5. Beginning in Eclipse 3.1 you will get best results by using the OSGi bundle manifest . In contrast to previous versions, this is now the default.

Specify name and plug-in structure

Figure 46.15. Specify name and plug-in structure

  1. Click Next .

  2. Now enter the fully qualified ID of the plug-in . By default it is the same as its project name.

  3. Accept the default values of the other options.

Specify plug-in content

Figure 46.16. Specify plug-in content

  1. Click Finish .

46.2.2.2. The plug-in structure

The plug-in project has the file structure illustrated in the followed figure.

The plug-in structure

Figure 46.17. The plug-in structure

46.2.2.3. Plug-in manifest

The plug-in manifest ties all the code and resources together. When you first create a plug-in, Eclipse will create and open the manifest for you automatically. The manifest is split into two files: MANIFEST.MF and plugin.xml . PDE provides a fancy editor to modify the options stored in these files (see Figure 46.18, “ Interface for editing the manifest and related files. ” ) but also allows you to edit the source directly.

Interface for editing the manifest and related files.

Figure 46.18.  Interface for editing the manifest and related files.

MANIFEST.MF

The OSGi bundle manifest is stored in MANIFEST.MF. OSGi is the name of a standard that Eclipse uses for dynamically loading plug-ins. Example 46.1, “MANIFEST.MF” shows the OSGi bundle manifest generated by the plug-in wizard. Everything in this file can be edited by the Manifest editor, so there should be no need to edit it by hand . However if you need to, just double-click it in the Package Explorer to bring up the Manifest editor, then click on the MANIFEST.MF tab in the editor to see and modify the source.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2 Bundle-Name:
Example Plug-in Bundle-SymbolicName:
org.objectweb.proactive.ic2d.example
Bundle-Version: 1.0.0 Bundle-Activator:
org.objectweb.proactive.ic2d.example.ExamplePlugin
Bundle-Localization: plugin Require-Bundle:
org.eclipse.ui, org.eclipse.core.runtime
Eclipse-AutoStart: true
						

Example 46.1. MANIFEST.MF

plugin.xml

The Eclipse extension manifest is called plugin.xml. It's used for defining and using Eclipse extension points , so if you're not using extension points then this file may be omitted. Extension points are the fundamental way that Eclipse plug-ins are tied together. This new plug-in is not yet using extension points so the plug-in wizard didn't generate the plugin.xml file.

46.2.2.4. Plug-in class

The plug-in class is an optional singleton class that can be used to store global information for the plug-in. It's also a convenient place to put a few static utility functions used by other classes in the plug-in. See the listing Example 46.2, “ExamplePlugin.java” for the plug-in class that was created for us by the plug-in wizard.

package org.objectweb.proactive.ic2d.example;

import org.eclipse.ui.plugin.*;
import org.eclipse.jface.resource.ImageDescriptor;
import org.osgi.framework.BundleContext;

/**
 * The main plugin class to be used in the desktop.
 */
public class ExamplePlugin extends AbstractUIPlugin {

	//The shared instance.
	private static ExamplePlugin plugin;
	
	/**
	 * The constructor.
	 */
	public ExamplePlugin() {
		plugin = this;
	}

	/**
	 * This method is called upon plug-in activation
	 */
	public void start(BundleContext context) throws Exception {
		super.start(context);
	}

	/**
	 * This method is called when the plug-in is stopped
	 */
	public void stop(BundleContext context) throws Exception {
		super.stop(context);
		plugin = null;
	}

	/**
	 * Returns the shared instance.
	 */
	public static ExamplePlugin 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 AbstractUIPlugin.imageDescriptorFromPlugin("org.objectweb.proactive.ic2d.example", path);
	}
}
					

Example 46.2. ExamplePlugin.java

46.2.2.5. Build properties

The build.properties file (see Example 46.3, “build.properties” ) will be needed when exporting the application for others to use . In particular if your application needs any resources like icons they should be listed here in the bin.includes section. The Plug-in Manifest editor provides a convenient interface to modify this file that is less error-prone than modifying it by hand.

source.. = src/
output.. = bin/
bin.includes = META-INF/,\ .
					

Example 46.3. build.properties

46.2.2.6. How to add your plugin to IC2D

In the project org.objectweb.proactive.ic2d , open ic2d.product . In the Configuration tab, click Add .

Configuration

Figure 46.19. Configuration

Then select your plug-in.

Plug-in selection

Figure 46.20. Plug-in selection

  1. Now, click Add Required Plug-ins .

  2. Return to the Overview tab and click Synchronize . Now launch ic2d by clicking Launch the product .

  3. You can verify that your plug-in is integrated : in the IC2D frame, go to Help > About product > Plug-in Details .

About product Plug-ins

Figure 46.21. About product Plug-ins

46.2.2.7. Perspectives, views and editors

Workbench structure

Figure 46.22. Workbench structure

46.2.2.8. Perspectives

Perspectives provide an additional layer of organization inside the workbench page. A perspective defines an appropriate collection of views , their layout, and applicable actions for a given user task. Users can switch between perspectives as they move across tasks. From an implementation point of view, the user's active perspective controls which views are shown on the workbench page and their positions and sizes. Editors are not affected by a change in perspective.

A new perspective is added to the workbench using a simple two step process :

  1. Add a perspective extension to the plugin.xml file.

  2. Define a perspective class for the extension within the plug-in.

Step 1 : Add a Perspective Extension to the plugin.xml file

  1. Open MANIFEST.MF with the Plug-in Manifest Editor

  2. Open the Extensions tab

Extensions tab (no extensions)

Figure 46.23. Extensions tab (no extensions)

  1. Click Add

  2. In the Extensions Points tab, select org.eclipse.ui.perspectives

Ajouter un screenshot

  1. Click Finish

Extensions tab (org.eclipse.ui.perspectives)

Figure 46.24.  Extensions tab (org.eclipse.ui.perspectives)

  1. Right click the new extension : New > perspective

  2. Now, enter the ID , the name and the class corresponding to the perspective.

Extensions tab (Example)

Figure 46.25. Extensions tab (Example)

If the plugin.xml file didn't exist, it is now created. Example 46.4, “plugin.xml” shows the plugin.xml file that was created.

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
   <extension
         point="org.eclipse.ui.perspectives">
      <perspective
            class="org.objectweb.proactive.ic2d.example.ExamplePerspective"
            id="org.objectweb.proactive.ic2d.example.ExamplePerspective"
            name="Example"/>
   </extension>
</plugin>
          

Example 46.4. plugin.xml

Step 2 : Define a Perspective Class for the Extension within the Plug-in

Now we need to define the perspective class which must implements the IPerspectiveFactory interface :

package org.objectweb.proactive.ic2d.example;

import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;

public class ExamplePerspective implements IPerspectiveFactory {

	public static final String ID="org.objectweb.proactive.ic2d.example.ExamplePerspective";
	
	public void createInitialLayout(IPageLayout layout) {
		// TODO Auto-generated method stub

	}

}
					

Example 46.5. ExamplePlugin.java

You have created your first perspective !

46.2.2.9. Views

A view is typically used to navigate a hierarchy of information, open an editor, or display properties for the active editor.

Create a view looks like create a perspective. You have to add a perspective extension to the plugin.xml file and to define a view class for the extension within the plug-in .

Step 1 : Add a View Extension to the plugin.xml file

Add an extension : org.eclipse.ui.views, then add a view and configure it.

46.2.2.10. Editors

An editor is a visual component within a workbench page. It is used to interact with the primary focus of attention, which may be a document, data object, or person. The primary focus of attention is a reflection of the primary task.