From Fedora Project Wiki

Introduction

OSGi bundles contain meta-data just like RPMs do. This meta-data can be used to automatically generate Provides and Requires similar to how it is done for mono packages. This functionality exists in Fedora's rpm-4.7.0-8.fc12 but isn't activate by default at this time (rhbz506471).

BTW, I especially thank Andrew Overolt for reviewing the document and for him nice community spirit - You rocks solid guy!

Glossary

OSGi meta-data: information contained in META-INF/MANIFEST.MF file pertaining to a JAR's modularity.

Bundle: a JAR file (that can be expanded) with special OSGi entries in its manifest and containing classes, resources, and other JARs.

OSGi Framework Overview

The Framework forms the core of the OSGi Service Platform Specifications. It provides a general-purpose, secure, and managed Java framework that supports the deployment of extensible and downloadable components known as bundles. OSGi-compliant "devices" can download and install OSGi bundles, and remove them when they are no longer required. The Framework manages the installation and update of bundles in an OSGi environment in a dynamic and scalable fashion. To achieve this, it manages the dependencies between bundles and services in detail. It provides the bundle developer with the resources necessary to take advantage of Java’s platform independence and dynamic code-loading capability in order to easily develop services for small-memory devices that can be deployed on a large scale.

This overview was copied from the OSGi specification version 4.0.1 available for download there: http://www.osgi.org/Specifications/HomePage

OSGi Framework Fedora support (osgideps.pl)

osgideps.pl script is run on each META-INF/MANIFEST.MF and .jar file. It parses OSGi headers and generates RPM Provides and Requires based on this meta-data.

