Uploaded image for project: 'Felix'
  1. Felix
  2. FELIX-807

conversion of JAR into bundle fails if there are classes is the default name space

    Details

      Description

      The conversion of JAR into bundle fails if there are classes is the default name space, like hsqldb does.

      Try this pom.xml:

      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>bug.maven.plugin</groupId>
      <artifactId>felix-bundle</artifactId>
      <packaging>bundle</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>hsqldb</name>
      <url>http://maven.apache.org</url>
      <build>
      <plugins>
      <plugin>
      <artifactId>maven-dependency-plugin</artifactId>
      <executions>
      <execution>
      <id>copy-dependencies</id>
      <phase>package</phase>
      <goals>
      <goal>copy-dependencies</goal>
      </goals>
      </execution>
      </executions>
      </plugin>
      <plugin>
      <groupId>org.apache.felix</groupId>
      <artifactId>maven-bundle-plugin</artifactId>
      <executions>
      <execution>
      <id>bundle-manifest</id>
      <phase>process-classes</phase>
      <goals>
      <goal>manifest</goal>
      </goals>
      </execution>
      </executions>
      <extensions>true</extensions>
      <configuration>
      <manifestLocation>META-INF</manifestLocation>
      <instructions>
      <Bundle-ClassPath>target/dependency/hsqldb-1.8.0.7.jar</Bundle-ClassPath>
      <Import-Package>*</Import-Package>
      <Export-Package>*</Export-Package>
      <Embed-Dependency>*;scope=compile|runtime;inline=false</Embed-Dependency>
      <Embed-Directory>target/dependency</Embed-Directory>
      <Embed-StripGroup>true</Embed-StripGroup>
      </instructions>
      </configuration>
      </plugin>
      </plugins>
      </build>
      <dependencies>
      <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
      </dependency>
      <dependency>
      <groupId>hsqldb</groupId>
      <artifactId>hsqldb</artifactId>
      <version>1.8.0.7</version>
      <scope>compile</scope>
      </dependency>
      </dependencies>
      </project>

      To fix this I suggest a modification inside biz.aQute.bndlib.bndlib-0.0.255.jar inside class aQute.lib.osgiProcessor:

      private void analyzeJar(Jar jar, String prefix, Map classSpace,
      Map contained, Map referred, Map uses) throws IOException {
      next: for (Iterator r = jar.getResources().keySet().iterator(); r
      .hasNext() {
      String path = (String) r.next();
      if (path.startsWith(prefix)) {
      String relativePath = path.substring(prefix.length());
      String pack = getPackage(relativePath);

      if (pack != null && !contained.containsKey(pack)) {
      if (!(pack.equals(".") || isMetaData(relativePath))) {

      The last line is the line where the default name space "." is expicit excluded. I don't understand why, but for class files it must be enabled. I suggest

      if (pack != null && !contained.containsKey(pack)) {
      if (!(pack.equals(".") || realtivePath.endsWith(".class") || isMetaData(relativePath))) {

      to solve this issue.

        Activity

        Hide
        mcculls Stuart McCulloch added a comment -

        I have not looked at this closely, but please note that it's a bad idea for a bundle to export the default package.
        This is why Peter explicitly checks the default namespace - probably it should be a warning, not an error, and
        it should definitely allow adding of classes in the default namespace if you're not going to export them.

        but exporting of classes in the default namespace should definitely be flagged, so your patch isn't quite right

        if you want to workaround this error, you can tell BND to ignore it and create the bundle anyway:

        <_failok>true</_failok>

        BTW, the bundleplugin docs:

        http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html#ApacheFelixMavenBundlePlugin(BND)-EmbedDependencyandExportPackage

        clearly state why you shouldn't use <Export-Package>*</Export-Package> if you're embedding dependencies,
        because you will end up duplicating content, especially when you're embedding jar files with "inline=false".

        if you look at the jar generated by your original pom it contains both the embedded jar files and their contents,
        because the Embed-Dependency instruction tells BND to embed the jars and the Export-Package instruction
        tells it to pull in everything on the compilation classpath (ie. inline all classfiles)

        few other things: I don't think you need the extra bundle:manifest goal, the Import-Package defaults to * so you
        can remove that, and Embed-Dependency takes care of updating Bundle-ClassPath with any embedded jars.

        so you could trim your instructions to something like the following, perhaps:

        <instructions>
        <_exportcontents>org.hsqldb.*</_exportcontents>
        <Embed-Dependency>*;scope=compile|runtime;type=!pom;inline=false</Embed-Dependency>
        <Embed-Directory>target/dependency</Embed-Directory>
        <Embed-StripGroup>true</Embed-StripGroup>
        <_failok>true</_failok>
        </instructions>

        Show
        mcculls Stuart McCulloch added a comment - I have not looked at this closely, but please note that it's a bad idea for a bundle to export the default package. This is why Peter explicitly checks the default namespace - probably it should be a warning, not an error, and it should definitely allow adding of classes in the default namespace if you're not going to export them. but exporting of classes in the default namespace should definitely be flagged, so your patch isn't quite right if you want to workaround this error, you can tell BND to ignore it and create the bundle anyway: <_failok>true</_failok> BTW, the bundleplugin docs: http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html#ApacheFelixMavenBundlePlugin(BND)-EmbedDependencyandExportPackage clearly state why you shouldn't use <Export-Package>*</Export-Package> if you're embedding dependencies, because you will end up duplicating content, especially when you're embedding jar files with "inline=false". if you look at the jar generated by your original pom it contains both the embedded jar files and their contents, because the Embed-Dependency instruction tells BND to embed the jars and the Export-Package instruction tells it to pull in everything on the compilation classpath (ie. inline all classfiles) few other things: I don't think you need the extra bundle:manifest goal, the Import-Package defaults to * so you can remove that, and Embed-Dependency takes care of updating Bundle-ClassPath with any embedded jars. so you could trim your instructions to something like the following, perhaps: <instructions> <_exportcontents>org.hsqldb.*</_exportcontents> <Embed-Dependency>*;scope=compile|runtime;type=!pom;inline=false</Embed-Dependency> <Embed-Directory>target/dependency</Embed-Directory> <Embed-StripGroup>true</Embed-StripGroup> <_failok>true</_failok> </instructions>
        Hide
        bebbo Stefan Franke added a comment -

        since there is a workaround using

        <_failok>true</_failok>

        this is no longer urgent.

        Show
        bebbo Stefan Franke added a comment - since there is a workaround using <_failok>true</_failok> this is no longer urgent.
        Hide
        bebbo Stefan Franke added a comment -

        Thanks for your input Stuart.

        I agree on the default namespace, but there are JARs haveing classes in the default name space like hsqldb and I would like to have one pom.xml to convert all into a bundle. And I even dont want to export the default name space!

        The <_failok>true</_failok> suppresses the abortion and thus it works now. And _failok is not mentioned in http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html#ApacheFelixMavenBundlePlugin(BND)-EmbedDependencyandExportPackage

        so I will use now either

        <Import-Package>!*</Import-Package>
        <Export-Package>org.hsqldb.*</Export-Package>
        <Embed-Dependency>hsqldb*;scope=compile|runtime;inline=true</Embed-Dependency>
        <Embed-Directory>target/dependency</Embed-Directory>
        <Embed-StripGroup>true</Embed-StripGroup>
        <_failok>true</_failok>

        or

        <Import-Package>!*</Import-Package>
        <_exportcontents>org.hsqldb.*</_exportcontents>
        <Embed-Dependency>hsqldb*;scope=compile|runtime;inline=false</Embed-Dependency>
        <Embed-Directory>target/dependency</Embed-Directory>
        <Embed-StripGroup>true</Embed-StripGroup>
        <_failok>true</_failok>

        and the tags starting with an underscore still look wrong.

        IMHO there should be no need for <_exportcontents>: The hint "inline=false" is enough information to avoid unpacking the JAR(s)
        Also <_failok> is ugly. It should run smooth without.

        Show
        bebbo Stefan Franke added a comment - Thanks for your input Stuart. I agree on the default namespace, but there are JARs haveing classes in the default name space like hsqldb and I would like to have one pom.xml to convert all into a bundle. And I even dont want to export the default name space! The <_failok>true</_failok> suppresses the abortion and thus it works now. And _failok is not mentioned in http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html#ApacheFelixMavenBundlePlugin(BND)-EmbedDependencyandExportPackage so I will use now either <Import-Package>!*</Import-Package> <Export-Package>org.hsqldb.*</Export-Package> <Embed-Dependency>hsqldb*;scope=compile|runtime;inline=true</Embed-Dependency> <Embed-Directory>target/dependency</Embed-Directory> <Embed-StripGroup>true</Embed-StripGroup> <_failok>true</_failok> or <Import-Package>!*</Import-Package> <_exportcontents>org.hsqldb.*</_exportcontents> <Embed-Dependency>hsqldb*;scope=compile|runtime;inline=false</Embed-Dependency> <Embed-Directory>target/dependency</Embed-Directory> <Embed-StripGroup>true</Embed-StripGroup> <_failok>true</_failok> and the tags starting with an underscore still look wrong. IMHO there should be no need for <_exportcontents>: The hint "inline=false" is enough information to avoid unpacking the JAR(s) Also <_failok> is ugly. It should run smooth without.
        Hide
        mcculls Stuart McCulloch added a comment -

        > I agree on the default namespace, but there are JARs haveing classes in the default name space like hsqldb and I would like to have one pom.xml to convert all into a bundle. And I even dont want to export the default name space!

        yes - I totally agree that you should be allowed to have classes in the default namespace, as long as you don't export them

        btw, if you don't want to export the default namespace then definitely don't use <Export-Package>*</Export-Package> as that exports everything!

        > The <_failok>true</_failok> suppresses the abortion and thus it works now. And _failok is not mentioned in http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html#ApacheFelixMavenBundlePlugin(BND)-EmbedDependencyandExportPackage

        true, the bundleplugin docs don't describe all of the possible BND instructions (as more are added over time) - it does point to the BND docs at http://aqute.biz/Code/Bnd in the first paragraph of the page and later on when it discusses certain instructions, but failok is one that should probably be mentioned explicitly

        > so I will use now either
        >
        > <Import-Package>!*</Import-Package>

        hmm, here you're telling BND not to import anything at all, which means you'll get exceptions at runtime because hsqldb needs various javax.* packages to work - the OSGi framework only boot delegates java.* packages, so you need to import javax.* to see the JVM packages exported via the system bundle

        FYI, unless you're adding attributes (like resolution:=optional for optional imports) or version ranges (to limit resolution to a specific API level) then it's often best to keep the default Import-Package instruction to * ... then BND will automatically calculate the correct imports for you (see http://aqute.biz/Code/Bnd for details)

        > <Export-Package>org.hsqldb.*</Export-Package>
        > <Embed-Dependency>hsqldb*;scope=compile|runtime;inline=true</Embed-Dependency>

        again, please do not use overlapping Export-Package and Embed-Dependency instructions!

        <Export-Package> tells BND to add matching packages to the bundle and export them (ie. make them visible to other bundles)

        <Private-Package> adds matching packages to the bundle but doesn't export them (ie. they are not then visible to other bundles)

        <Embed-Dependency> tells BND to embed or inline the contents of matching dependencies, but doesn't specify their visibility

        <_exportcontents> tells BND to make certain packages visible from the bundle without changing the contents of the bundle

        so if you're using Embed-Dependency then just use exportcontents to mark which packages you want to export ... unless you have classes in the compilation classpath (for example locally compiled classes) that you also want to add to the bundle, in which case you use Private-Package or Export-Package with the relevant package name to pull them in as well

        > <Embed-Directory>target/dependency</Embed-Directory>
        > <Embed-StripGroup>true</Embed-StripGroup>
        > <_failok>true</_failok>
        >
        > or
        >
        > <Import-Package>!*</Import-Package>

        [see above]

        > <_exportcontents>org.hsqldb.*</_exportcontents>
        > <Embed-Dependency>hsqldb*;scope=compile|runtime;inline=false</Embed-Dependency>

        this is correct - you can also use "inline=true" and exportcontents, because exportcontents acts just like Export-Package except it doesn't change the actual content of the bundle (doesn't pull in classes)

        > <Embed-Directory>target/dependency</Embed-Directory>
        > <Embed-StripGroup>true</Embed-StripGroup>
        > <_failok>true</_failok>
        >
        > and the tags starting with an underscore still look wrong.

        wrong in what way? bundleplugin works on top of BND, and a number of BND instructions like failok happen to start with a dash like -failok

        unfortunately in XML <-failok> is not a valid tag because of the leading dash, so we are forced to use <_failok> instead... it's the same with -exportcontents / <_exportcontents>

        > IMHO there should be no need for <_exportcontents>: The hint "inline=false" is enough information to avoid unpacking the JAR(s)

        this has nothing to do with unpacking the jar... exportcontents just says what packages you want to make visible to other bundles without changing the contents (see above for the full description of what the different instructions do). If you just use Embed-Dependency then you're telling BND to add the contents of the jar (or the jar itself) but don't say which packages should be made public

        so you can leave out exportcontents, but then you won't be exporting any packages (this is ok if you're not expecting other bundles to use the packages)

        > Also <_failok> is ugly. It should run smooth without.

        of course, that's why it's called a workaround

        Show
        mcculls Stuart McCulloch added a comment - > I agree on the default namespace, but there are JARs haveing classes in the default name space like hsqldb and I would like to have one pom.xml to convert all into a bundle. And I even dont want to export the default name space! yes - I totally agree that you should be allowed to have classes in the default namespace, as long as you don't export them btw, if you don't want to export the default namespace then definitely don't use <Export-Package>*</Export-Package> as that exports everything! > The <_failok>true</_failok> suppresses the abortion and thus it works now. And _failok is not mentioned in http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html#ApacheFelixMavenBundlePlugin(BND)-EmbedDependencyandExportPackage true, the bundleplugin docs don't describe all of the possible BND instructions (as more are added over time) - it does point to the BND docs at http://aqute.biz/Code/Bnd in the first paragraph of the page and later on when it discusses certain instructions, but failok is one that should probably be mentioned explicitly > so I will use now either > > <Import-Package>!*</Import-Package> hmm, here you're telling BND not to import anything at all, which means you'll get exceptions at runtime because hsqldb needs various javax.* packages to work - the OSGi framework only boot delegates java.* packages, so you need to import javax.* to see the JVM packages exported via the system bundle FYI, unless you're adding attributes (like resolution:=optional for optional imports) or version ranges (to limit resolution to a specific API level) then it's often best to keep the default Import-Package instruction to * ... then BND will automatically calculate the correct imports for you (see http://aqute.biz/Code/Bnd for details) > <Export-Package>org.hsqldb.*</Export-Package> > <Embed-Dependency>hsqldb*;scope=compile|runtime;inline=true</Embed-Dependency> again, please do not use overlapping Export-Package and Embed-Dependency instructions! <Export-Package> tells BND to add matching packages to the bundle and export them (ie. make them visible to other bundles) <Private-Package> adds matching packages to the bundle but doesn't export them (ie. they are not then visible to other bundles) <Embed-Dependency> tells BND to embed or inline the contents of matching dependencies, but doesn't specify their visibility <_exportcontents> tells BND to make certain packages visible from the bundle without changing the contents of the bundle so if you're using Embed-Dependency then just use exportcontents to mark which packages you want to export ... unless you have classes in the compilation classpath (for example locally compiled classes) that you also want to add to the bundle, in which case you use Private-Package or Export-Package with the relevant package name to pull them in as well > <Embed-Directory>target/dependency</Embed-Directory> > <Embed-StripGroup>true</Embed-StripGroup> > <_failok>true</_failok> > > or > > <Import-Package>!*</Import-Package> [see above] > <_exportcontents>org.hsqldb.*</_exportcontents> > <Embed-Dependency>hsqldb*;scope=compile|runtime;inline=false</Embed-Dependency> this is correct - you can also use "inline=true" and exportcontents, because exportcontents acts just like Export-Package except it doesn't change the actual content of the bundle (doesn't pull in classes) > <Embed-Directory>target/dependency</Embed-Directory> > <Embed-StripGroup>true</Embed-StripGroup> > <_failok>true</_failok> > > and the tags starting with an underscore still look wrong. wrong in what way? bundleplugin works on top of BND, and a number of BND instructions like failok happen to start with a dash like -failok unfortunately in XML <-failok> is not a valid tag because of the leading dash, so we are forced to use <_failok> instead... it's the same with -exportcontents / <_exportcontents> > IMHO there should be no need for <_exportcontents>: The hint "inline=false" is enough information to avoid unpacking the JAR(s) this has nothing to do with unpacking the jar... exportcontents just says what packages you want to make visible to other bundles without changing the contents (see above for the full description of what the different instructions do). If you just use Embed-Dependency then you're telling BND to add the contents of the jar (or the jar itself) but don't say which packages should be made public so you can leave out exportcontents, but then you won't be exporting any packages (this is ok if you're not expecting other bundles to use the packages) > Also <_failok> is ugly. It should run smooth without. of course, that's why it's called a workaround
        Hide
        rickhall Richard S. Hall added a comment -

        In OSGi there is no way to export the default package, since it has no name and exports need a name.

        Show
        rickhall Richard S. Hall added a comment - In OSGi there is no way to export the default package, since it has no name and exports need a name.
        Hide
        bebbo Stefan Franke added a comment -

        Again:

        1. I don't want to export something on the default scope.
        2. But if there is a class on the dfault scope - which is not exported - the plugin fails.

        The plugin MUST never fail on classes it MUST ignore.

        Show
        bebbo Stefan Franke added a comment - Again: 1. I don't want to export something on the default scope. 2. But if there is a class on the dfault scope - which is not exported - the plugin fails. The plugin MUST never fail on classes it MUST ignore.
        Hide
        mcculls Stuart McCulloch added a comment -

        Suggested patch, based on 0.0.308 - it keeps the default package in the list of contained packages, but disallows its export.
        For a simple testcase, create a class in the default package and use Private-Package: . to include the class but not export it.

        Show
        mcculls Stuart McCulloch added a comment - Suggested patch, based on 0.0.308 - it keeps the default package in the list of contained packages, but disallows its export. For a simple testcase, create a class in the default package and use Private-Package: . to include the class but not export it.
        Hide
        pkriens Peter Kriens added a comment -

        Applied the patch in bnd-310

        Show
        pkriens Peter Kriens added a comment - Applied the patch in bnd-310
        Hide
        mcculls Stuart McCulloch added a comment -

        Closing as maven-bundle-plugin 2.0.0 has been released.

        Show
        mcculls Stuart McCulloch added a comment - Closing as maven-bundle-plugin 2.0.0 has been released.

          People

          • Assignee:
            pkriens Peter Kriens
            Reporter:
            bebbo Stefan Franke
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Time Tracking

              Estimated:
              Original Estimate - 0.5h
              0.5h
              Remaining:
              Remaining Estimate - 0.5h
              0.5h
              Logged:
              Time Spent - Not Specified
              Not Specified

                Development