As a first step, we need a Maven 2 project descriptor. To create this beast, we have to decide, how we build the project. I generally use the Apache Felix Maven Bundle Plugin to build my projects as OSGi bundles. This great plugin comes with support for Maven 2 packaging but also provides goals to call if the packaging functionality should not be used.
Before talking too much, let me just present a project descriptor, which I know works. After that I will explain why I did it, like I did it.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ch.meschberger.sample</groupId>
<artifactId>ch.meschberger.sample.sysext</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>System Bundle Extension Sample</name>
<description>
This sample bundle extends the System Bundle export
list with the com.sun.image.codec.jpeg package such
that OSGi bundles may refer to Sun's JPEG implementation
without the OSGi framework itself to provide it in a
non-portable way.
</description>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<forceCreation>true
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
<manifestEntries>
<Export-Package>com.sun.image.codec.jpeg</Export-Package>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>1.4.3</version>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
<configuration>
<instructions>
<Bundle-Category>sample</Bundle-Category>
<Fragment-Host>system.bundle; extension:=framework</Fragment-Host>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
First of all, I use plain old jar packaging. This allows me to have more control over the manifest generation. The problem is, that the Bundle plugin removes any packages from the Export-Package header of the generated manifest which happen to not be present in the final JAR file. This is very good in all cases except in our case, which may of course be considered a special case.
So we use jar packaging. Still I like the wonderful setup of the Bundle plugin when it comes to setting the required OSGi manifest headers. Fortunately, the Bundle plugin allows me to generate a manifest file as if the packaging would be bundle. This is the manifest goal.
Consequently, in the sample above, packaing is set to jar and the Bundle plugin is configured to generate a manifest file with the standard headers plus the Fragment-Host header required to mark the bundle as Framework Extension Bundle. For the Jar plugin to include the generated manifest we refer to it with the manifestFile configuration element, which requires us to add the explicit Jar plugin configuration not normally needed.
Now, we have the Bundle plugin generate the standard headers, we have the Jar plugin use that manifest but still we have two issues: First the Bundle plugin does not have the Export-Package header definition, which would be useless because it would be removed anyway. And second, the Jar plugin would complain, because it has nothing to package.
The first issue is fixed by adding a manifestEntries element to the Jar plugin configuration, which lists the missing Export-Package header.
The second issue is just as easy to solve as the first: We just force the creation of the JAR file by setting the forceCreation parameter.
Unfortunately the Bundle plugin does not create the destination folder into which the generated manifest file is placed. To have this folder created, just create an empty src/main/resources folder. This causes the destination to be created.
That's it. We now just have to use Maven to build that project and we are done and can use it.