2.5 The Runtime
Historically, the Eclipse Runtime also included the plug-in model. As you have seen, the plug-in model has moved down to the OSGi layer. This leaves the remainder of the Runtime on top. The Runtime is home to several key mechanisms, in particular, the application model and extension registry.
Like the OSGi framework and JVMs, the Eclipse Runtime has to be told what to do. To run Eclipse, someone has to define an application. An application is very much like the main() method in normal Java programs. After the Runtime starts, it finds and runs the specified application. Applications are defined using extensions. Application extensions identify a class to use as the main entry point. When you run Eclipse, you can specify an application to run. Once invoked, the application is in full control of Eclipse. When the application exits, Eclipse shuts down.
The notion of a product is a level above applications. You can run Eclipse by just specifying an application, but the product branding context (e.g., splash screen and window icons) and various bits of customization (e.g., preferences and configuration files) would be missing. The notion of a product captures this diffuse set of information into one concept—something that users understand and run.
2.5.3 Extension Registry
The OSGi specification provides a mechanism for defining and running separate components. The Eclipse Runtime adds to that a mechanism for declaring relationships between plug-ins—the extension registry. Plug-ins can open themselves for extension or configuration by declaring an extension point. Such a plug-in is essentially saying, "If you give me the following information, I will do ..." Other plug-ins then contribute the required information to the extension point in the form of extensions.
The canonical example of this is the UI plug-in and its actionSets extension point. Simplifying somewhat, action sets are how the UI talks about menu and toolbar entries. The Eclipse UI exposes the extension point org.eclipse.ui.actionSets and says,
"Plug-ins can contribute actionSets extensions that define actions with an id, a label, an icon, and a class that implements the interface IActionDelegate. The UI will present that label and icon to the user, and when the user clicks on the item, the UI will instantiate the given action class, cast it to IActionDelegate, and call its run() method."
Figure 2–6 shows this relationship graphically.
Figure 2–6 Extension contribution and use
Extension-to-extension point relationships are defined using XML in a file called plugin.xml. Each participating plug-in has one of these files. In this scenario, org.eclipse.ui’s plugin.xml includes the following:
org.eclipse.ui/plugin.xml <extension-point id="actionSets" name="Action Sets"/>
The Hyperbola plug-in, org.eclipsercp.hyperbola, developed later in the book, similarly contributes an extension using the markup shown in the plugin.xml snippet below:
org.eclipsercp.hyperbola/plugin.xml <extension point="org.eclipse.ui.actionSets"> <actionSet id="org.eclipsercp.hyperbola.debugActionSet"> <action id="org.eclipsercp.hyperbola.debug" class="org.eclipsercp.hyperbola.DebugAction" icon="icons/debug.gif" label="Debug Chats"/> </actionSet> </extension>
The actionSets extension point contract plays out as follows: The UI presents the label "Debug Chats" along with the debug.gif icon. When the user clicks on the action, the class DebugAction is instantiated and its run() method is called.
This seemingly simple relationship is extremely powerful. The UI has effectively opened up its implementation of the menu system, allowing other plug-ins to contribute menu items. Further, the UI plug-in does not need to know about the contributions ahead of time and no code is run to make the contributions—everything is declarative and lazy. These turn out to be key characteristics of the registry mechanism and Eclipse as a whole. Some other characteristics worth noting here are:
- Extensions and extension points are used extensively throughout Eclipse for everything from contributing views and menu items to connecting Help documents and discovering builders that process resource changes.
- The mechanism can be used to contribute code or data.
- The mechanism is declarative—plug-ins are connected without loading any of their code.
- The mechanism is lazy in that no code is loaded until it is needed. In our example, the DebugAction class was only loaded when the user clicked on the action. If the user does not use the action, the class is not loaded.
- This approach scales well and enables various approaches for presenting, scoping, and filtering contributions.