Graphical Modeling Framework/Development Guidelines
The bullets below should cover all the tasks one would need to accomplish to become a "plugged-in" member of the GMF development community.
- GMF has two mailing lists, currently. The main developer mailing list [firstname.lastname@example.org email@example.com] and the release engineering mailing list [firstname.lastname@example.org email@example.com]. You are welcome to sign up for both, but it is generally sufficient to just be signed up for the developer mailing list. Now, remember that general questions should be posted to the newsgroup and not to the development mailing list! Development topics, architectural discussions, contribution and Committer voting, etc. all take place on the developer mailing list.
- To register for the mailing list, you must provide a valid email address and other information here. Note that in order to access the mailing list archive, you need to have a newsgroup user name and password. Information on the newsgroup is below.
- As mentioned above, the newsgroup is where general questions are asked and you are encouraged to ask and answer questions as you wish. Look here for information on how to get a password, in addition to a complete list of Eclipse newsgroups.
- You will most definitely need a Bugzilla account. Look here for information on setting up an account, using Bugzilla, etc. If you're interested in contributing right away, perhaps you can find something here to work on.
You will generally work with three (or more) workspaces. Each is discussed here, along with some overall workspace configuration and tips.
- In general, you can install whatever you want in your development instance, while most seem to prefer the bare essentials. As long as you have a target instance that is configured properly for GMF development, it doesn't really matter much. You will likely just need to adhere to equal or greater version numbers of both the Eclipse SDK and EMF.
- You may elect to configure your development instance to align with the requirements for GMF development and not bother with two... it's up to you. Of course, as we develop against moving targets (Platform, EMF, and GEF milestone releases), using this feature of the PDE is quite useful.
- Once your development instance is configured, you'll need to obtain the GMF source code in your workspace. To do this, there are several options, including the CVS Repository Exploring Perspective, a Team Project Set file (one is maintained here), and use the releng tool found here. Each of these is detailed below:
- CVS Repository Exploring Perspective
- In the CVS Repositories view, right click and select New > Repository Location... and fill in according to the dialog shown.
Note that a Committer will select 'extssh' for the connection type, and use their supplied user name and password. Find your way to /org.eclipse.gmf/plugins and expand it. Although you're able to check out features, examples, tests, etc., for now, just multi select the plug-ins and right-click. Select 'Check out' and sit back. If all goes well, all the plug-ins will be downloaded and built in your workspace.
- Team Project Set
- You can find a gmf.psf file here for use in quickly setting up a workspace with the GMF projects fetched from CVS that you'll need to get started. From File > Import/Export... simply select 'Team Project Set' from the Import list, navigate to the file, and you're done! Another psf file that contains all of GMF is found here.
- Release Engineering Tool
- A nice feature of this little-known tool is its ability to synchronize your workspace to the set of projects found in a map file. Of course, you'll first need to obtain the map file, which for GMF is found in the project org.eclipse.gmf/releng/org.eclipse.gmf.releng which you'll need to obtain from CVS. An alternative is to grab the directory.txt file found on most project download sites, add it to a project in your workspace with a .map extension and right-click to Team > Load Map Projects.
- The easiest way to find the current requirements for developing GMF is to look at the development update site. The build machine uses a local mirror to install and configure GMF dependencies (and GMF itself, when executing unit tests), so the list here is what is required. Now, try not to use this mirror as your source of obtaining GMF builds and its dependencies.
- Now, in order to point your development instance at your target instance that has all the required dependencies for GMF development installed, go to Window > Preferences... > Plug-in Development > Target Platform and point it at the 'eclipse' folder of your target instance.
- There are several possible scenarios for working with GMF as a developer. What you focus on will impact how you configure your development workspace and runtime instances. Below is a detailed scenario that represents a possible style of work which will be abbreviated here next. If you get it by reading the abbreviated form, great! If not, hopefully you will after reading the longer version and trying it out yourself.
- In brief, you will configure a launch configuration to contain the GMF plug-ins and create a project to work with your diagram/domain/mapping models. Once you're done and have generated your runtime plug-ins, return to your development instance and import those project. Then, create a new runtime launch configuration to test the generated diagram plug-ins, deploying only those and the required runtime plug-ins (no need to have all of the SDK present in this second configuration). Got it?
Currently, all Eclipse projects utilize CVS for their source repository. There is an excellent CVS plug-in provided with the Platform SDK that has been enhanced to work with the automated build process using this tool. This section focuses on some common CVS use cases and this tool's usage in GMF to facilitate our release engineering.
The structure of GMF's repository is shown below, and is also described in this document. A general document on using CVS with Eclipse projects is maintained here. In short, you'll likely be primarily interested in the plugins directory although anyone using anonymous pserver access can read from all of the modules. Committers using extssh can write to every module. GMF does not (yet) have fine-grained access control over its modules.
- /cvsroot/technology CVSROOT (dev.eclipse.org)
- /org.eclipse.gmf Graphical Modeling Framework subproject
- /contributions GMF code contributions
- /doc Project documentation
- /examples GMF examples
- /features GMF features
- /plugins GMF plugins
- /releng Build procedure scripts, update site, etc.
- /tests GMF unit tests
- /org.eclipse.gmf Graphical Modeling Framework subproject
Creating a Patch
It's likely the second thing you'll do with CVS is create a patch (the first was to obtain the GMF sources). To do this is quite straightforward:
- When you have made the changes or additions to a plug-in, simply right-click the project (or resource) and select Team > Create Patch...
- In the wizard, select the option to "Save in the file system" and create a patch file named after the plug-in.txt (e.g. org.eclipse.gmf.codegen.txt). Note: the naming convention is important to the IP tracking scripts in use by the project, as is the importance of not zipping your patch files, as the size of the file is used to indicate the size of the contribution.
- Submit the patch through Bugzilla. Don't send it directly to a Committer, or to the mailing list, or to the newsgroup. As described in another section of this document, Bugzilla is the best means by which to submit a contribution.
A tool provided by the Platform team to facilitate release engineering is found here. A list of basic functions for this tool is maintained on the download site, as seen at the bottom of this page for the 3.2 release. A copy of those functions is pasted below:
- 1. Release to the Team menu. This action will Tag selected projects with the specified version and update the appropriate loaded *.map files with the version. The user must have the *.map files loaded in their workspace and the use must commit the map file changes to the repository when done.
- 2. Load Map Projects to the Team menu. Select one or more *.map file and this action will load the projects listed in the *.map file into your workspace. Naturally the versions specified in the *.map file will be loaded.
- 3. Tag Map Projects to the Team menu. Select one or more *Map files and this action will tag the projects listed in the *Map files with a tag you specify.
- 4. Compare with Released to the Compare menu. Compare the selected projects with the versions referenced in the currently loaded map files.
- 5. Replace with Released to the Replace menu. Replace the selected projects with the versions referenced in the currently loaded map files.
- 6. Fix Copyright to the Resource Perspective Projects context menu. Select one or more projects in the Resource Perspective. This action will sanity check the copyright notices in all the *.java and *.properties files. Copyrights will be updated automatically where the tool deems appropriate. A copyright.log file will be written to the workspace directory noting odd conflicts that need to be looked at. You need to commit the changes yourself. This is the tool that was used to do the 2.1 Copyright pass.
The items here relate to coding standards, best practices and style concerns to maintain GMF code to the high standards expected from an Eclipse project.
In accordance with EPL projects, as described here, all source files need to have the appropriate copyright notice. To set this, navigate to Preferences... > Java > Code Style > Code Templates, use the following:
Another document covers what you'll need to do in order to run the automated build for GMF, including local update site mirror and CruiseControl setup. It is recommended that everyone read this, as you can learn a lot about how GMF is built, tested, and packaged in the process.
Adding or Removing a Plug-in
Adding a plug-in project is fairly straightforward:
- Create a project name that clearly indicates the component the plug-in is part of (runtime, codegen, map, etc.), all lower case and matching the plug-in ID.
- Stick with the default 'src' and 'bin' locations for source and binaries.
- Make sure you check 'Create an OSGi bundle manifest'. With that, if your plug-in has no extension-points defined, or contributes to another's, there is no need to maintain an empty plugin.xml file.
- The plug-in properties should contain localized Name and Provider strings, found in an accompanying plugin.properties file. Note that the Plug-in Provider name is always 'Eclipse.org' for GMF (and other eclipse.org project) plug-ins.
- Be sure to add '.qualifier' to the end of the version number to allow for automatic generation of fully-qualified plug-ins during the build process.
- All package names (regardless of whether they are ‘internal' or not) should be listed as Exported Packages (Runtime tab of manifest.mf editor) with “visible to downstream plug-ins” visibility option. Visibility of internal packages should be set to hidden. See this document for more details. Don't forget to list the package there as soon as it's created!
- Be sure to include your plug-in in the appropriate feature. Features are used for the automated build, so if they are not listed here, they will not be included.
- For javadoc to be run on your plug-in, add it to the buildDoc.xml file in the org.eclipse.gmf.doc plug-in.
- Add your plug-in to the appropriate map file, found in org.eclipse.gmf.releng/maps (there is a map file for each feature). You will find other plug-ins listed, so just use them as an example of how to create a map entry.
- Update the *.psf files maintained in the releng project to include your new plug-in.
- When checking in your new plug-in, be sure to specify the correct path in the CVS Team > Share Project... dialog. A plug-in will go into /org.eclipse.gmf/plugins/org.eclipse.gmf.my.plugin, as shown in the dialog below:
Removing a plug-in also introduces a few things to watch out for:
- Be sure to remove your plug-in from the feature(s) it is included in, and don't forget to update the Dependencies tab on the feature.xml editor. In fact, be sure to remove all traces of dependencies to your plug-in!
- Do not attempt to delete the empty folder from CVS yourself. Instead, submit a Bugzilla report to the Community project, using the CVS component to request its removal by the webmaster. It's recommended that old plug-ins are moved to the /archive module and not deleted.
Adding a Class
There's not much to say about adding a class, but for completeness:
- Don't forget to export the package on the Runtime tab of the manifest editor, if you're creating a new one.
- Be conscious of your imported dependencies and class location. Your dependencies should mirror the typical GMF workflow. In other words, be worried if your new runtime class has a dependency on a codegen class ;-)
- Add the appropriate JavaDoc comments, especially for API classes and Interfaces.
- Don't mix UI and non-UI code! Create a separate plug-in ending in '.ui' for your use interface elements (actions, dialogs, wizards, etc.). Of course, limit your logic code in UI plug-ins, favoring a 'core' plug-ins to hold the most reusable logic.
- For generated classes, if modifying a method that contains a '@generated' tag, be sure to place 'NOT' after it to prevent it from being overwritten. :*Note that it is preferable to create '@generated NOT' tags, rather than removing the '@generated' tag completely.
It was already mentioned that plugin.xml files that reference no extension points should be eliminated. These plug-ins will only need the OSGi Manifest.mf file.
Whenever possible, favor plug-ins deployed as a single JAR. This means your plug-in as listed in a feature.xml file should contain the unpack="false" attribute value. Note that some plug-ins will need to be unpacked upon installation.
With that, there should be no JAR listed for your plug-ins in the Classpath section of the Runtime tab in the manifest editor. There should be a single '.' entry listed in the Runtime Information section of the Build tab, with the default 'src' source folder specified (hint, you need to select the library in order for the source folder to be visible). Note that without the '.' library specified and pointing to the 'src' folder, the generated build.xml file needed during the automated build will have no compilation target.
Be sure that your Manifest.mf contains no Bundle-ClassPath entry.
Create your schema first when authoring a new extension-point. There is a wizard for this supplied by the PDE. It is extremely important to create proper extension-points that are well-documented.
In Windows > Preferences... > Java > Compiler, be sure to set your options to use JDK Compliance to 5.0, with default settings below. For GMF 1.0.0 and maintenance stream, we used 1.4 for compiler, generated .class file compatibility, and source compatibility settings.
The GMF Development Resources area contains links to convention and guideline documents for coding in general, like this one. Below are just a few quick notes:
- On the topic of formatting, the standard Eclipse settings for Java code are fine. The one exception is the (anachronistic?) line length limit of 80 characters. Feel free to bump this up to something more "reasonable" (say, 200).
- A set of format settings is maintained here for you to import into your workspace from Window > Preferences > Java > Code Style > Formatter > Import...
- Another file for code templates for use in GMF is maintained here and can be imported from Window > Preferences > Java > Code Style > Code Templates > Import... Note: You may wish to change the copyright name in Comments > Files to your company in place of the default Eclipse.org.
- Package naming policies for Eclipse projects are fairly standardized. Below are some examples for GMF (when in doubt, look at what's been done before):
- org.eclipse.gmf.<component> The "root" of the plug-in namespace for GMF
- org.eclipse.gmf.tests.<component> The "root" of the test plug-in namespace for GMF
- org.eclipse.gmf.internal.<component> The location of non-API code (note that 'internal' comes before the component).
The use of System.out and System.err is to be discouraged within committed code. Rather, utilize assertions, the Platform Log, or exceptions instead. Permanent debug output should be achieved using
Platform.getDebugOption() and corresponding .option files placed in the plug-in root. It's important to add descriptive comments for options you've added.
Strings that are subject to translation should be externalized, preferably from the very beginning. With that, never, ever, concatenate localized strings to insert values! Class java.text.MessageFormat is your friend.
Externalized strings should be put into standard java .properties files. Choose the placement of these files carefully. Try to avoid .properties files with few keys (like 2), unless you are quite sure there will be more keys as the project evolves. Consider merging small and dispersed .properties files into one file, with sole Messages.class to access them. Perhaps using single plugin.properties at the project's root is the best choice? It's not too much fun to dig through the packages structure looking for .properties files one may hide there.
Use Eclipse Message Bundles to externalize strings and not standard Java ResourceBundles. To use the new approach, don't forget to check 'Use Eclipse's string externalization mechanism' box in Externalize Strings dialog. This dialog is presented by selecting the Source > Find Strings to Externalize... menu option.
Note that ICU4J is now used in Eclipse.
The org.eclipse.gmf.codegen plug-in contains all the templates and utility classes to trigger code generation. JET templates are located under the 'templates' directory and are grouped by their task into subdirectories. An emf-merge.xml configuration file is also present to control JMerge (copied directly from EMF).
Templates target the 'src-templates' folder and should be checked into CVS with the templates.
Follow these conventions for template filename extensions - .javajet, .propertiesjet, .xmljet – reflecting resulting file type, and .jetinc for included template fragments.
It's reasonable to have a factory that encapsulates JETEmitter creation upon your request. Also, it's useful to provide an option to either use template file or Java code directly. In case you add a template to org.eclipse.gmf.codegen, there is already such class: org.eclipse.gmf.codegen.util.EmitterFactory.
To ease the development of JET templates, you may want to try using the JET Editor from the EMFT project.
Similar to adding and removing "normal" plug-ins, there are some things to watch out for when dealing with unit tests. Other information regarding the writing and execution of tests is found here as well.
Adding or Removing a Test Plug-in
dding a test plug-in is just like a "normal" plug-in, with the following additional details:
- Make sure all of your tests are added to the AllTests class.
- A test plug-in needs to have a test.xml file in the project root. This file is used by the automated build to execute the tests. See existing tests for an example.
- Within the test.xml file, a call is made to a target within the testing framework. The choices are 'ui-test' or 'core-test'. Be sure to read this document and make the right choice. Otherwise, your test will fail when run headless even though it may execute fine from the workspace.
- There is another test.xml file in the org.eclipse.gmf.tests-feature/sourceTemplatePlugin folder. You will need to add your plug-in to the list found in this file as well.
- Finally, there is a final file you need to modify, also in the *.releng.builder plug-in. Add your plug-in to the testManifest.xml file and include the impacted builds (see existing entries for an example).
Removing a test plug-in means undoing what was done above.
Running Tests in the Workbench
To execute test plug-ins from within the workbench, simply navigate to the plug-in's AllTests.java file and right-click. Select 'Run As > JUnit Plug-in Test' from the menu. One thing to be aware of here is to enable assertions by passing '-ea' as an argument to the VM for those plug-ins that utilize them. This can be done in the Run dialog, also shown below. One more note: when running the tooling tests (org.eclipse.gmf.tests) from the workspace, you'll need to add '-dev bin,runtime' to the program arguments.
An alternative way to execute your tests within the workbench is to use the test.xml file, which is required for each plug-in for use in the automated build. It is a little more complicated to do this, but it will help ensure your tests are able to be run outside the workbench.
- You will need to simulate the environment used by the automated build in order to execute your tests using the test.xml file. This means creating a test instance of Eclipse with the GMF SDK, Examples, and Test components installed, in addition to its dependencies. An easy way to do this is to setup the automated build locally and utilize the local update mirror for installing everything.
- To complete the setup of your target, you will need to install the testing framework, found here. The latest version is maintained on the Platform download page.
- Right-click the test.xml file and select 'Run As > Ant Build...' from the menu.
- In the dialog, you will need to specify some arguments on the Main tab, with an example shown below (alter to match your environment):
Bugzilla is used for just about everything on Eclipse projects, from bug reporting (obviously), to feature requests, to patch submissions and Intellectual Property governance, to requirements management. Here you will find links and information on how to best use Bugzilla when developing on GMF.
The Eclipse Process Guidelines contain some good information and a handy diagram for understanding the lifecycle of an issue in Bugzilla. Another source of information is the Modeling Project Workflow Conventions wiki.
Committing a Contribution
Care needs to be taken when submitting code from others to protect the IP of all parties involved, and to provide traceability for all source that ends up in the Eclipse repository. Basically, the process works like this:
- You work a bug (it should be assigned to you) or you add some new functionality.
- To create a patch file, see the CVS section of this document. Note the importance of the naming convention.
- To submit the patch, create an attachment for the item in Bugzilla, selecting the 'patch' checkbox:
- Once reviewed and approved by a Committer, the item's status will be changed to "Resolved" and checked into CVS, with the 'contributed' keyword added to indicate it was committed. The Bugzilla comment entered by the Committer should contain the word 'committed' (e.g. 'Reviewed and committed patch') in order for it to be identified by the IP tracking script.
- Another IP-related function is the collection of your contact information. The Committer you work with should collect this and forward to the Project Lead so that your Bugzilla ID used in the IP log can be linked to this information if necessary. Note that it is important to be a visible contributor for obtaining Committer rights, and the best way to do this is to adhere to these basic conventions of patch creation and submission to ensure the IP log is accurate.
- If you're interested in what this log contains, the one for GMF is maintained here. Feel free to review and point out contributions you have made that somehow are not called out in this log.