Snippets / BundleClassPath aQute - Software Consultancy
Search
*

Use of the OSGi Bundle-ClassPath with Beanshell

Purpose

The Bundle-Classpath sets a search path for classes inside the bundle. The search path can consist of the bundle's jar ('.') or the path name (inside the bundle) of a directory or jar file. This snippet shows the use of a library from the BeanShell project. We create a small hello world example using beanshell.

Prerequisites

  • osgi interfaces, provides all service interfaces for the OSGi specifications.

Instructions

The BeanShell library can be downloaded from bsh-core-2.0b4.jar. Note that this is a LGPL or Sub Public License library. The project name is aQute.bundleclasspath. We therefore store the code in aQute.bundleclasspath and the library in aQute/bundleclasspath/lib. This library is not a bundle (unfortunately). However, in this example we will include this relatively small JAR inside our bundle and link it on the Bundle-ClassPath.

First lets write the activator. The easiest way to use beanshell is to extend the bsh.Interpreter class. To keep the code simple and small we let the bundle activator extend this Interpreter class. The beanshell interpreter normally uses the file system; in this case there is no file system so we must adapt the file system calls to the resources of the bundle. We therefore override the source(String) method. This method gets a file name and evaluates the file contents. In our implementation, we just get the file from the resources. In this snippet we load the files from the package directory, but this can be easily changed.

The start and stop methods just call this source method with start.bsh and stop.bsh. In this examples these resources just contain simple System.out.println statements. Just for demonstration, we also set the "context" variable in the interpreter to our bundle context. This is, however, not used in the example.

  Source: aQute.bundleclasspath.Activator
  package aQute.bundleclasspath;

  import java.io.*;
  import org.osgi.framework.*;
  import bsh.*;

  public class Activator extends Interpreter implements
      BundleActivator {

    public void start(BundleContext context) throws Exception {
      set("context", context);
      source("start.bsh");
    }

    public void stop(BundleContext context) throws Exception {
      source("stop.bsh");
    }

    public Object source(String fileName) throws EvalError,
        IOException {
      InputStream in = getClass().getResourceAsStream(
          fileName);
      if (in == null) throw new FileNotFoundException(
          fileName
              + " could not be found in the bundle's resources");
      Reader rdr = new InputStreamReader(in);
      Object result = eval(rdr);
      rdr.close();
      return result;
    }
  }

The syntax of the Bundle-ClassPath header is simple. It is an ordered comma separated list of resource names. Each named resource can be a directory in the bundle, a JAR file in the bundle, or '.', indicating the bundle itself. By default, the Bundle-ClassPath is set to '.'; indicating the whole bundle. In this case we need the aQute.bundleclasspath package because it contains the bundle activator, and this package is in the bundle. We also want the contents of the bsh jar file. In this case the order is not that relevant because there is (and there should not be) any overlap between our bundle's contents and the bsh jar contents. The Bundle-ClassPath is therefore:

  Bundle-ClassPath: ., bsh-core-2.0b4.jar

The Bundle-ClassPath addresses its resources from the root of the bundle. Our bsh jar file is in the lib sub directory. We therefore need to copy it to the root of our bundle. Bnd provides the Include-Resource instruction to copy resources. Just to minimize typing, we just indicate the lib directory; this will copy all files in the lib directory to the root of the bundle.

Note the case for Bundle-ClassPath, bnd is case sensitive and using the wrong case can send you on a long debugging session. Bnd > 0.0.112 gives a warning if you use another case.

  Include-Resource: lib

If we would have liked the file to go the lib directory, we could have used lib=lib, this syntax allows one to specify a destination directory. However, in this case we are happy with the root of the bundle.

We only then need to specify the contents of the bundle and the activator. In this case we only use the aQute.bundleclasspath package. There is no need to make this an exported package so we keep it private.

Resulting bnd file:

  Bnd file: aQute.bundleclasspath.bnd
  Bundle-ClassPath: .,bsh-core-2.0b4.jar
  Private-Package: aQute.bundleclasspath
  Include-Resource: lib
  Bundle-Activator: aQute.bundleclasspath.Activator
  Bundle-License: Contains LGPL or Sun Public License code. 

Links

Copyright 2006 aQute SARL, All Rights Reserved