| <html> |
| |
| <head> |
| <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"> |
| <title>PDE Does Plug-ins</title> |
| <link rel="stylesheet" href="../default_style.css"> |
| </head> |
| |
| <body LINK="#0000ff" VLINK="#800080"> |
| <div align="right"><font face="Times New Roman, Times, serif" size="2">Copyright |
| © 2003 International Business Machines Corporation. All rights reserved</font> |
| <table border=0 cellspacing=0 cellpadding=2 width="100%"> |
| <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> |
| </table> |
| </div> |
| <div align="left"> |
| <h1><img src="images/Idea.jpg" height=86 width=120 align=CENTER></h1> |
| </div> |
| |
| <h1 ALIGN="CENTER">PDE Does Plug-ins</h1> |
| |
| <blockquote> |
| <b>Summary</b> |
| |
| <br> |
| <font face="Arial">The Plug-in Development Environment (PDE) provides a set |
| of tools that assist the developer in every stage of plug-in development from |
| genesis to deployment. This article chronicles the creation, development, testing, |
| building, and deployment of a simple "Hello World" plug-in using a |
| subset of these tools.</font> |
| <p><b> By Wassim Melhem and Dejan Glozic, IBM Canada Ltd.</b><br> |
| <font size="-1">September 8, 2003</font></p> |
| </blockquote> |
| |
| <hr width="100%"> |
| <h2>Why PDE?</h2> |
| <p>A plug-in is the fundamental building block of the Eclipse platform. Eclipse |
| is the sum of its constituent plug-ins, where each plug-in contributes functionality |
| to the platform and is activated when the functionality it provides is needed. |
| Structurally, each plug-in resides in a subdirectory called eclipse/plugins |
| in the Eclipse installation, and contains a manifest (plugin.xml) file that |
| describes its content to the Eclipse runtime. A plug-in may also include a Java™ |
| code library and other resource files it needs, such as icons, properties files, |
| etc.</p> |
| <p align="center"> |
| <img border="0" src="images/directory.gif" width="575" height="369"></p> |
| <p align="left"> Writing an Eclipse plug-in is straight forward, but not exactly |
| trivial. The task entails creating a manifest file, writing Java source code, |
| compiling the code into a library, testing it and packaging the plug-in into |
| a form that is suitable for deployment. This task can be quite intricate, depending |
| on the complexity of the plug-in and the developer's Eclipse expertise. Enter |
| PDE.</p> |
| <p>The Plug-in Development Environment (PDE) is a set of tools designed to assist |
| the Eclipse developer in developing, testing, debugging, building, and deploying |
| Eclipse plug-ins while working inside the Eclipse workbench. Keeping with |
| Eclipse's philosophy of seamless integration of components, PDE is not a separately |
| launched tool. PDE integrates itself in the workbench by providing platform |
| contributions, such as editors, wizards, views and a launcher, which users can |
| easily access from any perspective without interrupting their work flow. </p> |
| <p>This article showcases a subset of PDE tools that are available in Eclipse |
| 2.1 by chronicling the journey of one plug-in from genesis to deployment. The |
| plug-in will contribute to the Eclipse workbench a menu containing a single |
| item which, when selected, will pop up a dialog containing the phrase "Hello, |
| world!"</p> |
| <h2>Configuring PDE</h2> |
| <p>In order for PDE to provide a development environment that is identical to |
| the runtime environment in which the plug-in will be later deployed, one needs |
| to specify the <b>Target</b> <b>Platform</b>. Target<b> </b>platform refers to the set of plug-ins with which the plug-in |
| being developed will be deployed. At runtime, most plug-ins require other plug-ins to be on their class path in order to |
| run properly. At development time, a plug-in, which is |
| represented as a project in the workspace, similarly requires that all the libraries for its required |
| plug-ins be on its build path in order for its code to compile without errors. </p> |
| <p>Libraries for required plug-ins can be easily made available to the workspace |
| plug-in by simply specifying the installation location of the target platform. |
| PDE scans and lists all the plug-ins found at that location, but only the |
| plug-ins explicitly selected by the user will constitute the target platform and |
| can be used by plug-ins in the workspace; the rest are ignored.</p> |
| <p align="center"> |
| <img border="0" src="images/target_platform.gif" width="586" height="478" ></p> |
| <p align="left"> |
| <img src="images/tip.gif" width="62" height="13"> Plug-ins from the target |
| platform are |
| not part of the workspace, and their contents therefore cannot be browsed in Eclipse's Navigator |
| and Package |
| Explorer views. PDE thus provides a <b>Plug-ins </b> |
| view where the directory structure of these external plug-ins can be browsed and |
| external files can be opened (in read-only mode, of course).</p> |
| <h2>Creating a New Plug-in Project</h2> |
| <p>In the workspace, a plug-in is encapsulated in a single project. At its |
| top level, the project must contain a manifest file, describing the plug-in |
| content, and a build.properties file, containing information that is used |
| to guide the build process. To create a plug-in project, |
| PDE provides a <b>New Plug-in Project </b>wizard, which can be found under the |
| <b>Plug-in Development</b> category in the <b>New Project</b> creation wizard. |
| This wizard not only creates the plug-in project, it also gives the developer a quick |
| start by generating the two essential plug-in files and, optionally, some Java |
| code.</p> |
| <p align="center"> |
| <img border="0" src="images/plugin_project_1.gif" width="500" height="500" ></p> |
| <p align="left">Most plug-ins, including the "Hello World" plug-in, are meant |
| to contain executable Java code and must therefore be housed in a Java project. |
| In such cases, one can specify the source folder that will contain |
| the plug-in code during development, and the library where the compiled code |
| will be packaged. PDE maps the library name to the source |
| folder and saves that information in the plug-in project's build.properties |
| file, so that it can be used later during the build process. One can |
| also specify the output folder, where the Java compiler will place the compiled |
| *.class files of the project. When launching a runtime workbench instance to run |
| or debug the plug-in, PDE will put this output folder on the plug-in |
| runtime classpath, thus allowing the runtime class loader to locate and load the |
| freshly generated class files.</p> |
| <p align="left"> <img src="images/tip.gif" width="62" height="13"> Not all plug-ins contain Java code. |
| Plug-ins such as documentation plug-ins contain only non-Java resources, and |
| can therefore be sufficiently contained in simple projects. In fact, it is |
| desirable to create simple projects for such plug-ins, so that they would not |
| unnecessarily be subjected to Java builders.</p> |
| <p align="center"> |
| <img border="0" src="images/plugin_project_2.gif" width="500" height="500" ></p> |
| <p align="left"> |
| The ability to create a plug-in with a ready-to-run extension is appealing, |
| particularly to novice Eclipse developers. Therefore, templates for |
| Eclipse's more popular extensions are available during the plug-in project |
| creation process. Writing an Eclipse extension always |
| involves adding markup to the manifest file, and if required, accompanying Java |
| code that gets executed upon the invocation of the extension. The |
| code generation wizards generate all the markup and code needed to produce a |
| customizable and fully-functioning extension. </p> |
| <p>Selecting the "Hello, World" template wizard from the list above |
| results in the creation of a "Hello World" plug-in that is ready to |
| run. That is great, but would make this paper extremely short. In |
| this example, we will create a blank plug-in project, so that we can demonstrate |
| how to write a plug-in from scratch.</p> |
| <p>As a result of our selections, the wizard generates the plug-in project, the |
| manifest file, the build.properties file and initializes the content of these |
| two files based on the data entered in the wizard. Let us now proceed with the |
| implementation of the plug-in, starting with the editing of the manifest file.</p> |
| <p align="center"> |
| <img border="0" src="images/project.gif" width="295" height="180"></p> |
| <h2>Editing the Plug-in Manifest File</h2> |
| <p>The manifest file describes the content of the plug-in to the Eclipse runtime. |
| In addition to basic plug-in information such as plug-in identifier, version, |
| etc., this file contains four main sections:</p> |
| <ol> |
| <li>A Dependencies section listing all the plug-ins required by the plug-in. |
| A plug-in must list as dependencies all the plug-ins needed for its code to |
| compile and all the plug-ins contributing extension points that it is using.</li> |
| <li>An Extensions section declaring all the functionalities that this plug-in |
| contributes to the platform by extending other plug-ins' extension points.</li> |
| <li>A Runtime section declaring the libraries where the plug-in code is |
| packaged. At runtime, the class loader searches these libraries when |
| loading the plug-in's classes.</li> |
| <li>An Extension Points section declaring new function points defined by this |
| plug-in which other plug-ins can extend (i.e., provide an implementation for). |
| For example, the Platform UI plug-in provides an editor extension point, which |
| other plug-ins can extend to implement and contribute a new editor to the |
| platform.</li> |
| </ol> |
| <p>Let us now edit the different sections of the plug-in |
| manifest file using the PDE multi-page UI editor, the default editor for manifest |
| files in Eclipse.</p> |
| <h3 align="left">Dependencies</h3> |
| <p>Contributing a menu to the workbench requires extending the <i>actionSets</i> |
| extension point that is defined by the <i>org.eclipse.ui</i> plug-in. Therefore, |
| the "Hello World" plug-in must declare this plug-in as a dependency. |
| By doing so, in addition to providing access to the extension point, the libraries |
| of <i> org.eclipse.ui</i> will be on the plug-in's runtime classpath.</p> |
| <p align="center"> |
| <img border="0" src="images/dependencies_page.gif" width="532" height="380"></p> |
| <p>The list of required plug-ins solely determines the libraries that will be |
| on the plug-in's runtime classpath. PDE takes charge of the vital task of computing |
| the plug-in project's classpath during development time, so that it accurately |
| reflects the runtime classpath. Upon saving the manifest file, PDE automatically |
| updates the project's classpath to reflect changes made to the dependency list, |
| if any. This feature is an invaluable utility because the alternative, i.e., |
| computing the classpath manually, is tedious and error-prone.</p> |
| <p>The list of required plug-ins should not contain unused entries. An incomplete list of dependencies is easy to spot at development |
| time because the plug-in's code will not compile in the workspace. |
| Extraneous entries, on the other hand, are harder to spot because they are |
| benign at development time, but can slow down class loading at runtime as extra |
| libraries on the plug-in's runtime classpath will unnecessarily be searched. PDE, therefore, provides a <b> |
| Find Unused Dependencies</b> utility as an item in the required plug-ins list's |
| context menu, which scans the dependency list for extraneous entries and offers |
| to remove them.</p> |
| <p> <img src="images/tip.gif" width="61" height="13"> The plug-ins <i> |
| org.eclipse.core.boot</i> and <i>org.eclipse.core.runtime</i> are implicitly |
| available for all plug-ins at runtime, and therefore need not be explicitly |
| listed as required plug-ins.</p> |
| <h3>Extensions</h3> |
| <p style="font-family: arial, helvetica, geneva; font-size: 10pt">A plug-in can |
| contribute new functionality to the platform by adding an extension to extension |
| points declared by other plug-ins. The extension declaration must follow the schema |
| defined by the extension point it contributes to. The schema can be as simple or as complex as the author of the |
| extension point defines it to be. </p> |
| <p style="font-family: arial, helvetica, geneva; font-size: 10pt">Adding a new |
| extension on the Extensions page of the manifest editor involves creating nested |
| elements using the context menu, and setting attribute values for these elements |
| in the Properties view. When adding a new extension, PDE uses the grammar of |
| the extension point to fill the context menu with valid element names and populate |
| the property view with the legal attributes for the selected element.</p> |
| <p style="font-family: arial, helvetica, geneva; font-size: 10pt">Menus and menu |
| items, which, along with toolbar actions, are collectively referred to as action |
| sets, can be added to the workbench by contributing to the <i>org.eclipse.ui.actionSets</i> |
| extension point. The top-level element of this extension is an 'actionSet' |
| element specifying its unique internal identifier, as well as its label and |
| visibility in the workbench. When the attribute 'visible' is set to 'true', |
| the action set will be visible in all perspectives; otherwise, the action set |
| will have to be manually added to a perspective by choosing <b>Window > Customize |
| Perspective... > Other</b>.</p> |
| <p align="center"> |
| <img border="0" src="images/extensions.gif" width="602" height="233"></p> |
| <p align="left"> |
| The 'menu' element specifies the label of the menu as it will appear in the |
| workbench and the internal identifier of the menu.</p> |
| <p align="center"> |
| <img border="0" src="images/extensions2.gif" width="523" height="230"></p> |
| <p align="left"> |
| The 'separator' element creates a menu separator that also serves as a group to |
| which the menu item will be added.</p> |
| <p align="center"> |
| <img border="0" src="images/extensions3.gif" width="502" height="232"></p> |
| <p align="left"> The 'action' element specifies the actual menu item. Using |
| the menu's identifier and the separator's name, the 'menubarPath' attribute |
| indicates the slot where the item is to be placed. When the menu action |
| is selected, the class that will be executed to display the "Hello, world!" |
| message is the one specified by the 'class' attribute. The schema indicates |
| that this class must implement the interface <i>org.eclipse.ui.IWorkbenchWindowActionDelegate</i>; |
| PDE therefore customizes the value field for the 'class' property to allow one |
| to specify and generates on the spot a Java class that implements the specified |
| interface.</p> |
| <p align="center"> |
| <img border="0" src="images/extensions4.gif" width="682" height="381"></p> |
| <p align="left"> PDE generates the class, complete with the stubs for all the |
| required methods. The init(..) and run(..) method need to be manually |
| fleshed out as below:</p> |
| <p> |
| <img border="0" src="images/sample_action_code.gif" width="588" height="502"></p> |
| <h3>Runtime</h3> |
| <p>During the plug-in project creation process, we had specified that the code is to be packaged in a library named 'helloworld.jar'. |
| The library's type, visibility, and content can be set |
| on the <b>Runtime</b> page of the manifest editor.</p> |
| <p align="center"> |
| <img border="0" src="images/runtime_page.gif" width="495" height="555" ></p> |
| <p>A library's <b>type</b> plays an important role at runtime. If a library is |
| declared to contain both code and resources, accessing a resource or a class |
| file from such a library results in the activation of the plug-in. On the other |
| hand, accessing a resource from a library that is declared to contain only resources, |
| e.g., libraries that only contain NL-*.properties files, does not activate the |
| plug-in. </p> |
| <p>In order to speed up class loading, one should always declare the package |
| prefixes that are found in each library. A library will not be searched |
| during class loading unless its list of package prefixes contains a prefix for |
| the fully qualified name of the class being searched for. Libraries that |
| do not declare a list of package prefixes will be searched during the loading of |
| every class.</p> |
| <p>During development, the library JAR has not been created yet. The <b>Library Content</b> section lists the source folders |
| that will be compiled into the selected library during the build process. |
| Whenever the user modifies this list, PDE automatically updates the appropriate entries in the plug-in |
| project's build.properties file.</p> |
| <h3>Extension Points</h3> |
| <p>Defining a new extension point requires the writing of a schema, which all |
| clients of the extension point must then follow in order to be processed |
| correctly at runtime. PDE provides an editor for the composition of such a |
| schema. However, since the "Hello World" plug-in does not contribute new |
| extension points, we will leave the discussion of extension points and schemas |
| for a future article.</p> |
| <h2>Testing the Plug-in</h2> |
| <p>PDE contributes to the platform a launcher that allows one to test and debug |
| plug-ins. One can create and run a runtime workbench launch configuration |
| to spawn a second (runtime) workbench instance, whose constituent plug-ins are |
| the workspace plug-ins and all selected external plug-ins in the target platform. The |
| runtime workbench instance thus previews the behavior of the plug-ins in the |
| environment in which they will later be deployed.</p> |
| <p>The runtime workbench instance is launched in development mode (i.e., with |
| the <i>-dev</i> option), so the output folder of the plug-in project is put |
| on the runtime classpath of the corresponding plug-in. This allows the runtime |
| class loader to always locate and load the plug-in's freshest class files. All |
| other execution options and settings with which to launch the runtime workbench |
| are set in the launch configuration itself. These settings include the JRE, |
| VM arguments, and all the program execution options supported by the Eclipse |
| platform. The workspace location for the runtime workbench is also specified |
| in the configuration, and must be different from the workspace location of the |
| host platform as one definitely needs to test their plug-in in a sandbox. One |
| may create multiple configurations to test their plug-ins under different conditions.</p> |
| <p align="center"> |
| <img border="0" src="images/launcher_1.gif" width="671" height="525"></p> |
| <p> <img src="images/tip.gif" width="61" height="13"> PDE uses the values specified |
| on the <b>Plug-in Development > Target Environment</b> preference page to |
| set the default values for the -<i>os</i>, -<i>ws</i>, -<i>arch</i> and -<i>nl</i> |
| arguments in the configuration. Changes made to these values in the configuration |
| are local to that configuration. Changes made to values on the preference page |
| affect the defaults for all configurations that are created thereafter.</p> |
| <p align="left"> When the launch configuration in our example is run, the runtime |
| workbench will appear within seconds. The "Hello World Menu" menu |
| will appear at the top, containing one item "Hello World Action". |
| When this item is selected, a dialog pops us to greet the world.</p> |
| <p align="center"> |
| <img border="0" src="images/dialog.gif" width="497" height="235"></p> |
| <h2>Exporting the Plug-in into a Deployable Zip</h2> |
| <p>The last stage in the life cycle of a workspace plug-in is its packaging in |
| a format that will make it easily deployable in any Eclipse-based product.</p> |
| <p>The process of packaging a plug-in project is driven by the build.properties |
| configuration file. This file is structured as a set of key-value pairs, where |
| the keys are defined by Eclipse's build process, and provides information about |
| the mapping of source folder to jars, what files to include in the packaged |
| plug-in, what files to exclude, etc.</p> |
| <p>Two of these keys are used in the building |
| of the "Hello World" plug-in:</p> |
| <ul> |
| <li><b><font face="Arial">source.<library></font></b> - The value is a |
| comma-separated list of the source folders to be compiled into the library |
| specified. This key is maintained up-to-date by PDE using the data entered |
| on the Runtime page of the manifest editor.</li> |
| <li><b><font face="Arial">bin.includes</font></b> - The value is a comma-separated |
| list of the files and folders to include in the binary build. While an initial |
| value for this key is set by PDE during the plug-in project creation process, |
| it is up to the developer to maintain this key and explicitly specify all |
| the files and folders to be included in the packaged plug-in. For this sample |
| plug-in, plugin.xml and helloworld.jar are the only two files to be included |
| in the build.</li> |
| </ul> |
| <p>To package and export the plug-in, the <b>Deployable Plug-ins and Fragments |
| </b>export wizard is used.</p> |
| <p align="center"> |
| <img border="0" src="images/export_wizard.gif" width="563" height="550"></p> |
| <p align="left">The zip file generated then simply needs to be unzipped into the installation |
| directory of any Eclipse-based product and the plug-in becomes part of that |
| product.</p> |
| <p align="center"> |
| <img border="0" src="images/deploy.gif" width="570" height="295"></p> |
| <h2 align="left">Conclusion</h2> |
| <p align="left">Using a simple "Hello World" plug-in as an example, |
| this article demonstrates how PDE provides all the tools necessary to develop |
| an Eclipse plug-in more easily and more quickly. The plug-in project creation |
| wizard gives a quick start by generating the project along with the plugin.xml |
| and build.properties files. The code generation wizards generate code |
| and markup for Eclipse's more popular extension points, so that a novice Eclipse |
| developer can get their first plug-in up and running in a few minutes. |
| The manifest editor generates a syntactically and semantically valid manifest |
| file. The runtime workbench launcher allows the testing and debugging |
| of the plug-in in an environment that is identical to the runtime environment |
| in which it will be deployed. Finally, the plug-in export wizard turns |
| the tedious build and packaging process into a simple one-step operation.</p> |
| <p align="left">While plug-ins seem to take center stage in the Eclipse architecture, |
| other components such as fragments, features and update sites play an important |
| role in the development of Eclipse products. In future articles we will discuss |
| the PDE tools available for the development of these components, as well as |
| take a detailed look at how to define new extension points.</p> |
| |
| <p><small>IBM is a registered trademark of International Business Machines Corporation |
| in the United States, other countries, or both.</small></p> |
| <p><small>Java and all Java-based trademarks and logos are trademarks or registered |
| trademarks of Sun Microsystems, Inc. in the United States, other countries, |
| or both.</small></p> |
| |
| </body> |
| </html> |