blob: 5e15e394cec858c623efed0106cef3e8cfe53aa1 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=charset=ISO-8859-1">
<title>What the heck is a plug-in anyway?</title>
<link rel="stylesheet" href="/default_style.css">
</head>
<body link="#0000ff" vlink="#800080">
<p align="right"><img src="../../../images/ngibmcpy.gif" alt="Copyright IBM Corporation and others 2000, 2003." border="0" width="324" height="14"></p>
<table border="0" cellspacing="0" cellpadding="2" width="100%">
<tbody>
<tr>
<td align="Left" valign="Top" colspan="2" bgcolor="#0080c0"><b><font face="Arial,Helvetica"><font color="#ffffff">
Eclipse Corner Article</font></font></b></td>
</tr>
</tbody>
</table>
<div align="Left">
<h1><img src="images/Idea.jpg" height="86" width="120" align="Center">
</h1>
</div>
<h1 align="Center">What the heck is a plug-in anyway? </h1>
<blockquote>
<p><b>Summary</b><br>
<br>
The Eclipse Platform is based on the notion of plug-ins. Plug-ins are a simple
but powerful mechanism that allow developers and users to construct complex
tool sets by composing functionality (i.e., plug-ins). There are of course
a number of subtleties in how plug-ins are defined and how they interact.
This article attempts to demystify plug-ins and make it easier to create and
manage Eclipse Platform configurations.</p>
<p><b> By Debbie Wilson and Jeff McAffer, IBM OTI Labs</b><br>
<font size="-1">March 9, 2004</font></p>
</blockquote>
<hr width="100%">
<h2>Why Plug-ins?</h2>
<p>One of the main design points of the Eclipse Platform is that it is extremely
extensible. Another is that it is uniform. The Eclipse plug-in model is key
in satisfying both of these goals. A plug-in is a piece of functionality which
can be added to the Platform. Tools or applications are constructed by creating
one or more plug-ins. How tools or applications are factored into plug-ins depends
on the nature of the tool or application. </p>
<p>The Eclipse Platform itself, for example, is made up entirely of plug-ins:
some 50 or so in all. Even the runtime which manages plug-ins, is itself a plug-in!
Plug-ins interact via well defined API's. Since everything is a plug-in and
plug-ins interact via public interfaces, all plug-ins are equal in the system.
There are no plug-ins which get special treatment or privileges. For example,
the Workbench UI is a plug-in which presents the resource model defined by the
Resources plug-in. Since the Workbench accesses the Resources plug-in only via
API, all other plug-ins have exactly the same opportunities for manipulating
resources.</p>
<p>It follows from this, that capabilities are added to the Platform incrementally,
by adding plug-ins. Each new plug-in ties into the API of existing plug-ins
and provides new functionality. Still other plug-ins then build on the API of
these new plug-ins to add still more functionality to the Platform. And so on...</p>
<p>Another design point that makes Eclipse extremely extensible is its policy
of lazy plug-in activation. Only those plug-ins with code that is actually being
used are activated. Lazy activation is key to supporting a large base of installed
plug-ins, only some of which are needed in any given user session. Until a plug-in's
code is loaded, it has a negligible memory footprint and impact on start up
time.</p>
<h2>What is a Plug-in?</h2>
<p>Note: This article covers plug-ins as they are in Eclipse 2.1. While there
are some changes coming in Eclipse 3.0, the basic model described here will
continue to be accurate.</p>
<p>Fundamentally, plug-ins
are defined by an XML <em>manifest
file</em> called <code><strong>plugin.xml</strong></code>. An example plug-in
manifest is shown below. </p>
<blockquote>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;plugin
id="com.example.myplugin"
name="My Plugin"
version="2.0.0"
provider-name="Example Plug-ins Inc."&gt;<br>&lt;/plugin&gt;
</pre>
</blockquote>
<p>Each plug-in is contained in a file system directory or at a base URL on a
server, with a plug-in manifest file (as seen above) and anything else it needs.
</p>
<p>A typical plug-in consists of Java code in a JAR library, some read-only files,
and other resources such as images, web templates, message catalogs, native
code libraries, translation files, etc. Most plug-ins contribute executable
code though not all. Documentation plug-ins, for example, contribute online
help in the form of HTML pages. If a plug-in does contain code it must either
be written in Java or be callable from Java. </p>
<p>The above plug-in example is very simple. The following sections show how the
following elements of the plug-in architecture are used to round out the specification
of a plug-in.</p>
<ul>
<li><b>Libraries</b> define the location of executable code. </li>
<li><b>Prerequisites</b> define dependencies between plug-ins. </li>
<li><b>Extension points</b> allow other plug-ins to contribute information in
a well-defined manner. </li>
<li><b>Extensions</b> contribute information to the extension points of other
plug-ins. </li>
<li><b>Fragments</b> allow a plug-in to be extended without the need to modify
anything related to the existing plug-in. </li>
</ul>
<h2>What is a Library?</h2>
<p>The first thing you are likely to want to do with a plug-in is define the location
of the plug-in's executable code and/or resources. <code><strong>library</strong></code>
entries in plugin.xml (see example below) describe the shape of these contributions.
</p>
<blockquote>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;plugin
id="com.example.myplugin"
name="My Plugin"
version="2.0.0"
provider-name="Example Plug-ins Inc."&gt;
<strong>&lt;runtime&gt;
&lt;library name="mylibrary.jar" type=&quot;code&quot;&gt;
&lt;export name="*"/&gt;
&lt;/library&gt;
&lt;/runtime&gt;
</strong>
&lt;/plugin&gt;
</pre>
</blockquote>
<p><code><strong>library</strong></code> elements specify a portion of the plug-in's
local classpath. Each plug-in has two classpaths: one for code libraries and
one for resource libraries. Correspondingly, <code><strong>library</strong></code>
elements have a type attribute whose value is either <code><strong>code</strong></code>
or <code><strong>resource</strong></code> (<code><strong>code</strong></code>
is the default). Code libraries contain Java class files as well as any associated
resources. There is no need to artificially separate resources from the code
as code libraries can contain both. Libraries defined as type <code><strong>resource</strong></code>
on the other hand, can contain only resources (properties files, images).</p>
<p>The distinction allows the classloaders to ignore resource libraries while
loading classes, as they are guaranteed to contain only resources (e.g., translated
properties files). This translates into performance improvements as there are
fewer places to look for classes. Note that both the code and resource libraries
are consulted when loading resources.</p>
<p>Each <strong><code>library</code></strong> element identifies a files system
location (directory or jar file) which contains the code and/or resources. The
path specified is relative to the plug-in's file system directory and cannot
resolve to a location outside the scope of the plug-in (for example, &quot;../../foo.jar&quot;
is not allowed). </p>
<p>By default, everything in a code library is considered private (i.e., known
only within the scope of the plug-in). Portions of a library are made visible
outside its containing plug-in using the <strong><code>export</code></strong>
sub-element. Plug-ins can export some, all or none of their libraries by specifying
patterns in the name attribute of the <strong><code>export</code></strong> tag.
</p>
<p>A <strong><code>library</code></strong> entry contained in our example plug-in,
<code>com.example.myplugin</code> is shown in the snippet above. It shows a
code library called &quot;mylibrary.jar&quot; which is exported in total.</p>
<h2>What is a Plug-in Prerequisite?</h2>
<p>Plug-ins must declare their dependencies on other plug-ins using a <strong><code>requires</code></strong>
element in their plug-in manifest file. Typically dependencies arise from inter-plug-in
class references. If a plug-in A requires plug-in B, plug-in B is said to be
a prerequisite of plug-in A. Continuing our example, the manifest below shows
the plugin.xml expressing a dependency on <code>com.example.anotherplugin</code>.</p>
<blockquote>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;plugin
id="com.example.myplugin"
name="My Plug-in"
version="2.0.0"
provider-name="Example Plug-ins Inc."&gt;<br>
<strong>&lt;requires&gt;
&lt;import plugin="com.example.anotherplugin"
version=&quot;2.1.3&quot;
match=&quot;equivalent&quot;/&gt;
&lt;/requires&gt;
</strong>
&lt;runtime&gt;
&lt;library name="mylibrary.jar" type=&quot;code&quot;&gt;
&lt;export name="*"/&gt;
&lt;/library&gt;
&lt;/runtime&gt;
&lt;/plugin&gt;</pre>
</blockquote>
<p>In this example, <code>com.example.myplugin</code> (My Plugin) can access any
of the classes in <code>com.example.anotherplugin</code> (Another Plugin) which
are explicitly exported in its library statements. </p>
<p>Notice that the <strong><code>import</code></strong> statement is qualified
by a version number and matching rule. Versions refine the dependencies between
plugins and help the runtime choose between different installations of the same
plug-in. In general the runtime picks the most recent version which matches
given the matching rule. Eclipse version numbers are a four part string of the
form <strong><code>major.minor.service.tag</code></strong>. Versions are compared
using one of four matching rules.</p>
<dl>
<dl>
<dt><b>perfect</b></dt>
<dd>All four components of the version must match.</dd>
<dt><b>equivalent</b></dt>
<dd>major and minor must match and others must sort after</dd>
<dt><b>compatible</b> (default)</dt>
<dd>major must match and others must sort after</dd>
<dt><b>greaterOrEqual</b></dt>
<dd>Any version which is a perfect match or sorts lexographically after</dd>
</dl>
</dl>
<p>Plug-in dependencies are transitive. That is, if Another Plugin requires some
plug-in, say Final Plugin, then My Plugin will not be enabled unless both
Another
Plugin and Final Plugin are present. This is easy to see since Another Plugin
would be disabled if its prerequisites are not present (e.g., Final Plugin
is missing). Similarly, My Plugin would also be disabled if its prerequisite,
Another Plugin, is not present. Under no circumstances are circular dependencies
permitted.
Any plug-in involved in a cycle will be disabled at runtime.</p>
<p>Class visibility through the dependency chain is not transitive unless explicitly
stated. That is, My Plugin cannot see the classes in Final Plugin. This effectively
encapsulates
the implementation of Another Plugin. Where transitivity is required, the <code><strong>export</strong></code>
attribute of the <strong><code>import</code></strong> tag is used to re-export
the classes exported by imported plug-ins. (try saying that a few times quickly!).
For example, Another
Plugin can explicitly re-export its import of Final Plugin:</p>
<blockquote>
<pre> &lt;import plugin="com.example.finalplugin" export=&quot;true&quot;/&gt;
</pre>
</blockquote>
<p>Finally, plug-in prerequisite statements can be made optional by adding the
<strong><code>optional=&quot;true&quot;</code></strong> attribute to the <strong><code>import</code></strong>
tag (see below for an example). Marking an import as <code>optional</code> simply
states that if the specified plug-in is not found at runtime, the dependent
plug-in should be left enabled. This is used when a plug-in can be used in many
scenarios or it is reasonable to operate with reduced function. It allows the
creation of minimal installs that cover functional subsets. Authors of plug-ins
using optional prerequisites should take special care to avoid or handle the
ClassNotFoundExceptions which will occur when the optional plug-in is not present.</p>
<pre> &lt;import plugin="com.example.finalplugin" optional=&quot;true&quot;/&gt;
</pre>
<h2>What are Extensions and Extension Points?</h2>
<p><em>Extension points</em> are a mechanism used by plug-ins to indicate they
are willing to accept contributions from other plug-ins. An <em>extension</em>
is a plug-in's way of contributing information to these extension points. For
example, a UI plug-in might expose an extension point for menu actions. A plug-in
wishing to contribute an action to the UI would define an extension for the
UI's menu action extension point.</p>
<p>Extension points have a globally unique id constructed from the defining plug-in
id and a simple id specified in the extension point itself. The example below
is from the <code>org.eclipse.ui</code> plug-in. The full identifier of the
extension point is therefore <code>org.eclipse.ui.actionSets</code>. All extension
points have this relatively simple form.</p>
<blockquote>
<pre> &lt;extension-point name="Action Sets" id="actionSets"/&gt;</pre>
</blockquote>
<p>The exact form of extensions is defined by the plug-in which defines the extension
point being extended. In the above example, the UI plug-in specifies what
information
is needed to define the menu action as well as the form of that information.
For example, the UI needs an icon and label to draw and a class to instantiate
and run when the menu entry
is selected. Extensions which identify classes to run are called <em>executable
extensions</em>. The type characteristics (e.g., superclass,
interfaces) of the class are also defined by the extension point itself. The
snippet below shows
an example UI extension.</p>
<blockquote>
<pre> &lt;extension
point=&quot;org.eclipse.ui.actionSets&quot;&gt;
&lt;actionSet
label=&quot;Example&quot;
visible=&quot;false&quot;
id=&quot;com.example.actions&quot;&gt;
&lt;action
id=&quot;com.example.action1&quot;
class=&quot;com.example.CoolAction&quot;
icon=&quot;icons/action1.gif&quot;
label=&quot;Cool Action&quot;
&lt;/action&gt;
&lt;/actionSet&gt;
&lt;/extension&gt;
</pre>
</blockquote>
<p>A plug-in can define any number of extension points and extensions. Further,
any given extension point may be extended by any number of extensions. Extensions
can extend extension points defined in their own plug-in or in
others. It follows, therefore, that extension points can accept extensions
from their own plug-in or other plug-ins. </p>
<p>Extending an extension point does not imply a dependency relationship. Rather,
it is a statement that if there is an extension point with the given id (point
attribute in the <strong><code>extension</code></strong> tag), add the given
extension. Otherwise, do nothing. Doc plug-ins for example have no need to
get classes from the Help plug-ins -- they simply add extensions to Help system
extension points.</p>
<h4></h4>
<h2>What is a Plug-in Fragment?</h2>
<p>Fragments allow optional functionality/content to be <strong>added</strong>
to existing plug-ins. For example, the base Eclipse contains only English messages.
Fragments are used to add message catalogs containing other languages (e.g.,
French, Italian) without modifying the existing plug-ins. Note that fragments
can only add function/content to plug-ins. They cannot override that which the
plug-in already contains. Fragments are added to the base plug-in in no particular
order and fragments for missing plug-ins are ignored.</p>
<p>It is not surprising to find that fragments are very similar to plug-ins; they
are defined with a single manifest file, called <strong><code>fragment.xml</code></strong>,
in a file system directory which contains everything the fragment needs. Each
fragment must be associated with a particular plug-in. And any given plug-in
can have any number of fragments associated with it. </p>
<p>Further, fragments can contribute libraries, prerequisites, extension points
or extensions using standard syntax. These contributions are seamlessly merged
into the fragment's base plug-in. That is, extensions and extension points from
a fragment appear to come from/be part of (respectively) the base plug-in, libraries
are put on the base plug-in's classpath and prerequisites contribute to the
plug-in's prerequisite chain.</p>
<p>Below, is an example of a simple NL fragment for <code>com.example.myplugin</code>.</p>
<blockquote>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;fragment
id="com.example.myplugin.addon1"
name="Example Add-on 1 Fragment"
version="2.1.2"
provider-name="Eclipse.org"
plugin-id="com.example.myplugin"
plugin-version="2.1.0"
match="compatible"&gt;
&lt;runtime&gt;<br> &lt;library name="nl1.jar"/&gt;<br> &lt;/runtime&gt;<br>&lt;/fragment&gt;
</pre>
</blockquote>
<p>This fragment contributes additional jars which contain translations of the
messages used by the hosting plug-in itself. In this case the jar contains
files named
according to the standard Java locale-based lookup strategy (e.g., message_en_US.properties,
message_jp_JP.properties). Since the jars are added to the plug-in's classpath,
the plug-in classloader will find these resources automatically. </p>
<h2>The Plug-in Model at Runtime</h2>
<p>All of the information we have discussed so far has dealt with physical plug-in
information stored in the Eclipse environment. We will now talk about the <em>runtime</em>
version of all this plug-in information.</p>
<h4>The Plug-in Registry</h4>
<p>When the Eclipse Platform starts, it first discovers all available plug-ins
and fragments. The install/update component of Eclipse and a user-defineable
plug-in path are used to determine directories where plug-ins and fragments
can be found. Each plug-in/fragment directory may contain exactly one manifest
file named <code>plugin.xml </code>or <code>fragment.xml</code>. </p>
<p> Once the discovery is completed, the platform parses the discovered manifest
files and builds a <em>plug-in registry</em>. Manifests which cannot be loaded
are skipped and the failure is noted in the platform's log (typically under
in <code>&lt;workspace&gt;/.metadata/.log</code>). The registry is
then
<em>resolved.</em> That is, it is examined to ensure the structure is useful
and sane, and its structures are cross linked. Resolution includes the following
steps:</p>
<ul>
<li>each element in the list (plug-in, fragment, extension point, etc.) must
have all of the required fields. Required fields are those fields with the
tag &quot;#REQUIRED&quot; in the appendix &quot;DTD's for plugin.xml and fragment.xml".</li>
<li>each fragment must be associated with a plug-in</li>
<li>each plug-in must have access to any prerequisite plug-ins (after version
compatibility matching) unless a prerequisite has been denoted as <code>optional</code></li>
<li>each extension must be matched with an extension point</li>
</ul>
<p>An error message is logged if any problems are encountered and the offending
element is removed from the plug-in registry. This allows Eclipse to continue
running even if there are minor problems. The resulting plug-in registry is
available via the <code>org.eclipse.core.runtime</code> plug-in's API. The whole
plug-in registry is available through <code>IPluginRegistry</code> and individual
plug-ins can be examined with <code>IPluginDescriptor</code>.</p>
<p>Changes to the set of installed plug-ins are only detected when Eclise is
restarted.</p>
<h4>Plug-in Activation</h4>
<p>When Eclipse starts up, only those plug-ins needed to build the plug-in registry
and get things started are activated. All other plug-ins (the vast majority
of plug-ins) remain dormant. When something happens causing the code within
a plug-in to be loaded, that particular plug-in is activated. That is, classloading
is the only trigger for plug-in activation. Plug-ins are only activated if the
class loaded comes from the plug-in's local classpath (i.e., one of its libraries).
Loading classes from a prerequisite does not count. This is the basis for Eclipse's
lazy plug-in activation policy.</p>
<p>Many things can happen without activating a plug-in. In particular, </p>
<ul>
<li>resources can be loaded (either from a resource or code library) </li>
<li>plug-in classloaders can ask other classloaders to load classes. </li>
<li>extensions and extension points can be examined without having to activate
the plug-in that contains the extension. </li>
</ul>
<p>Once a plug-in is activated it remains active until Eclipse shuts down. When
Eclipse does shut down, all plug-ins are shut down in a dependents-first order.
For example, if plug-in A requires plug-in B, then plug-in A will be shut down
before plug-in B.</p>
<h4>Plug-in Classloading</h4>
<p>Libraries define the local classpath of a plug-in. Each library entry translates
into an entry on the classpath of the plug-in's classloader. Earlier we discussed
the concept of a <strong><code>code</code></strong> vs. a <strong><code>resource</code></strong>
library. Resource libraries are loaded by a resource loader and do not figure
into the strict classloading model.</p>
<p>Classloading in Eclipse follows the P-S-P model. That is, Parent-Self-Prerequisites.
</p>
<dl>
<dl>
<dt><b>Parent</b> </dt>
<dd>Each plug-in classloader has the Eclipse boot plug-in's classloader as
its parent. The boot plug-in loader's parent is the system classloader.
Note that the standard Java AppClassloader (the one used to load the class
containing main()) is not added to the classloading chain. As a result,
the jars added to the JVM's classpath are ignored. Jars added to the JVM's
bootclasspath are part of the system classloader and are considered during
plug-in classloading.</dd>
<dt><b>Self</b></dt>
<dd>Self considers the libraries defined as part of this plug-in. All code
libraries contributed by fragments to this plug-in are also considered.
Libraries contributed by fragments appear after those contributed in the
plug-in manifest (in indeterminant order). Libraries from the same manifest
appear on the class path in the same order in which they were declared.</dd>
<dt><b>Prerequisites</b></dt>
<dd>Finally the exported libraries of the plug-in's prerequisites are considered.
Prerequisites are queried in the order in which they were declared with
the exception of the runtime plugin (<code>org.eclipse.core.runtime</code>).
All plug-ins automatically have the Eclipse runtime plug-in (<code>org.eclipse.core.runtime</code>)
added to their prerequisite list as the first prerequisite. All imports
of the runtime plug-in are ignored.
<p> Note that prerequisite consultation is transitive. When locating a class,
a prerequisite plug-in will follow the same (though optimized) P-S-P model.
Since all plug-in classloaders have the same parent, prerequisite loaders
need not look there. Similarly, plug-ins which occur repeatedly in the
transitive closure of the prerequisite graph are consulted at most once.
Finally, prerequisite re-exporting rules are followed as described above.</p>
</dd>
</dl>
</dl>
<h4>Plug-in Data</h4>
<p>The Eclipse Platform makes certain assumptions about the physical structure
of a plug-in. Each plug-in or fragment is typically stored in a separate directory
under a directory named <strong><code>plugins</code></strong> under your Eclipse
install directory. The name of this directory is usually the same as the plug-in's
id (though it may have the version number appended to it). In addition to the
<code>plugin.xml</code> or <strong><code>fragment.xml</code></strong> file,
there may be any number of folders under the plug-in's root folder.</p>
<p>Since Eclipse can be run on a wide range of machine configurations (i.e., operating
system, window system) it needs a way of managing different forms of the same
data (e.g., shared libraries). Eclipse provides four variables for use in library
statements which resolve to parts of the current machine configuration.</p>
<dl>
<dl>
<dt><b>os</b></dt>
<dd>The operating system on which Eclipse is currently running (e.g., win32,
linux, solaris)</dd>
<dt><b>ws</b></dt>
<dd>The window system being used for the Eclipse UI (e.g., win32, motif, gtk)</dd>
<dt><b>arch</b></dt>
<dd>The type of processor in the machine (e.g., x86, ppc, sparc)</dd>
<dt><b>nl</b></dt>
<dd>The current locale (e.g., en_CA, jp_JP)</dd>
</dl>
</dl>
<p>So, for example, if your plug-in uses windowing system-specific features, it
may be necessary to provide a different library for each configuration. Using<em>
</em><strong><code>$ws$/&lt;library name&gt;</code></strong> in your plug-in
manifest file directs Eclipse to look for the library in a window system directory
with the same name as the current window system. The <code>org.eclipse.swt</code>
plug-in uses this mechanism as follows:</p>
<blockquote>
<pre> &lt;runtime&gt;
&lt;library name=&quot;$ws$/swt.jar&quot;&gt;
&lt;export name=&quot;*&quot;/&gt;
&lt;/library&gt;
&lt;/runtime&gt;
</pre>
</blockquote>
<p>The SWT plug-in has a series of directories of the form <code>ws/&lt;windowing
system&gt;/</code>(e.g., <code>ws/win32</code>, <code>ws/gtk</code>, <code>ws/motif</code>).
Each of these directories contains a different version of <code>swt.jar</code>.
If you are working in an Eclipse environment in a win32 windowing system,
the
library name <code>$ws$/swt.jar</code> will match <code>ws/win32/swt.jar</code>.
Note that in practice any given Eclipse install will have only one <code>swt.jar</code>
(the one that matches the install). The jars are actually contributed by window
system-specific fragments. Similar structures are seen in the Resources, and
Update plug-ins. This mechanism allows the common elements to be put
in the plug-in and have only the window system, operating system, ... specific
parts in a fragment.</p>
<h2>Summary</h2>
<p>This article has set the stage for plug-ins: defining what they are, why they
are important and concepts related to them. More detail on the exact form of
<a href="http://help.eclipse.org/help21/topic/org.eclipse.platform.doc.isv/reference/misc/plugin_manifest.html">plug-in/fragment
markup</a> can be found in the Eclipse help system. Eclipse plug-in developers
are encouraged to look at existing plug-ins for further examples.</p>
<div class=Section1>
<p><a href="hglegal.htm"><img src="../../../images/ngibmcpy.gif" alt="Copyright IBM Corporation and others 2000, 2003." border="0" width="250" height="12"></a></p>
</div>
<p>&nbsp;</p>
</body>
</html>