Historically, the Eclipse Runtime included the plug-in model and various functional elements. As you have seen, the plug-in or bundle model has moved down to the OSGi layer. This is implemented by the Equinox project. Most of the other functionality previously supplied by the Eclipse Runtime is now also part of the Equinox project. So we distinguish between the base standard OSGi implementation and the value-added function elements of Equinox discussed in this section.
Like JVMs and standard Java programs, OSGi systems have 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 Equinox 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.
A product is a level above an application. 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 information into one concept—something that users understand and run.
2.5.3 Extension Registry
OSGi provides a mechanism for defining and running separate components and a services mechanism to support inter-bundle collaboration. Equinox 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 following plugin.xml snippet:
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. Furthermore, 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 these:
- 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 loaded only 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.