buildr-bnd

This is a Buildr extension for packaging OSGi bundles using Bnd (See www.aqute.biz/Code/Bnd). The extension allows the user to define properties/directives to be supplied to the Bnd tool and provides reasonable defaults for those that can be derived from the project model. Please see the bnd tool for documentation on the available properties.

The ‘bnd’ setting is used to provide directives to the bnd tool that are not inherited by subprojects while the standard ‘manifest’ setting is used to define properties that inherited by subprojects.

A typical project that uses the extension may look something like;

define 'myProject' do
  ...
  package(:bundle).tap do |bnd|
    bnd['Import-Package'] = "*;resolution:=optional"
    bnd['Export-Package'] = "*;version=#{version}"
  end
  ...
end

Installation

The extension is packaged as a gem named “buildr-iidea”, consult the ruby gems installation steps but typically it is either

sudo gem install buildr-bnd

for MRI ruby or

jgem install buildr-bnd

for jruby.

The user then needs to add the following require into the build file:

require 'buildr_bnd'

If the local maven repository does not contain the required bnd jars they can be downloaded but you will need to register the remote repository by adding the following to the build file:

repositories.remote << Buildr::Bnd.remote_repository

Defaults

The extension sets the following bnd parameters;

  • Bundle-Version defaults to the project version.

  • Bundle-SymbolicName defaults to the concaternation of the project group and project id, replacing ‘:’ characters with ‘.’.

  • Bundle-Name defaults to the project description if present else the project name

  • Bundle-Description defaults to the project description.

  • Import-Package and Export-Package default to *

  • -classpath is set to the compile target directory and any compile time dependencies.

Parameters

classpath_element

The user can also specify additional elements that are added to the classpath using the ‘classpath_element’ method. If the parameter to this element is a task, artifact, artifact namespace etc. then it will be resolved prior to invoking bnd.

define 'foo' do
  ...
  package(:bundle).tap do |bnd|
    # This dependency will be added to classpath
    bnd.classpath_element 'someOtherExistingFile.zip'
    # All of these dependencies will be invoked and added to classpath 
    bnd.classpath_element artifact('com.sun.messaging.mq:imq:jar:4.4')
    bnd.classpath_element project('bar') # Adds all the packages
    bnd.classpath_element 'org.apache.ant:ant:jar:1.8.0'
    bnd.classpath_element file('myLocalFile.jar')
    ...
  end

  project 'bar' do
    ...
  end
end

Examples

Using bnd to wrap an existing jar

Bnd can be used to wrap an existing jar as an OSGi bundle. The following example wraps the OpenMQ JMS provider as an OSGi bundle.

require 'buildr_bnd'

# Add repository for OpenMQ
repositories.remote << 'http://download.java.net/maven/2'

desc 'OSGi bundle for OpenMQ JMS provider client library'
define 'com.sun.messaging.mq.imq' do
  project.version = '4.4'
  project.group = 'iris'
  package(:bundle).tap do |bnd|
    bnd['Import-Package'] = "*;resolution:=optional"
    bnd['Export-Package'] = "com.sun.messaging.*;version=#{version}"
    bnd.classpath_element 'com.sun.messaging.mq:imq:jar:4.4'
  end
end

Create an OSGi bundle with an Activator

The following example presents a basic buildfile for building an OSGi bundle with an activator.

require 'buildr_bnd'

# repository for OSGi core bundle
repositories.remote << 'https://repository.apache.org/content/repositories/releases'

desc 'Hello World bundle'
define 'helloworld' do
  project.version = '1.0'
  project.group = 'org.example'
  compile.with 'org.apache.felix:org.osgi.core:jar:1.4.0'
  package(:bundle).tap do |bnd|
    bnd['Export-Package'] = "org.example.helloworld.api.*;version=#{version}"
    bnd['Bundle-Activator'] = "org.example.helloworld.Activator"
  end
end

Inheriting parameters for bnd tool

The following example shows how you can use ‘manifest’ to define a bnd parameter that is inherited to all child subprojects. The “Bundle-License” defined in the top level project is passed to the bnd tool when generating both the ‘fe’ and ‘fi’ subprojects but the ‘fo’ subproject overrides this parameter withy a local value.

require 'buildr_bnd'

define 'myproject' do
  manifest['Bundle-License'] = "http://www.apache.org/licenses/LICENSE-2.0"
  ...
  define 'fe' do
    ...
    package :bundle
  end

  define 'fi' do
    ...
    package :bundle
  end

  define 'fo' do
    ...
    package(:bundle).tap do |bnd|
      bnd['Bundle-License'] = "http://www.apache.org/licenses/LICENSE-1.1"
    end
  end
end

Credit

The plugin was heavily inspired by the bnd tasks originally authored by Rhett Sutphin. It began life as a fork but has been rewritten from scratch to use a different approach.