Some rules that the script follows to generate dependencies

  • it doesn't generate Provides for symlinks (these OSGi bundles are not contained in the package as only symlinks are provided).
  • it strictly Requires the file of symlink'd bundles (we ensure that we don't pull-in broken packages due to dead symlinks).
  • it strictly Requires files of symlink'd bundle defined by the Bundle-ClassPath header (an example of this are the symlinks to ant JAR files in the Eclipse packages).
  • it ignores system.bundle (since that's an alias that represents the OSGi framework itself).
  • it doesn't take care of optional dependencies.
  • it always generates the complete OSGi version to be able to match 1.0 and 1.0.0 as equal in RPM.

Options

-provides print provides of OSGi files (META-INF/MANIFEST.MF and .jar)

-requires print requires of OSGi files

-debug print file path (used with -provides or -requires)

-system print system bundle of OSGi .profile files

Example of uses

Print OSGi required bundles of all jar files into the current directory :

ls -1  *.jar | /usr/lib/rpm/osgideps.pl -requires | sort -u

Print OSGi required bundles of all JAR files in /usr/share/java directory with the file path on the same line (useful to debug sub-package errors):

find /usr/share/java -name "*.jar" | /usr/lib/rpm/osgideps.pl -provides -debug

Generate provides of an OSGi .profile file:

ls -1 J2SE-1.6.profile | /usr/lib/rpm/osgideps.pl -s | sed "s/^osgi/Provides\:\tosgi/g"

OSGi Packaging Guidelines

Bundles that only contain symlink'd JAR files

The junit bundle of the eclipse-jdt package is used to explain this problem. Currently if a package Requires the osgi(org.junit) bundle, then the whole eclipse-jdt package is pulled in because it Provides that bundle though meta-data (MANIFEST.MF)

The OSGi specification says The Framework should provide a private persistent storage area for each installed bundle on platforms with some form of file system support.

I conclude that each OSGi implementation that Fedora could support in the future would have they own structure to contain their bundles. So if we will share the same bundle within multiple Framework implementations, we need to play with symbolic links to accomplish this.

We can fix that problem in 3 different ways (maybe more) but I personally prefer the first one because we can stay as close as possible with upstream projects without losing the advantage of not pulling in unneeded dependencies.


Put entire OSGi meta-data directory org.junit%{version} into the junit package as a sub-package that Requires the main package

junit-osgi package can contain org.junit%{version} directory and automatically require junit main package though the Bundle-ClassPath manifest entry.

Advantages:

  • Other OSGi implementations don't need to symlink to Eclipse-specific paths.
  • Package name accurately reflects what the content is.
  • No need to patch manifest file or include non-upstream content in the junit package.
  • We stay close to upstream because we can symlink to the same content.

Disadvantages:

  • Needs more work.


Create sub package for each bundles that contain OSGi meta-data

We could create a sub-package that contains the /usr/lib/eclipse/dropins/jdt/plugins/org.junit%{version} directory (e.g. eclipse-jdt-junit or eclipse-junit).

Advantages:

  • We stay close to upstream
  • Not many changes are needed

Disadvantages:

  • Other OSGi implementations need to create symbolic links to Eclipse-specific paths.


"Inject" OSGi meta-data into junit package

This technique is used in existing Fedora packages such as jakarta-commons-el (commons-el-eclipse-manifest.patch patch).

Advantages:

  • Other OSGi implementations don't need to symlink to Eclipse-specific paths.
  • No need for a sub-package.

Disadvantages:

  • junit package diverges from upstream.
  • In the case of junit bundle, we need to include some other files into the upstream JAR. Not sure if it's a good idea to diverge so much with upstream.

Fedora Java Runtime

Provide appropriate system bundles

Fedora Java Runtime packages need to add appropriate OSGi Provides. These provides can be extracted by osgideps.pl script with the following command. See [script doc link] for more information about the script.

ls -1 J2SE-1.6.profile | osgideps.pl -s | sed "s/^osgi/Provides\:\tosgi/g"

Why

The OSGi specification says in the Parent Class Loader paragraph: The set of implicitly imported packages are all java.* packages, since these packages are required by the Java runtime, and using multiple versions at the same time is not easy. For example, all objects must extend the same Object class. A bundle must not declare imports or exports for java.* packages; doing so is an error and any such bundle must fail to install. All other packages available through the parent class loader must be hidden from executing bundles.

However, the Framework must explicitly export relevant packages from the parent class loader. The system property

   org.osgi.framework.system.packages

contains the export package descriptions for the system bundle. This property employs the standard Export-Package manifest header syntax:

   org.osgi.framework.system.packages ::= package-description (
   ',' package-description )*

Some classes on the boot classpath assume that they can use any class loader to load other classes on the boot classpath, which is not true for a bundle class loader. Framework implementations should attempt to load these classes from the boot class path. The system bundle (bundle ID zero) is used to export non-java.* packages from the parent class loader. Export definitions from the system bundle are treated like normal exports, meaning that they can have version numbers, and are used to resolve import definitions as part of the normal bundle resolving process. Other bundles may provide alternative implementations of the same packages.

Java Runtimes need to provides appropriate Named Execution Environments (not yet implemented)

We can imagine the need to add provides for Execution Environments. OSGi bundles can requires osgi(JavaSE-1.6) through Bundle-RequiredExecutionEnvironment and the java-1.6.0-openjdk package can provide it.

Why

The OSGi specification say in the Naming Execution Environments paragraph: Execution environments require a proper name so that [...] A bundle can require that a Framework provides a certain execution environment before it is installed

Table of most common execution environments

Name Description
CDC-1.0/Foundation-1.0 Equal to J2ME Foundation Profile
OSGi/Minimum-1.1 OSGi EE that is a minimal set that allows the implementation of an OSGi Framework.
JRE-1.1 Java 1.1.x
J2SE-1.2 Java 2 SE 1.2.x
J2SE-1.3 Java 2 SE 1.3.x
J2SE-1.4 Java 2 SE 1.4.x
J2SE-1.5 Java 2 SE 1.5.x
JavaSE-1.6 Java SE 1.6.x
PersonalJava-1.1 Personal Java 1.1
PersonalJava-1.2 Personal Java 1.2
CDC-1.0/PersonalBasis-1.0 J2ME Personal Basis Profile
CDC-1.0/PersonalJava-1.0 J2ME Personal Java Profile