From Fedora Project Wiki
(Add List of execution environment that java-1.6.0-openjdk may provide + some minor modifications)
No edit summary
Line 1: Line 1:
= Introduction =
= 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 ([https://bugzilla.redhat.com/506471 bz506471 ]) but isn't activate by default at this time.
OSGi bundles are JAR files containing Java bytecode along with meta-data similar to RPMs. This OSGi meta-data can be translated into RPM Requires and Provides similar to how it is done for perl or mono packages. This functionality exists in Fedora's rpm-4.7.0-8.fc12 ([https://bugzilla.redhat.com/506471 bz506471 ]) and will be turned on by default in Fedora in the near future.


BTW, I especially thank Andrew Overolt for reviewing the document and for him nice community spirit - You rocks solid guy!
= What this means for Fedora packagers =
If your package contains OSGi bundles (JARs), RPM Requires and Provides will automatically be created at the end of the build.  If your package does not contain OSGi metadata but another package needs an OSGi bundle of your package's contents, OSGi meta-data should be injected into your package's JAR <pre>META-INF/MANIFEST.MF</pre> files.  While this does cause our packages to diverge from their various upstreams, it allows us to easily have a single copy of the bytecode (and JARs) on the installed system.  Non-OSGi Java runtimes will simply ignore the OSGi meta-data.  See below for an example of how to inject this meta-data.  It is difficult to provide an example for every case as there are many different build systems in use.  The requirement is just that JARs that get installed must have the appropriate OSGi properties in their <pre>META-INF/MANIFEST.MF</pre> files.


= Glossary =
== Example of injecting OSGi meta-data into an existing package ==
'''OSGi meta-data:''' information contained in ''META-INF/MANIFEST.MF'' file pertaining to a JAR's modularity.
<pre>commons-el-eclipse-manifest.patch</pre> contains:
<pre>
--- META-INF/MANIFEST.MF.orig 2007-07-11 12:47:24.000000000 -0400
+++ META-INF/MANIFEST.MF 2007-07-11 12:49:32.000000000 -0400
@@ -9,3 +9,16 @@
Implementation-Title: org.apache.commons.el
  Implementation-Vendor: Apache Software Foundation
Implementation-Version: 1.0
+Import-Package: javax.servlet;version="2.4",javax.servlet.http;version
+ ="2.4",javax.servlet.jsp;version="2.0",javax.servlet.jsp.el;version="
+ 2.0",javax.servlet.jsp.resources;version="2.0",javax.servlet.jsp.tage
+ xt;version="2.0",javax.servlet.resources;version="2.4"
+Bundle-ManifestVersion: 2
+Export-Package: org.apache.commons.el;version="1.0.0",org.apache.commo
+ ns.el.parser;version="1.0.0"
+Bundle-Version: 1.0.0.v200806031608
+Bundle-SymbolicName: org.apache.commons.el
+Bundle-Name: Apache Commons JSP 2.0 Expression Language Interpreter
+Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3
+Bundle-Localization: plugin
+Bundle-Vendor: Apache Software Foundation
</pre>


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


= OSGi Framework Overview =
<pre>
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.
%prep
%setup -q -n %{short_name}-%{version}-src
%patch0 -p1 -b .license
pushd src/conf
%patch1 -p1
popd
...
</pre>


This  overview was copied from the OSGi specification version 4.0.1 available for download there: http://www.osgi.org/Specifications/HomePage
= osgideps.pl Details =
 
= 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 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 the file of symlink'd bundles (we ensure that we don't pull-in broken packages due to dead symlinks).
Line 24: Line 48:
* it doesn't take care of optional dependencies.
* 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.
* it always generates the complete OSGi version to be able to match 1.0 and 1.0.0 as equal in RPM.
You can run the script (<pre>/usr/lib/rpm/osgideps.pl</pre>) manually on a set of JARs.  See below for script options and example usage.


== Options ==
== Options ==
Line 34: Line 60:
'''-system''' print system bundle of OSGi .profile files
'''-system''' print system bundle of OSGi .profile files


== Example of uses ==
== Example of script usage ==
Print OSGi required bundles of all jar files into the current directory :
Print OSGi required bundles of all jar files into the current directory :
<pre>
<pre>
Line 47: Line 73:
ls -1 J2SE-1.6.profile | /usr/lib/rpm/osgideps.pl -s | sed "s/^osgi/Provides\:\tosgi/g"
ls -1 J2SE-1.6.profile | /usr/lib/rpm/osgideps.pl -s | sed "s/^osgi/Provides\:\tosgi/g"
</pre>
</pre>
= 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.
=== 1. Put entire OSGi meta-data directory ''org.junit%{version}''  into the ''junit''  package as a sub-package that Requires the main package ===
<tt>junit-osgi</tt> package can contain <tt>org.junit%{version}</tt> 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.
=== 2. Create sub package for each bundles that contain OSGi meta-data ===
We could create a sub-package that contains the <tt>/usr/lib/eclipse/dropins/jdt/plugins/org.junit%{version}</tt> directory (e.g. <tt>eclipse-jdt-junit</tt> or <tt>eclipse-junit</tt>).
'''Advantages:'''
* We stay close to upstream
* Not many changes are needed
'''Disadvantages:'''
* Other OSGi implementations need to create symbolic links to Eclipse-specific paths.
=== 3. "Inject" OSGi meta-data into ''junit''  package ===
This technique is used in existing Fedora packages such as [http://cvs.fedoraproject.org/viewcvs/devel/jakarta-commons-el/ 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 <tt>osgideps.pl</tt> script with the following command.
<pre>
ls -1 J2SE-1.6.profile | osgideps.pl -s | sed "s/^osgi/Provides\:\tosgi/g"
</pre>
====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''
==== List of Execution Environments that ''java-1.6.0-openjdk'' may provide ====
* OSGi/Minimum-1.1
* J2SE-1.3
* J2SE-1.4
* J2SE-1.5
* JavaSE-1.6
* Foundation-1.0 and Foundation-1.1 can also be provided with the exception that it provides some MicroEdition IO classes. These classes seems to not be used by bundles provided by Eclipse. 
FYI, There is a table containing all bundles that Eclipse 3.5 provides and their needed execution environments available in the [http://www.eclipse.org/eclipse/development/readme_eclipse_3.5.html#Appendix1 3.5 README], maybe it can be useful in the future.
====Table of most common execution environments====
{|- border="1"
! Name
! Description
|-
| CDC-1.0/Foundation-1.0
| indicates that the bundle can only be run on Foundation 1.0 or greater. Note that with the exception of some MicroEdition IO classes, Foundation 1.0 is a subset of J2SE 1.3.
|-
| CDC-1.1/Foundation-1.1
| indicates that the bundle can only be run on Foundation 1.1 or greater. Note that with the exception of some MicroEdition IO classes, Foundation 1.1 is a subset of J2SE 1.4.
|-
| OSGi/Minimum-1.1
| This is a subset of the J2ME Foundation class libraries defined by OSGi to be the base for framework implementations. See the OSGi specification for more details.
|-
| J2SE-1.3
| J2SE 1.3 - indicates that the bundle can only be run on JSE 1.3 or greater.
|-
| J2SE-1.4
| J2SE 1.4 - indicates that the bundle can only be run on JSE 1.4 or greater.
|-
| J2SE-1.5
| Java SE 5 - indicates that the bundle can only be run on Java SE 5 or greater.
|-
| JavaSE-1.6
| Java SE 6 - indicates that the bundle can only be run on Java SE 6 or greater.
|-
| 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
|}

Revision as of 16:35, 12 August 2009

Introduction

OSGi bundles are JAR files containing Java bytecode along with meta-data similar to RPMs. This OSGi meta-data can be translated into RPM Requires and Provides similar to how it is done for perl or mono packages. This functionality exists in Fedora's rpm-4.7.0-8.fc12 (bz506471 ) and will be turned on by default in Fedora in the near future.

What this means for Fedora packagers

If your package contains OSGi bundles (JARs), RPM Requires and Provides will automatically be created at the end of the build. If your package does not contain OSGi metadata but another package needs an OSGi bundle of your package's contents, OSGi meta-data should be injected into your package's JAR

META-INF/MANIFEST.MF

files. While this does cause our packages to diverge from their various upstreams, it allows us to easily have a single copy of the bytecode (and JARs) on the installed system. Non-OSGi Java runtimes will simply ignore the OSGi meta-data. See below for an example of how to inject this meta-data. It is difficult to provide an example for every case as there are many different build systems in use. The requirement is just that JARs that get installed must have the appropriate OSGi properties in their

META-INF/MANIFEST.MF

files.

Example of injecting OSGi meta-data into an existing package

commons-el-eclipse-manifest.patch

contains:

--- META-INF/MANIFEST.MF.orig	2007-07-11 12:47:24.000000000 -0400
+++ META-INF/MANIFEST.MF	2007-07-11 12:49:32.000000000 -0400
@@ -9,3 +9,16 @@
 Implementation-Title: org.apache.commons.el
 Implementation-Vendor: Apache Software Foundation
 Implementation-Version: 1.0
+Import-Package: javax.servlet;version="2.4",javax.servlet.http;version
+ ="2.4",javax.servlet.jsp;version="2.0",javax.servlet.jsp.el;version="
+ 2.0",javax.servlet.jsp.resources;version="2.0",javax.servlet.jsp.tage
+ xt;version="2.0",javax.servlet.resources;version="2.4"
+Bundle-ManifestVersion: 2
+Export-Package: org.apache.commons.el;version="1.0.0",org.apache.commo
+ ns.el.parser;version="1.0.0"
+Bundle-Version: 1.0.0.v200806031608
+Bundle-SymbolicName: org.apache.commons.el
+Bundle-Name: Apache Commons JSP 2.0 Expression Language Interpreter
+Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3
+Bundle-Localization: plugin
+Bundle-Vendor: Apache Software Foundation

and is applied:

%prep
%setup -q -n %{short_name}-%{version}-src
%patch0 -p1 -b .license
pushd src/conf
%patch1 -p1
popd
...

osgideps.pl Details

  • 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.

You can run the script (

/usr/lib/rpm/osgideps.pl

) manually on a set of JARs. See below for script options and example usage.

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 script usage

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"