As Andreas blogged a while ago, we at itemis are working on a requirements editor as part of a public research project. Developing a full-fledged requirements management tool is not in the scope of the project. What is of interest is to have a solution to enable traceability from requirements to design, all the way to source code. Looking around for an eclipse based open source solution for requirements management, we realized that this space is currently empty (except for ORMF which somehow didn’t fit our needs or give us confidence).
Having decided to move on with a solution of our own, the next step was to shop for a suitable meta-model for requirements. We weren’t quite unlucky as before here. We had two choices here, SysML or RIF.
SysML or RIF (now ReqIF)
SysML is a general purpose modeling language for systems engineering applications. RIF on the other hand is an interchange format for exchanging requirements between partners. Although SysML and RIF can capture requirements, we found RIF more apt for our needs, as its scope is limited to requirements management. Currently, RIF is up for standardization at OMG with a new name ReqIF.
RIF offers a schema based XML format as well as its UML meta-model in Enterprise Architect. To add to our confidence in RIF, IBM had already incorporated an importer/exporter for the RIF in IBM Rational DOORS . Several other companies, like MKS, are also working on an implementation of the RIF specification.
Bringing RIF to Eclipse world
The first step in building some tooling around RIF was to bring it into an eclipse compatible meta-model. Naturally, the first choice was Ecore, the now de-facto eclipse meta-model. However, converting RIF from an Enterprise Architect format to a Ecore XMI was a herculean task. After failing to do the conversion with the steps I detailed here, we went on a journey of export-import-export from tool to tool and finally had a RIF compatible Ecore meta-model.
The RIF Model
The RIF model is a generic requirements meta-model. (From another perspective, too generic to be called a requirements meta-model). The meta-model allows to define requirement types and requirement objects, fitting one of those types. Take for instance, a type “Functional Requirement” with attributes such as “ID“, “Name” and “Status“. You could use RIF to create a SpecType named “Functional Requirement” with matching AttributeDefinitions for “ID“, “Name” and “Status” . The AttributeDefinitions could also have DatatypeDefinitions. Based on the defined SpecType you could create SpecObjects having AttributeValues for all the AttributeDefinitions.
This is a birds-eye view of the RIF meta-model.
We retained the generic nature of RIF in the editor as well. To start with, you could create type specifications using a tree based editor.
Based on the type specifications, the editor at runtime creates an eclipse forms based user interface, lays it out neatly and lets you edit your requirements. As you could see below, the editor creates a tree to display the requirement hierarchy on the left. On the right, the editor lets you edit the requirement attributes by creating matching UI elements to handle the basic datatypes like String, Integer, Enumeration etc. you created during RIF type specification using the tree editor.
You could easily build extensions to the editor using the provided extension points. If you need a specific UI behavior, you could define a new complex datatype and build UI customizations for this complex datatype. For example, we extended the basic editor to have an embedded DSL editor (using Xtext) to capture detailed requirements.
The RIF editor loads and writes out XML conforming to the RIF schema.
Filling the void
We aren’t quite there yet. We, of course need more community interest and support to take this forward. Once we do, we hope to fill the void completely and have an open source solution for requirements management.
Signing an eclipse plugin is the process of stamping an eclipse plugin with a certificate, by which the plugin could reveal its authenticity to anyone who installs and executes it. Although, by default, eclipse generates unsigned plugins, starting 3.3, eclipse began verifying the integrity of plugins installed via update sites by checking for an attached digital certificate and issuing a warning when an unsigned content is found. Luckily, eclipse doesn’t prevent you from running the unsigned content. However, if you would like to distribute your eclipse plugins or host them via an update site, it is important that your plugins are signed. This would allow the users to reliably identify you as the publisher of the plugin and make sure that the plugin has not been altered since it was uploaded to the update site. This also avoids the user getting a warning message as below.
The signing of a plugin is done using a certificate. A certificate is a digitally signed statement from an entity (person, company etc.), saying that the public key of some other entity (for example, a Java class file) has a particular value. There are two types of certificates:
- Self-signed certificates: A self signed certificate is what you could create on your own to sign your plugins. When users install plugins signed with self-signed certificate, they are presented with a dialog similar to the one below. The users could verify the certificate and install the plugins if they feel the source is trustworthy.
- Certificates signed by a trusted third-party: When a certificate issued by a trusted third-party like Verisign is used, the user will not be presented with the warning/trust dialog and the plugins are installed directly. However, such certificates have high cost implications. If your plugins would be made available on Eclipse.org, they will be signed with the foundation certificate (refer http://wiki.eclipse.org/JAR_Signing for more information). However, the process of signing with such certificates is not in the scope of this article.
Eclipse doesn’t define a mechanism of its own for signing plugins. Since all eclipse plugins are JARs (well almost), eclipse uses the java mechanism of JAR signing to sign plugins. Also, eclipse doesn’t come with any tooling for JAR signing (until Bugzilla request 11485 is closed). Hence you have to rely on command line tools keytool and jarsigner (keytool.exe and jarsigner.exe on Windows ) that comes with java to get the job done.
Before you begin, make sure to set the environment variable $JAVA_HOME to the Java location. To identify the location of installed Java, open Eclipse "Help > About" dialog and click on "Configuration Details". Look for the value "java.home=<some path>" and copy the entire path. On Windows replace "$JAVA_HOME" with "%JAVA_HOME%".
The commands below are for Mac OSX/Linux and uses “sudo” to make updates. On Windows leave out “sudo“.
1. Creating a self-signed certificate
sudo keytool -genkey -dname “cn=<common name>, ou=<organizational unit>, o=<organization>, c=<country>” -alias <alias name> -keystore <keystore location> -storepass <keystore password> -validity <validity of certificate in days>
sudo keytool -genkey -dname “cn=Nirmal Sasidharan, ou=Pf, o=itemis, c=DE” -alias “nirmal” -keystore $JAVA_HOME/lib/security/cacerts -storepass “changeit” -validity 180
The default Java keystore password is “changeit” unless you have changed it. The command would ask for a password to be created for the alias. Enter a password, confirm it and remember it for the next step and for later.
2. Signing the JARs
To sign the plugin and feature JARs with the certificate created by the step above run the following command.
jarsigner –keystore <keystore location> -storepass <keystore password> -verbose
jarsigner -keystore $JAVA_HOME/lib/security/cacerts -storepass “changeit” -verbose de.itemis.project.updatesite/plugins/de.itemis.plugin_1.0.0.jar nirmal
The command signs one JAR at a time. To do batch signing, you could create a simple shell script (or an equivalent batch file on Windows) as below:
for i in $1/*.jar
jarsigner -keystore $JAVA_HOME/lib/security/cacerts -storepass
“changeit” -verbose -keypass $3 $i $2
Invoke the script as
./jarbatchsign.sh <path to folder containing jars> <alias name> <password for alias>
./jarbatchsign.sh de.itemis.project.updatesite/plugins/ nirmal aliaspassword
3. Testing the signed plugins
Delete your own certificate from the keystore before you test the update site with the signed plugins (see “Deleting certificate from keystore” below).
Restart eclipse and install the signed plugins from the update site. If all is well, a trust dialog as described before appears.
Other Useful functions
Listing certificates in keystore
sudo keytool -list -keystore <keystore location> -storepass <keystore password> -v -alias <alias name>
sudo keytool -list -keystore $JAVA_HOME/lib/security/cacerts -storepass “changeit” -v -alias nirmal
Deleting certificate from keystore
sudo keytool -delete –keystore <keystore location> -storepass <keystore password>
sudo keytool -delete -keystore $JAVA_HOME/lib/security/cacerts -storepass “changeit” nirmal
Verifying signed jars
jarsigner -keystore <keystore location> -storepass <keystore password> -verify -verbose -certs
jarsigner -keystore $JAVA_HOME/lib/security/cacerts -storepass “changeit” -verify -verbose -certs de.itemis.project.updatesite/plugins/de.itemis.plugin_1.0.0.jar
Disabling security check
You could disable the eclipse certificate check all together using the startup option -Declipse.p2.unsignedPolicy=allow. See Bug 235526.
A “split package” is a pretty old Java term where you have packages in different libraries with the same name providing related (or sometimes unrelated functionality). The classes in one package can access classes in the other package (with the same name) across library boundaries without any problem at both compile and runtime. This is true even for package-private classes. This works fine in the Java world as you deal with only a single hierarchical class loader. If you bring this concept to the OSGi (or Eclipse) world, you are in for trouble, where each bundle has its own class loader. This is what happened to me while I was doing some heavy refactoring recently.
I had the task of making a “monolithic” Eclipse system modular. Refactoring in JDT did a great job and in the end I had a modular system with no compile time errors. The pain started when I ran the application and started getting exceptions, I have never seen until now working with Eclipse framework.
Here’s what I did in short. I split a plug-in into two plugins, “Plugin A” and “Plugin B”, where “Plugin A” contained the main functionality and “Plugin B” was providing some library functions. So naturally “Plugin A” depended on “Plugin B” (or in OSGi terms, “Plugin A” had a “Require-Bundle: Plugin B” declared). Though not intentional, both plugins ended up having a package with the same name “SplitPackage”. A “Class A” in “SplitPackage” in “Plugin A” had a method call on “Class B” in “SplitPackage” in “Plugin B”.
PDE did not complain nor did I get any compile time errors. Now when I ran it, I got a “java.lang.IllegalAccessError: tried to access Class B from Class A”. I kept wondering why I would get this linkage error which I should normally get at compile time from PDE. After spending half a day on it, I found the cause. “Class B” was declared as package-private . The moment I changed this into a public class, all was well again (although this wasn’t my final solution).
The root cause here was that OSGi loaded “Plugin A” and “Plugin B” using different class loaders and the packages “SplitPackage” in both bundles are not the same and they live in two different worlds with a clear boundary between them. “Class A” in “Plugin A” cannot see package-private “Class B” after the bundles are resolved. This resulted in the java.lang.IllegalAccessError exception at runtime. The exception doesn’t pop up at compile time as a Java compiler doesn’t know these boundaries and sees them as split packages. May seem strange but true!
Moral of the story is that never have split packages in the Eclipse environment. For OSGi, a package is the atomic unit and it should be as cohesive as possible. If you have functionality split into two packages with the same name, then they are not cohesive and ideally the packages should have different names or the classes should live within one package. If you really need split packages, make one of them an Eclipse fragment plugin. A fragment plugin always lives within a host plugin and both of them are loaded by the same class loader.