In my previous blog post, I explained about how to convert third party and in-house API libraries to OSGi bundles. Once you convert your in-house API libraries to OSGi bundles, you will not be able to browse/debug your API source code, while working on GUI code. "Attach source" will not be an option anymore in
What is
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: cruise
Build-Jdk: 1.6.0_10
Bundle-ManifestVersion: 2
Bundle-Name: Utility
Bundle-SymbolicName: com.mycompany.utility.source
Bundle-Vendor: MyCompanyName
Bundle-Version: 1.0.0.SNAPSHOT
Here the last line (Eclipse-SourceBundle) is the one which identifies this bundle as a source bundle. This says that this bundle is source bundle of "com.mycompany.utility" bundle whose version is "1.0.0.SNAPSHOT". Note that bundle name and version has to match exactly.
roots directive says which folder within the source bundle has source code. By default it is "." and it is true for most cases. If you have a special case, you can change it.
Automation:
Automation of source bundles can be done using maven build helper and maven source plugins. In your project's POM or parent POM, add the following block in build section:
<!-- Build helper maven plugin sets the parsedVersion.osgiVersion property -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>set-osgi-version</id>
<phase>verify</phase>
<goals>
<goal>parse-version</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- source maven plugin creates the source bundle and adds manifest -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifestEntries>
<Bundle-ManifestVersion>2</Bundle-ManifestVersion>
<Bundle-Name>${name}</Bundle-Name>
<Bundle-SymbolicName>${groupId}.${artifactId}.source</Bundle-SymbolicName>
<Bundle-Vendor>${organization.name}</Bundle-Vendor>
<Bundle-Version>${parsedVersion.osgiVersion}</Bundle-Version>
<Eclipse-SourceBundle>${groupId}.${artifactId};version="${parsedVersion.osgiVersion}";roots:="."</Eclipse-SourceBundle>
</manifestEntries>
</archive>
</configuration>
</plugin>
Here, maven source plugin takes care of creating the source jar and adding appropriate information to it's manifest so that it can be a valid OSGi source bundle. One small problem is, maven adds "-" before qualifier, whereas OSGi adds "." before qualifier. If you use BND to turn your jar into bundle, the bundle version would be 1.0.0.SNAPSHOT, whereas maven version is 1.0.0-SNAPSHOT. This is where, maven build helper plugin helps above. Make sure to use the latest version (1.5) of this plugin, which has parse-version goal. This goal sets the parsedVersion.osgiVersion property, which has the version string, but has the "-" replaced by ".".
Automate copying source bundles to Eclipse target platform:
Now, that source bundles are automatically created and installed/deployed to your maven repo, next step is to make sure they are automatically copied to Eclipse target platform, so that Eclipse can recognize it. Only then, you can view/debug the source code from within Eclipse. In my previous post, I explained about how to automate copying dependency bundles to target platform. Look at "Automate Copying Bundles to
<properties>
<pluginsDir>./plugins</pluginsDir>
</properties>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
<!-- This execution downloads and copies the dependency bundles -->
<execution>
<id>copy-dependencies</id>
<phase>process-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${pluginsDir}</outputDirectory>
</configuration>
</execution>
<!-- This execution downloads and copies the dependency source bundles -->
<execution>
<id>copy-dependency-sources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<classifier>sources</classifier>
<failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
<outputDirectory>${pluginsDir}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Maven dependency plugin takes care of downloading/copying the dependencies and it's corresponding source bundles. Here, "sources" classifier takes care of the source bundle. Now, whenever you do "mvn process-resources", this would pull in latest OSGi bundle dependencies and also it's source bundles from maven repo and copy to plugins folder in target platform.
Conclusion:
We saw what an Eclipse source bundle is and how to automatically create it, whenever the bundle is built. We also saw how to download and copy the source bundles from maven repo to your local Eclipse target platform, using maven plugins.