3.3. Plug-in Manifest
As stated earlier, there are two filesMANIFEST.MF and plugin.xmlper plug-in defining various high-level aspects so that the plug-in does not have to load until you need its functionality. The format and content for these files can be found in the Eclipse help facility accessed by Help > Help Contents; look under Platform Plug-in Developer Guide > Reference > Other Reference Information > OSGi Bundle Manifest and Plug-in Manifest.
What is OSGi?
Eclipse originally used a home-grown runtime model/mechanism that was designed and implemented specifically for Eclipse. This was good because it was highly optimized and tailored to Eclipse, but less than optimal because there are many complicated issues, and having a unique runtime mechanism prevented reusing the work done in other areas (e.g., OSGi, Avalon, JMX, etc.). As of Eclipse 3.0, a new runtime layer was introduced based upon technology from the OSGi Alliance (www.osgi.org) that has a strong specification, a good component model, supports dynamic behaviour, and is reasonably similar to the original Eclipse runtime. With each new release of Eclipse, the Eclipse runtime API and implementation (e.g. "plug-ins") continues to align itself more and more closely with the OSGi runtime model (e.g. "bundles").
Bundle-Name: Favorites Plug-in Bundle-SymbolicName: com.qualityeclipse.favorites; singleton:=true Bundle-Version: 1.0.0 Bundle-Activator: com.qualityeclipse.favorites.FavoritesPlugin Bundle-Vendor: Quality Eclipse
Strings in the plug-in manifest, such as the plug-in name, can be moved into a separate plugin.properties file. This process facilitates internationalization as discussed in Chapter 16, Internationalization.
220.127.116.11. Plug-in identifier
The plug-in identifier (Bundle-SymbolicName) is designed to uniquely identify the plug-in and is typically constructed using Java package naming conventions (e.g., com.<companyName>.<productName>, or in our case, com.quality-eclipse.favorites). If several plug-ins are all part of the same product, then each plug-in name can have four or even five parts to it as in com.quality-eclipse.favorites.core and com.qualityeclipse.favorites.ui.
18.104.22.168. Plug-in version
Every plug-in specifies its version (Bundle-Version) using three numbers separated by periods. The first number indicates the major version number, the second indicates the minor version number, and the third indicates the service level, as in 1.0.0. You can specify an optional qualifier that can include alphanumeric characters as in 1.0.0.beta_1 or 22.214.171.1246-03-20 (no whitespace). Eclipse does not use or interpret this optional qualifier in any way, so the product builder can use it to encode the build type, build date, or other useful information.
For an outline of the current use of version numbers and a proposed guideline for using plug-in version numbering to better indicate levels of compatibility, see eclipse.org/equinox/documents/plugin-versioning.html.
Both the name and the provider are human-readable text, so they can be anything and are not required to be unique. To see the names, versions, and providers of the currently installed plug-ins, select Help > About Eclipse SDK to open the About dialog (see Figure 3-3), and then click the Plug-in Details button to open the Plug-ins dialog (see Figure 3-4).
Figure 3-3. The About Eclipse SDK dialog, showing information about the Eclipse platform.
Figure 3-4. The About Eclipse SDK Plug-ins dialog, showing all the installed plug-ins with the Favorites plug-in highlighted at the bottom.
The Bundle-ClassPath declaration in the MANIFEST.MF file is a comma separated list describing which libraries (*.jar files) contain the plug-in code. The Export-Package declaration is a comma-separated list indicating which packages within those libraries are accessible to other plug-ins (see Section 20.2.4, How Eclipse is different, on page 713 and Section 20.2.5, Related plug-ins, on page 713).
Bundle-ClassPath: favorites.jar Export-Package: com.qualityeclipse.favorites.views
The plug-in loader instantiates a separate class loader for each loaded plug-in, and uses the Require-Bundle declaration of the manifest to determine which other plug-insthus which classeswill be visible to that plug-in during execution (see Section 20.9, Plug-in ClassLoaders, on page 742 for information about loading classes not specified in the Require-Bundle declaration).
Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime
If a plug-in has been successfully compiled and built but, during execution, throws a NoClassDefFoundError, it may indicate that the plug-in project's Java classpath is out of sync with the Require-Bundle declaration in the MANIFEST.MF file. As discussed in Section 2.3.1, The Plug-in manifests, on page 71, it is important to keep the classpath and the Require-Bundle declaration in sync.
When the plug-in loader is about to load a plug-in, it scans the Require-Bundle declaration of a dependent plug-in and locates all the required plug-ins. If a required plug-in is not available, then the plug-in loader throws an exception, generating an entry in the log file (see Section 3.6, Logging, on page 122) and does not load the dependent plug-in. When a plug-in gathers the list of plug-ins that extend an extension point it defines, it will not see any disabled plug-ins. In this circumstance, no exception or log entry will be generated for the disabled plug-ins.
If a plug-in can successfully execute without a required plug-in, then that required plug-in can be marked as optional in the plug-in manifest. To do so, open the plug-in manifest editor and then switch to the Dependencies tab (see Figure 2-10 on page 73). Select the required plug-in, click the Properties button and then check the Optional checkbox in the Properties dialog (see Figure 3-5).
Figure 3-5. The required plug-in properties dialog.
Making this change in the plug-in manifest editor appends ;resolution:=optional to the required plug-in in the Require-Bundle declaration so that it now looks something like this:
Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime;resolution:=optional
If your plug-in requires not just any version of another plug-in, you can specify an exact version or a range of versions using the required plug-in properties dialog (see Figure 3-5). The following are some examples:
The general syntax for a range is
[ floor, ceiling )
where floor is the minimum version and ceiling is the maximum version. The first character can be [ or ( and the last character may be ] or ) where these characters indicate the following:
You can specify a floor or minimum version with no extra characters indicating that your plug-in needs any version greater than or equal to the specified version. Entering one of the preceding in the required plug-in properties dialog (see Figure 3-5) modifies the Require-Bundle declaration so that it now looks something like this:
Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime;bundle-version="[3.0.0,3.1.0)"
Finally, check the Reexport this dependency checkbox (see Figure 3-5) to specify that the dependent plug-in classes are made visible (are (re)exported) to users of this plug-in. By default, dependent classes are not exported (i.e., they are not made visible).
Import-Package is similar to Require-Bundle except that Import-Package specifies names of packages that are required for execution rather than names of bundles. Using Import-Package can be thought of as specifying the service required whereas using Require-Bundle is like specifying the service provider. Import-Package makes it easier to swap out one bundle for another that provides the same service, but harder to know who is providing that service.
A plug-in declares extension points so that other plug-ins can extend the functionality of the original plug-in in a controlled manner (see Section 17.1, The Extension Point Mechanism, on page 595). This mechanism provides a layer of separation so that the original plug-in does not need to know about the existence of the extending plug-ins at the time you build the original plug-in. Plug-ins declare extension points as part of their plug-in manifest, as in the views extension point declared in the org.eclipse.ui plug-in:
<extension-point id="views" name="%ExtPoint.views" schema="schema/views.exsd"/>
You can find documentation for this extension point in the Eclipse help (select Help > Help Contents, then in the Help dialog, select Platform Plug-in Developer Guide > Reference > Extension Points Reference > Workbench > org.eclipse.ui.views). It indicates that any plug-in using this extension point must provide the name of a class that implements the interface org.eclipse.ui.IViewPart (see Section 20.5, Types Specified in an Extension Point, on page 723).
Other plug-ins declare extensions to the original plug-in's functionality similar to the Favorites plug-in's view extensions. In this case, the Favorites plug-in declares a new category of views with the name Quality Eclipse and the class, com.qualityeclipse.favorites.views.FavoritesView, as a new type of view as follows:
<extension point="org.eclipse.ui.views"> <category name="Quality Eclipse" id="com.qualityeclipse.favorites"> </category> <view name="Favorites" icon="icons/sample.gif" category="com.qualityeclipse.favorites" class="com.qualityeclipse.favorites.views.FavoritesView" id="com.qualityeclipse.favorites.views.FavoritesView"> </view> </extension>
Each type of extension point may require different attributes to define the extension. Typically, ID attributes take a form similar to the plug-in identifier. The category ID provides a way for the Favorites view to uniquely identify the category that contains it. The name attribute of both the category and view is human-readable text, while the icon attribute specifies a relative path from the plug-in directory to the image file associated with the view.
This approach allows Eclipse to load information about the extensions declared in various plug-ins without loading the plug-ins themselves, thus reducing the amount of time and memory required for an operation. For example, selecting the Windows > Show View > Other... menu opens a dialog showing all the views provided by all the plug-ins known to Eclipse (see Section 2.5, Installing and Running the Product, on page 86). Because each type of view is declared in its plug-in's manifest, the Eclipse runtime can present a list of views to the user without actually loading each plug-in that contains the view.