You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by gn...@apache.org on 2010/03/10 18:40:46 UTC

svn commit: r921470 - in /felix/trunk/bundleplugin/src: main/java/org/apache/felix/bnd/ main/java/org/apache/felix/bundleplugin/ main/java/org/osgi/impl/bundle/obr/resource/ main/resources/org/apache/felix/bnd/ main/resources/org/apache/felix/bundleplu...

Author: gnodet
Date: Wed Mar 10 17:40:45 2010
New Revision: 921470

URL: http://svn.apache.org/viewvc?rev=921470&view=rev
Log:
FELIX-2175: Improve the Blueprint component to parse / introspect blueprint configuration files and generate OBR service requirements / capabilities accordingly

Added:
    felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java
    felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/
    felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/blueprint.xsl
    felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java
    felix/trunk/bundleplugin/src/test/resources/OSGI-INF/
    felix/trunk/bundleplugin/src/test/resources/OSGI-INF/blueprint/
    felix/trunk/bundleplugin/src/test/resources/OSGI-INF/blueprint/bp.xml
Removed:
    felix/trunk/bundleplugin/src/main/java/org/apache/felix/bnd/BlueprintComponent.java
    felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bnd/blueprint.xsl
    felix/trunk/bundleplugin/src/test/java/org/apache/felix/bnd/BlueprintComponentTest.java
    felix/trunk/bundleplugin/src/test/resources/org/apache/felix/bnd/bp.xml
Modified:
    felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
    felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java
    felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java

Added: felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java?rev=921470&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java (added)
+++ felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java Wed Mar 10 17:40:45 2010
@@ -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;
+    }
+
+}

Modified: felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java?rev=921470&r1=921469&r2=921470&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java (original)
+++ felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java Wed Mar 10 17:40:45 2010
@@ -55,7 +55,6 @@ import org.apache.maven.project.MavenPro
 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.EmbeddedResource;
 import aQute.lib.osgi.FileResource;
 import aQute.lib.osgi.Jar;
 import aQute.lib.spring.SpringXMLType;
-import aQute.lib.spring.JPAComponent;
 
 
 /**
@@ -893,7 +891,8 @@ public class BundlePlugin extends Abstra
 
         // Add default plugins
         header( properties, Analyzer.PLUGIN,
-                BlueprintComponent.class.getName() + "," + SpringXMLType.class.getName());
+                    BlueprintPlugin.class.getName() + ","
+                        + SpringXMLType.class.getName());
 
         return properties;
     }

Modified: felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java?rev=921470&r1=921469&r2=921470&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java (original)
+++ felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java Wed Mar 10 17:40:45 2010
@@ -207,8 +207,8 @@ public class BundleInfo {
 				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);
 			}

Modified: felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java?rev=921470&r1=921469&r2=921470&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java (original)
+++ felix/trunk/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java Wed Mar 10 17:40:45 2010
@@ -87,8 +87,8 @@ public class ManifestEntry implements Co
 					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;
 

Added: felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/blueprint.xsl
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/blueprint.xsl?rev=921470&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/blueprint.xsl (added)
+++ felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/blueprint.xsl Wed Mar 10 17:40:45 2010
@@ -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>
+

Added: felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java?rev=921470&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java (added)
+++ felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java Wed Mar 10 17:40:45 2010
@@ -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));
+        }
+    }
+
+}

Modified: felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java?rev=921470&r1=921469&r2=921470&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java (original)
+++ felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java Wed Mar 10 17:40:45 2010
@@ -21,10 +21,21 @@ package org.apache.felix.bundleplugin;
  */
 
 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 org.apache.maven.model.Organizati
 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 class BundlePluginTest extends Ab
 
     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 @@ public class BundlePluginTest extends Ab
         String cleanupVersion = Builder.cleanupVersion( "0.0.0.4aug2000r7-dev" );
         assertEquals( "0.0.0.4aug2000r7-dev", cleanupVersion );
     }
+
 }

Added: felix/trunk/bundleplugin/src/test/resources/OSGI-INF/blueprint/bp.xml
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/test/resources/OSGI-INF/blueprint/bp.xml?rev=921470&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/test/resources/OSGI-INF/blueprint/bp.xml (added)
+++ felix/trunk/bundleplugin/src/test/resources/OSGI-INF/blueprint/bp.xml Wed Mar 10 17:40:45 2010
@@ -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>