Thursday, November 24, 2005

Btool, the OSGi Bundle Maker

Bundles are plain old JAR files, which in their turn are plain old ZIP files. The JAR files are a convenient container for code and resources, grouped in packages. Additionally, a manifest is provided that provides bits and pieces of information about the contents. The common way to make a bundle is to create a directory structure that mirrors the desired structure and then use the jar-tool of the JDK to create the JAR file.

Unfortunately, this way of working is error prone because the contents of the JAR are closely related to the manifest. The manifest must specify the packages that can be exported (available to others) as well as which packages must be imported. This is not trivial, especially when bundles are designed as small, self contained, cohesive units, for example, OSGi RI and TCK consist over 700 bundles, which have a myriad of relations among each other.

Another problem is that making the intermediate directory structure is usually done in highly project dependent ant or make files. These scripts are hard to read, which makes it difficult  to get an overview how the JAR file is structured. A particularly tricky problem is when a JAR file needs a copy of a package that is on the class path, this is almost impossible without special support.

Meet Btool. Btool started its life in 1998 when I got so frustrated with making bundles using only the jar-tool as support. Tracking import- and exported packages and their versions are not my description of fun. I was working for Ericsson Research at that time and had to help a lot of people making bundles.

The first version of Btool was given a root class, which it then recursively parsed for all dependencies. Command line parameters were used to indicate which packages should packed in the JAR. From this information, Btool could calculate the import and export clauses. Versions were derived from a file called packageinfo, which we maintain in each package directory.  The packageinfo file is also packed in the JAR.

Btool generates the manifest from the generated JAR and a raw-manifest file that can contain property references. An example raw-manifest file:

     Manifest-Version: 1.0
     Bundle-Name: ${p}
Bundle-Activator:     ${p}.Activator
     Bundle-Description: The %24{p} variable is
       replaced with the project name ${p}
Comment: $(DATE)
     $(IMPORT-PACKAGE)
     $(EXPORT-PACKAGE)
     $(PRIVATE-PACKAGE)

The manifest file is pre-processed and the property references are replaced with the appropriate information. Btool supports an extensive number of macros like substitute, prefix/suffix, sort, filter, and more.

Since then a lot has changed, we are currently at generation 3. Btool is now an ant task and completely driven by a properties file. Eclipse drove the use of the build.properties file (which is standard in Eclipse) but in the end they have become incompatible. A typical build.properties file looks like:

     jars.compile.order=${p}.jar
     expand.${p} = [com.acme.mybundle], \
                com.acme.util.*
     include.mybundle.jar = [doc/license.html], \
          doc/help.html, \
[README.txt]
     
The expand property indicates the packages that should be stored in the JAR, which come from the project’s class path. If the package is enclosed with square brackets ([]), it means the package is to be exported. Package can contain wildcards, which will include all packages starting with that prefix. The project’s class path can be set with the Eclipse IDE (we use the .classpath file) or the classpath property can be set to a list of directories or JAR files. The include property will copy files into the JAR. If a file is enclosed with square brackets, it will be pre-processed just like the manifest.

While creating the JAR file, Btool can store all the sources in the OPT-INF/src directory, calculate the Name sections, create files for initial provisioning, and can do many more functions. However, crucial is the analysis phase at the end. When the JAR file is created, Btool can open it again and analyze it for consistency. It will check the import/export sections, checks if the Bundle Activator is in the JAR or imported, looks at the Bundle-Classpath, and does many more checks. The analysis has saved me from endless grief.

I am so used to Btool that for me personally it is hard to see how you can make bundles without it. However, must people are doing well without it looking at the large number of bundles that are created. However, there is work going on. In the Oscar/Felix project there is mangen that creates manifests for a set of bundles. There is also the OSGi plugin for the Maven project, Eclipse is working hard on bundle tools, and there are plugins. However, when you are member of OSGi, take a look at the OSGi repository on membercvs and see how Btool can be used to simplify your projects.

No comments:

Post a Comment