Search code examples
javagradleblueprint-osgi

Blueprint XML file scanning with Gradle OSGI plugin


I'm investigating migrating an existing OSGI/blueprint project from Maven to Gradle. In Maven the maven-bundle-plugin plugin scans context XML files for imports that might not occur in the code, however I can't get this to work with the Gradle OSGI plugin.

For example, blueprint XML contains an import like this

<reference id="exampleService" availability="mandatory" interface="com.adamish.test.Test" />

Maven

Using the Bundle-Blueprint instruction in the POM with maven-bundle-plugin...

<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <version>2.4.0</version>
    <extensions>true</extensions>
    <configuration>
        <instructions>
        <Bundle-Blueprint>OSGI-INF/blueprint/context.xml</Bundle-Blueprint> 
        </instructions>
    </configuration>
</plugin>

Then the generated MANFEST.MF will contain an import like this

Import-Package: com.adamish.test 

Gradle

However using the following build.gradle file does not generate a MANIFEST.MF with a Import-Package for com.adamish.test

apply plugin: 'osgi'

jar {
    manifest {
        instruction 'Bundle-Blueprint', 'OSGI-INF/blueprint/context.xml'
    }
}

Analysis

Both Maven and Gradle use BND which seems to contain the Bundle-Blueprint instruction, however when invoked via Gradle it does not cause imports to be added to the MANIFEST.

I've tested this in Gradle 2.4 and now latest 2.10


Solution

  • The Blueprint parsing capability of maven-bundle-plugin is provided by the class BlueprintPlugin part of maven-bundle-plugin, not BND. BND does contain some blueprint-aware code, however that is part of a repoindex command tool.

    I've been able to workaround this issue temporarily by parsing the XML files manually and building list of Java packages

    def importPackages = new LinkedHashSet<String>();
    fileTree(dir: 'src/main/resources/OSGI-INF/blueprint/', include: '*.xml').each {
       new XmlSlurper().parse(it).'**'.findAll { it.@availability == "mandatory" }.each {
          def iFace = [email protected]()
          importPackages.add(iFace.substring(0, iFace.lastIndexOf('.')))
       }
    }
    
    importPackages.add('com.adamish.foo')
    
    jar {
        manifest {
            instruction 'Import-Package', importPackages.join(',')
        }
    }