FELIX-2175: Improve the Blueprint component to parse / introspect blueprint configuration files and generate OBR service requirements / capabilities accordingly
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@921470 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/org/apache/felix/bnd/BlueprintComponent.java b/bundleplugin/src/main/java/org/apache/felix/bnd/BlueprintComponent.java
deleted file mode 100644
index daa4257..0000000
--- a/bundleplugin/src/main/java/org/apache/felix/bnd/BlueprintComponent.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.apache.felix.bnd;
-
-import java.util.List;
-import java.util.ArrayList;
-
-import aQute.lib.spring.XMLTypeProcessor;
-import aQute.lib.spring.XMLType;
-import aQute.lib.osgi.Analyzer;
-
-public class BlueprintComponent extends XMLTypeProcessor {
-
- protected List<XMLType> getTypes(Analyzer analyzer) throws Exception {
- List<XMLType> types = new ArrayList<XMLType>();
-
- String header = analyzer.getProperty("Bundle-Blueprint", "OSGI-INF/blueprint");
- process(types,"blueprint.xsl", header, ".*\\.xml");
-
- return types;
- }
-
-}
diff --git a/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java b/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java
new file mode 100644
index 0000000..6205e23
--- /dev/null
+++ b/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java
@@ -0,0 +1,342 @@
+package org.apache.felix.bundleplugin;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import aQute.bnd.service.AnalyzerPlugin;
+import aQute.lib.osgi.Analyzer;
+import aQute.lib.osgi.Jar;
+import aQute.lib.osgi.Processor;
+import aQute.lib.osgi.Resource;
+import aQute.libg.generics.Create;
+import aQute.libg.qtokens.QuotedTokenizer;
+import aQute.libg.reporter.Reporter;
+
+public class BlueprintPlugin implements AnalyzerPlugin {
+
+
+ static Pattern QN = Pattern.compile("[_A-Za-z$][_A-Za-z0-9$]*(\\.[_A-Za-z$][_A-Za-z0-9$]*)*");
+ static Pattern PATHS = Pattern.compile( ".*\\.xml");
+
+ Transformer transformer;
+
+ public BlueprintPlugin() throws Exception {
+ transformer = getTransformer(getClass().getResource("blueprint.xsl"));
+ }
+
+ public boolean analyzeJar(Analyzer analyzer) throws Exception {
+ transformer.setParameter("nsh_interface", analyzer.getProperty("nsh_interface") != null ? analyzer.getProperty("nsh_interface") : "");
+ transformer.setParameter("nsh_namespace", analyzer.getProperty("nsh_namespace") != null ? analyzer.getProperty("nsh_namespace") : "");
+
+ Set<String> headers = Create.set();
+
+ String bpHeader = analyzer.getProperty("Bundle-Blueprint", "OSGI-INF/blueprint");
+ Map<String, Map<String,String>> map = Processor.parseHeader(bpHeader, null);
+ for (String root : map.keySet()) {
+
+ Jar jar = analyzer.getJar();
+ Map<String, Resource> dir = jar.getDirectories().get(root);
+ if(dir == null || dir.isEmpty())
+ {
+ Resource resource = jar.getResource(root);
+ if(resource != null)
+ process(analyzer, root, resource, headers);
+ return false;
+ }
+ for(Map.Entry<String,Resource> entry : dir.entrySet())
+ {
+ String path = entry.getKey();
+ Resource resource = entry.getValue();
+ if(PATHS.matcher(path).matches())
+ process(analyzer, path, resource, headers);
+ }
+
+ }
+
+ // Group and analyze
+ Map<String, Set<Attribute>> hdrs = Create.map();
+ for (String str : headers) {
+ int idx = str.indexOf(':');
+ if (idx < 0)
+ {
+ analyzer.warning((new StringBuilder("Error analyzing services in blueprint resource: ")).append(str).toString());
+ continue;
+ }
+ String h = str.substring(0, idx).trim();
+ String v = str.substring(idx + 1).trim();
+ Set<Attribute> att = hdrs.get(h);
+ if (att == null) {
+ att = new TreeSet<Attribute>();
+ hdrs.put(h, att);
+ }
+ att.addAll(parseHeader(v, null));
+ }
+ // Merge
+ for (String header : hdrs.keySet())
+ {
+ if ("Import-Class".equals(header) || "Import-Package".equals(header))
+ {
+ Set<Attribute> newAttr = hdrs.get(header);
+ for (Attribute a : newAttr)
+ {
+ String pkg = a.getName();
+ if ("Import-Class".equals(header))
+ {
+ int n = a.getName().lastIndexOf('.');
+ if (n > 0) {
+ pkg = pkg.subSequence(0, n).toString();
+ } else {
+ continue;
+ }
+ }
+ if (!analyzer.getReferred().containsKey(pkg))
+ {
+ analyzer.getReferred().put(pkg, a.getProperties());
+ }
+ }
+ }
+ else
+ {
+ Set<Attribute> orgAttr = parseHeader(analyzer.getProperty(header), null);
+ Set<Attribute> newAttr = hdrs.get(header);
+ for (Attribute a : newAttr)
+ {
+ boolean found = false;
+ for (Attribute b : orgAttr)
+ {
+ if (b.getName().equals(a.getName()))
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ orgAttr.add(a);
+ }
+ }
+ // Rebuild from orgAttr
+ StringBuilder sb = new StringBuilder();
+ for (Attribute a : orgAttr)
+ {
+ if (sb.length() > 0)
+ {
+ sb.append(",");
+ }
+ sb.append(a.getName());
+ for (Map.Entry<String, String> prop : a.getProperties().entrySet())
+ {
+ sb.append(';').append(prop.getKey()).append("=").append(prop.getValue());
+ }
+ }
+ analyzer.setProperty(header, sb.toString());
+ }
+ }
+ return false;
+ }
+
+ private void process(Analyzer analyzer, String path, Resource resource, Set<String> headers)
+ {
+ InputStream in = null;
+ try
+ {
+ in = resource.openInputStream();
+
+ // Retrieve headers
+ Set<String> set = analyze(in);
+ headers.addAll(set);
+ }
+ catch(Exception e)
+ {
+ analyzer.error((new StringBuilder("Unexpected exception in processing spring resources(")).append(path).append("): ").append(e).toString());
+ }
+ finally
+ {
+ try
+ {
+ if (in != null)
+ {
+ in.close();
+ }
+ }
+ catch (IOException e)
+ {
+ }
+ }
+ }
+
+ public Set<String> analyze(InputStream in)
+ throws Exception
+ {
+ Set<String> refers = new HashSet<String>();
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ javax.xml.transform.Result r = new StreamResult(bout);
+ javax.xml.transform.Source s = new StreamSource(in);
+ transformer.transform(s, r);
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ bout.close();
+ BufferedReader br = new BufferedReader(new InputStreamReader(bin));
+ for(String line = br.readLine(); line != null; line = br.readLine())
+ {
+ line = line.trim();
+ line = line.replace(";availability:=mandatory", "");
+ if(line.length() > 0)
+ {
+ refers.add(line);
+ }
+ }
+
+ br.close();
+ return refers;
+ }
+
+ protected Transformer getTransformer(URL url)
+ throws Exception
+ {
+ TransformerFactory tf = TransformerFactory.newInstance();
+ javax.xml.transform.Source source = new StreamSource(url.openStream());
+ return tf.newTransformer(source);
+ }
+
+ public static class Attribute implements Comparable<Attribute>
+ {
+ private final String name;
+ private final Map<String,String> properties;
+
+ public Attribute(String name, Map<String, String> properties) {
+ this.name = name;
+ this.properties = properties;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ public int compareTo(Attribute a) {
+ int c = name.compareTo(a.name);
+ if (c == 0)
+ {
+ c = properties.equals(a.properties) ? 0 :
+ properties.size() < a.properties.size() ? -1 :
+ properties.hashCode() < a.properties.hashCode() ? -1 : +1;
+ }
+ return c;
+ }
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Attribute attribute = (Attribute) o;
+
+ if (name != null ? !name.equals(attribute.name) : attribute.name != null) return false;
+ if (properties != null ? !properties.equals(attribute.properties) : attribute.properties != null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (properties != null ? properties.hashCode() : 0);
+ return result;
+ }
+ }
+
+ public static Set<Attribute> parseHeader(String value, Reporter logger)
+ {
+ if ((value == null) || (value.trim().length() == 0)) {
+ return new TreeSet<Attribute>();
+ }
+ Set<Attribute> result = new TreeSet<Attribute>();
+ QuotedTokenizer qt = new QuotedTokenizer(value, ";=,");
+ char del = '\0';
+ do {
+ boolean hadAttribute = false;
+ Map<String,String> clause = Create.map();
+ List<String> aliases = Create.list();
+ String name = qt.nextToken(",;");
+
+ del = qt.getSeparator();
+ if ((name == null) || (name.length() == 0)) {
+ if ((logger != null) && (logger.isPedantic())) {
+ logger.warning("Empty clause, usually caused by repeating a comma without any name field or by having " +
+ "spaces after the backslash of a property file: " +
+ value);
+ }
+
+ if (name != null)
+ continue;
+ break;
+ }
+ name = name.trim();
+
+ aliases.add(name);
+ String advalue;
+ while (del == ';') {
+ String adname = qt.nextToken();
+ if ((del = qt.getSeparator()) != '=') {
+ if ((hadAttribute) && (logger != null)) {
+ logger.error("Header contains name field after attribute or directive: " +
+ adname +
+ " from " +
+ value +
+ ". Name fields must be consecutive, separated by a ';' like a;b;c;x=3;y=4");
+ }
+
+ if ((adname != null) && (adname.length() > 0))
+ aliases.add(adname.trim());
+ } else {
+ advalue = qt.nextToken();
+ if ((clause.containsKey(adname)) && (logger != null) && (logger.isPedantic())) {
+ logger.warning("Duplicate attribute/directive name " +
+ adname +
+ " in " +
+ value +
+ ". This attribute/directive will be ignored");
+ }
+
+ if (advalue == null) {
+ if (logger != null) {
+ logger.error("No value after '=' sign for attribute " + adname);
+ }
+ advalue = "";
+ }
+ clause.put(adname.trim(), advalue.trim());
+ del = qt.getSeparator();
+ hadAttribute = true;
+ }
+ }
+
+ for (String clauseName : aliases) {
+ result.add(new Attribute(clauseName, clause));
+ }
+ }
+ while (del == ',');
+ return result;
+ }
+
+}
diff --git a/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java b/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
index a9f8ed0..1ebffac 100644
--- a/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
+++ b/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
@@ -55,7 +55,6 @@
import org.apache.maven.project.MavenProjectHelper;
import org.apache.maven.shared.osgi.DefaultMaven2OsgiConverter;
import org.apache.maven.shared.osgi.Maven2OsgiConverter;
-import org.apache.felix.bnd.BlueprintComponent;
import org.codehaus.plexus.archiver.UnArchiver;
import org.codehaus.plexus.archiver.manager.ArchiverManager;
import org.codehaus.plexus.util.DirectoryScanner;
@@ -68,7 +67,6 @@
import aQute.lib.osgi.FileResource;
import aQute.lib.osgi.Jar;
import aQute.lib.spring.SpringXMLType;
-import aQute.lib.spring.JPAComponent;
/**
@@ -893,7 +891,8 @@
// Add default plugins
header( properties, Analyzer.PLUGIN,
- BlueprintComponent.class.getName() + "," + SpringXMLType.class.getName());
+ BlueprintPlugin.class.getName() + ","
+ + SpringXMLType.class.getName());
return properties;
}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
index 39e4048..01ec40c 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
@@ -207,8 +207,8 @@
ri.setFilter(createServiceFilter(entry));
ri.setComment("Import Service " + entry.getName());
- // TODO the following is arbitrary
- ri.setOptional(false);
+ String avail = entry.getDirective("availability");
+ ri.setOptional("optional".equals(avail));
ri.setMultiple(true);
resource.addRequirement(ri);
}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java
index b4bbf79..b7a4c4a 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java
@@ -87,8 +87,8 @@
attributes = new HashMap();
attributes.put(parameter.key, parameter.value);
if (parameter.key.equalsIgnoreCase("version")
- || parameter.key
- .equalsIgnoreCase("specification-version"))
+ || parameter.key.equalsIgnoreCase("specification-version")
+ || parameter.key.equalsIgnoreCase("bundle-version"))
this.version = new VersionRange(parameter.value);
break;
diff --git a/bundleplugin/src/main/resources/org/apache/felix/bnd/blueprint.xsl b/bundleplugin/src/main/resources/org/apache/felix/bnd/blueprint.xsl
deleted file mode 100644
index eb44e25..0000000
--- a/bundleplugin/src/main/resources/org/apache/felix/bnd/blueprint.xsl
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
--->
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0">
- <xsl:output method="text" />
-
- <xsl:template match="/">
-
- <!-- Match all attributes that holds a class or a comma delimited
- list of classes and print them -->
-
- <xsl:for-each select="
- //bp:bean/@class
- | //bp:service/@interface
- | //bp:service/bp:interfaces/bp:value/text()
- | //bp:reference/@interface
- | //bp:reference-list/@interface
- ">
- <xsl:value-of select="." />
- <xsl:text>
- </xsl:text>
- </xsl:for-each>
-
- <xsl:for-each select="
- //bp:bean/bp:argument/@type
- | //bp:list/@value-type
- | //bp:set/@value-type
- | //bp:array/@value-type
- | //bp:map/@key-type
- | //bp:map/@value-type
- ">
- <xsl:choose>
- <xsl:when test="contains(., '[')"><xsl:value-of select="substring-before(., '[')"/></xsl:when>
- <xsl:otherwise><xsl:value-of select="."/></xsl:otherwise>
- </xsl:choose>
- <xsl:text>
- </xsl:text>
- </xsl:for-each>
-
- </xsl:template>
-
-
-</xsl:stylesheet>
-
diff --git a/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/blueprint.xsl b/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/blueprint.xsl
new file mode 100644
index 0000000..49e0d8a
--- /dev/null
+++ b/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/blueprint.xsl
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <xsl:param name="nsh_interface" select="''"/>
+ <xsl:param name="nsh_namespace" select="''"/>
+ <xsl:output method="text" />
+
+ <xsl:template match="/">
+
+
+ <xsl:text>Import-Package:org.osgi.service.blueprint;version="[1.0.0,2.0.0)"
+ </xsl:text>
+
+ <xsl:if test="not($nsh_interface = '' or $nsh_namespace = '')">
+ <xsl:for-each select="descendant-or-self::node() | descendant-or-self::node()/attribute::*">
+ <xsl:if test="not(namespace-uri() = 'http://www.osgi.org/xmlns/blueprint/v1.0.0' or namespace-uri() = '')">
+ <xsl:value-of select="concat('Import-Service:', $nsh_interface, ';', $nsh_namespace, '=', namespace-uri())" />
+ <xsl:text>
+ </xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+
+ <xsl:for-each select="
+ //bp:bean/@class
+ | //bp:service/@interface
+ | //bp:service/bp:interfaces/bp:value/text()
+ | //bp:reference/@interface
+ | //bp:reference-list/@interface
+ ">
+ <xsl:value-of select="concat('Import-Class:', .)" />
+ <xsl:text>
+ </xsl:text>
+ </xsl:for-each>
+
+ <xsl:for-each select="
+ //bp:bean/bp:argument/@type
+ | //bp:list/@value-type
+ | //bp:set/@value-type
+ | //bp:array/@value-type
+ | //bp:map/@key-type
+ | //bp:map/@value-type
+ ">
+ <xsl:choose>
+ <xsl:when test="contains(., '[')"><xsl:value-of select="concat('Import-Class:', substring-before(., '['))"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="concat('Import-Class:', .)"/></xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>
+ </xsl:text>
+ </xsl:for-each>
+
+ <xsl:for-each select="//bp:service">
+ <xsl:choose>
+ <xsl:when test="@interface">
+ <xsl:value-of select="concat('Export-Service:', @interface)" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="bp:interfaces/bp:value/text()">
+ <xsl:value-of select="concat('Export-Service:', bp:interfaces/bp:value/text())" />
+ </xsl:when>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:for-each select="bp:service-properties/bp:entry">
+ <xsl:value-of select="concat(';', @key, '=', @value)" />
+ </xsl:for-each>
+ <xsl:text>
+ </xsl:text>
+ </xsl:for-each>
+
+ <xsl:for-each select="//bp:reference[@interface] | //bp:reference-list[@interface]">
+ <xsl:choose>
+ <xsl:when test="@availability">
+ <xsl:value-of select="concat('Import-Service:', @interface, ';availability:=', @availability)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="/bp:blueprint/@default-availability">
+ <xsl:value-of select="concat('Import-Service:', @interface, ';availability:=', /bp:blueprint/@default-availability)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('Import-Service:', @interface, ';availability:=mandatory')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>
+ </xsl:text>
+ </xsl:for-each>
+
+ </xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/bundleplugin/src/test/java/org/apache/felix/bnd/BlueprintComponentTest.java b/bundleplugin/src/test/java/org/apache/felix/bnd/BlueprintComponentTest.java
deleted file mode 100644
index 014610e..0000000
--- a/bundleplugin/src/test/java/org/apache/felix/bnd/BlueprintComponentTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bnd;
-
-import java.util.Set;
-
-import aQute.lib.spring.XMLType;
-import junit.framework.TestCase;
-
-public class BlueprintComponentTest extends TestCase {
-
- public void testPackages() throws Exception {
- XMLType t = new XMLType(getClass().getResource("blueprint.xsl"), null, ".*\\.xml");
- Set<String> s = t.analyze(getClass().getResourceAsStream("bp.xml"));
- assertEquals(14, s.size());
- assertTrue(s.contains("java.lang"));
- for (int i = 1; i <= 13; i++) {
- assertTrue(s.contains("p" + i));
- }
- }
-}
diff --git a/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java b/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java
new file mode 100644
index 0000000..8c9ac37
--- /dev/null
+++ b/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.bundleplugin;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.jar.Manifest;
+
+import aQute.lib.osgi.Builder;
+import aQute.lib.spring.XMLType;
+import junit.framework.TestCase;
+import org.apache.felix.bundleplugin.ManifestPlugin;
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
+import org.osgi.framework.Constants;
+
+public class BlueprintComponentTest extends TestCase {
+
+ public void testBlueprint() throws Exception
+ {
+
+ MavenProjectStub project = new MavenProjectStub() {
+ private final List resources = new ArrayList();
+ @Override
+ public void addResource(Resource resource) {
+ resources.add(resource);
+ }
+
+ @Override
+ public List getResources() {
+ return resources;
+ }
+ };
+ project.setGroupId( "group" );
+ project.setArtifactId( "artifact" );
+ project.setVersion( "1.1.0.0" );
+ Resource r = new Resource();
+ r.setDirectory(new File("src/test/resources").getAbsoluteFile().getCanonicalPath());
+ r.setIncludes(Arrays.asList("**/*.*"));
+ project.addResource(r);
+ project.addCompileSourceRoot(new File("src/test/resources").getAbsoluteFile().getCanonicalPath());
+
+ ManifestPlugin plugin = new ManifestPlugin();
+ plugin.setBasedir(new File("target/tmp/basedir"));
+ plugin.setBuildDirectory("target/tmp/basedir/target");
+ plugin.setOutputDirectory(new File("target/tmp/basedir/target/classes"));
+
+ Map instructions = new HashMap();
+ instructions.put("Test", "Foo");
+
+ instructions.put("nsh_interface", "foo.bar.Namespace");
+ instructions.put("nsh_namespace", "ns");
+
+ Properties props = new Properties();
+ Builder builder = plugin.buildOSGiBundle(project, instructions, props, plugin.getClasspath(project));
+
+ Manifest manifest = builder.getJar().getManifest();
+ String expSvc = manifest.getMainAttributes().getValue(Constants.EXPORT_SERVICE);
+ String impSvc = manifest.getMainAttributes().getValue(Constants.IMPORT_SERVICE);
+ assertNotNull(expSvc);
+ assertNotNull(impSvc);
+
+ String impPkg = manifest.getMainAttributes().getValue(Constants.IMPORT_PACKAGE);
+ List<String> pkgs = Arrays.asList(impPkg.split(","));
+ for (int i = 1; i <= 13; i++) {
+ assertTrue(pkgs.contains("p" + i));
+ }
+ }
+
+}
diff --git a/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java b/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java
index 581b28f..c9748e8 100644
--- a/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java
+++ b/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java
@@ -21,10 +21,21 @@
*/
import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Properties;
+import java.util.jar.Manifest;
+import org.apache.maven.model.Resource;
import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.osgi.DefaultMaven2OsgiConverter;
@@ -33,6 +44,9 @@
import aQute.lib.osgi.Analyzer;
import aQute.lib.osgi.Builder;
import aQute.lib.osgi.Jar;
+import org.osgi.framework.Constants;
+import org.osgi.impl.bundle.obr.resource.RepositoryImpl;
+import org.osgi.impl.bundle.obr.resource.BundleInfo;
/**
@@ -59,6 +73,10 @@
public void testConvertVersionToOsgi()
{
+ try {
+ new BundleInfo(new RepositoryImpl(new URL("file:.")), new File("/Users/gnodet/.m2/repository/org/apache/felix/karaf/webconsole/org.apache.felix.karaf.webconsole.branding/1.5.0-SNAPSHOT/org.apache.felix.karaf.webconsole.branding-1.5.0-SNAPSHOT.jar")).build();
+ } catch(Exception e ) {}
+
String osgiVersion;
osgiVersion = plugin.convertVersionToOsgi( "2.1.0-SNAPSHOT" );
@@ -195,4 +213,5 @@
String cleanupVersion = Builder.cleanupVersion( "0.0.0.4aug2000r7-dev" );
assertEquals( "0.0.0.4aug2000r7-dev", cleanupVersion );
}
+
}
diff --git a/bundleplugin/src/test/resources/OSGI-INF/blueprint/bp.xml b/bundleplugin/src/test/resources/OSGI-INF/blueprint/bp.xml
new file mode 100644
index 0000000..fe8d4f3
--- /dev/null
+++ b/bundleplugin/src/test/resources/OSGI-INF/blueprint/bp.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:tx="http://foo.bar/tx"
+ xmlns:t2="http://foo.bar/t2">
+
+ <type-converters>
+ <bean class="p1.Foo" t2:a="b">
+ <argument type="java.lang.Integer[]" value="0 1"/>
+ </bean>
+ </type-converters>
+
+ <bean class="p2.Foo">
+ <tx:transaction method="*" value="NotSupported"/>
+ <property name="bar">
+ <bean class="p3.Foo"/>
+ </property>
+ </bean>
+
+ <reference interface="p4.Foo" availability="optional"/>
+
+ <reference-list interface="p5.Foo">
+ </reference-list>
+
+ <service interface="p6.Foo">
+ <service-properties>
+ <entry key="k" value="v" />
+ </service-properties>
+ </service>
+
+ <service>
+ <interfaces>
+ <value>p7.Foo</value>
+ </interfaces>
+ <bean class="p8.Foo">
+ <argument type="p9.Foo[][]"><null/></argument>
+ <property name="bar">
+ <list value-type="p10.Foo">
+ <map key-type="p11.Foo" value-type="p12.Foo">
+ </map>
+ <set value-type="p13.Foo[]"/>
+ </list>
+ </property>
+ </bean>
+ </service>
+
+</blueprint>
diff --git a/bundleplugin/src/test/resources/org/apache/felix/bnd/bp.xml b/bundleplugin/src/test/resources/org/apache/felix/bnd/bp.xml
deleted file mode 100644
index ec74f7d..0000000
--- a/bundleplugin/src/test/resources/org/apache/felix/bnd/bp.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
- <type-converters>
- <bean class="p1.Foo">
- <argument type="java.lang.Integer[]" value="0 1"/>
- </bean>
- </type-converters>
-
- <bean class="p2.Foo">
- <property name="bar">
- <bean class="p3.Foo"/>
- </property>
- </bean>
-
- <reference interface="p4.Foo" />
-
- <reference-list interface="p5.Foo">
- </reference-list>
-
- <service interface="p6.Foo">
- </service>
-
- <service>
- <interfaces>
- <value>p7.Foo</value>
- </interfaces>
- <bean class="p8.Foo">
- <argument type="p9.Foo[][]"><null/></argument>
- <property name="bar">
- <list value-type="p10.Foo">
- <map key-type="p11.Foo" value-type="p12.Foo">
- </map>
- <set value-type="p13.Foo[]"/>
- </list>
- </property>
- </bean>
- </service>
-
-</blueprint>
\ No newline at end of file