felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gno...@apache.org
Subject svn commit: r1595765 - in /felix/trunk/bundleplugin: ./ src/main/java/org/apache/felix/bundleplugin/ src/main/resources/org/apache/felix/bundleplugin/ src/test/java/org/apache/felix/bundleplugin/
Date Mon, 19 May 2014 07:12:49 GMT
Author: gnodet
Date: Mon May 19 07:12:48 2014
New Revision: 1595765

URL: http://svn.apache.org/r1595765
Log:
[FELIX-4517] Generate generic capabilities and requirements for services from blueprint and
scr descriptors

Added:
    felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/ScrPlugin.java
    felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/scr.xsl
Modified:
    felix/trunk/bundleplugin/pom.xml
    felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java
    felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
    felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/blueprint.xsl
    felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java

Modified: felix/trunk/bundleplugin/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/pom.xml?rev=1595765&r1=1595764&r2=1595765&view=diff
==============================================================================
--- felix/trunk/bundleplugin/pom.xml (original)
+++ felix/trunk/bundleplugin/pom.xml Mon May 19 07:12:48 2014
@@ -70,6 +70,11 @@
     <version>1.6.6</version>
   </dependency>
   <dependency>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>org.apache.felix.utils</artifactId>
+    <version>1.6.0</version>
+  </dependency>
+  <dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-core</artifactId>
    <version>2.0.7</version>

Modified: 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=1595765&r1=1595764&r2=1595765&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java
(original)
+++ felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BlueprintPlugin.java
Mon May 19 07:12:48 2014
@@ -26,8 +26,11 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -39,6 +42,7 @@ import javax.xml.transform.TransformerFa
 import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 
+import aQute.bnd.header.Attrs;
 import aQute.bnd.service.AnalyzerPlugin;
 import aQute.bnd.osgi.Analyzer;
 import aQute.bnd.osgi.Descriptors.PackageRef;
@@ -48,6 +52,12 @@ import aQute.bnd.osgi.Resource;
 import aQute.libg.generics.Create;
 import aQute.libg.qtokens.QuotedTokenizer;
 import aQute.service.reporter.Reporter;
+import org.apache.felix.utils.manifest.Attribute;
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.manifest.Directive;
+import org.osgi.framework.Constants;
+
+import static org.apache.felix.utils.manifest.Parser.parseHeader;
 
 
 public class BlueprintPlugin implements AnalyzerPlugin
@@ -67,6 +77,11 @@ public class BlueprintPlugin implements 
 
     public boolean analyzeJar( Analyzer analyzer ) throws Exception
     {
+        String mode = analyzer.getProperty("service_mode");
+        if (mode == null) {
+            mode = "generic";
+        }
+
         transformer.setParameter( "nsh_interface",
             analyzer.getProperty( "nsh_interface" ) != null ? analyzer.getProperty( "nsh_interface"
) : "" );
         transformer.setParameter( "nsh_namespace",
@@ -114,7 +129,9 @@ public class BlueprintPlugin implements 
 		}
 
         // Group and analyze
-        Map<String, Set<Attribute>> hdrs = Create.map();
+        Set<String> caps = Create.set();
+        Set<String> reqs = Create.set();
+        Map<String, Set<Clause>> hdrs = Create.map();
         for ( String str : headers )
         {
             int idx = str.indexOf( ':' );
@@ -126,21 +143,137 @@ public class BlueprintPlugin implements 
             }
             String h = str.substring( 0, idx ).trim();
             String v = str.substring( idx + 1 ).trim();
-            Set<Attribute> att = hdrs.get( h );
-            if ( att == null )
+            Clause[] hc = parseHeader(v);
+            // Convert generic caps/reqs
+            if ("Import-Service".equals(h))
             {
-                att = new TreeSet<Attribute>();
-                hdrs.put( h, att );
+                if (!"service".equals(mode))
+                {
+                    Clause clause = hc[0];
+                    String multiple = clause.getDirective("multiple");
+                    String avail = clause.getDirective("availability");
+                    String filter = clause.getAttribute("filter");
+
+                    StringBuilder sb = new StringBuilder();
+                    sb.append("osgi.service;effective:=active;");
+                    if ("optional".equals(avail)) {
+                        sb.append("resolution:=optional;");
+                    }
+                    if ("true".equals(multiple)) {
+                        sb.append("cardinality:=multiple;");
+                    }
+                    if (filter == null) {
+                        filter = "(" + Constants.OBJECTCLASS + "=" + clause.getName() + ")";
+                    } else if (!filter.startsWith("(") && !filter.endsWith(")"))
{
+                        filter = "(&(" + Constants.OBJECTCLASS + "=" + clause.getName()
+ ")(" + filter + "))";
+                    } else {
+                        filter = "(&(" + Constants.OBJECTCLASS + "=" + clause.getName()
+ ")" + filter + ")";
+                    }
+                    sb.append("filter:=\"").append(filter).append("\"");
+                    reqs.add(sb.toString());
+                }
+                else if (!"generic".equals(mode))
+                {
+                    Set<Clause> clauses = hdrs.get(h);
+                    if (clauses == null) {
+                        clauses = new HashSet<Clause>();
+                        hdrs.put(h, clauses);
+                    }
+                    clauses.addAll(Arrays.asList(hc));
+                }
+            }
+            else if ("Export-Service".equals(h))
+            {
+                if (!"service".equals(mode))
+                {
+                    StringBuilder sb = new StringBuilder();
+                    sb.append("osgi.service;effective:=active;objectClass");
+                    if (hc.length > 1) {
+                        sb.append(":List<String>=\"");
+                    } else {
+                        sb.append("=\"");
+                    }
+                    for (int i = 0; i < hc.length; i++)
+                    {
+                        if (i > 0)
+                        {
+                            sb.append(",");
+                        }
+                        sb.append(hc[i].getName());
+                    }
+                    sb.append("\"");
+                    for (int i = 0; i < hc[0].getAttributes().length; i++)
+                    {
+                        sb.append(";");
+                        sb.append(hc[0].getAttributes()[i].getName());
+                        sb.append("=\"");
+                        sb.append(hc[0].getAttributes()[i].getValue());
+                        sb.append("\"");
+                    }
+                    caps.add(sb.toString());
+                }
+                else if (!"generic".equals(mode))
+                {
+                    Set<Clause> clauses = hdrs.get(h);
+                    if (clauses == null) {
+                        clauses = new HashSet<Clause>();
+                        hdrs.put(h, clauses);
+                    }
+                    clauses.addAll(Arrays.asList(hc));
+                }
+            }
+            else
+            {
+                Set<Clause> clauses = hdrs.get(h);
+                if (clauses == null)
+                {
+                    clauses = new HashSet<Clause>();
+                    hdrs.put(h, clauses);
+                }
+                clauses.addAll(Arrays.asList( hc ) );
             }
-            att.addAll( parseHeader( v, null ) );
+        }
+        if (!caps.isEmpty())
+        {
+            StringBuilder sb = new StringBuilder();
+            String header = analyzer.getProperty("Provide-Capability");
+            if (header != null)
+            {
+                sb.append(header);
+            }
+            for (String cap : caps) {
+                if (sb.length() > 0) {
+                    sb.append(",");
+                }
+                sb.append(cap);
+            }
+            System.err.println("Provide-Capability: " + sb.toString());
+            analyzer.setProperty("Provide-Capability", sb.toString());
+        }
+        if (!reqs.isEmpty())
+        {
+            StringBuilder sb = new StringBuilder();
+            String header = analyzer.getProperty("Require-Capability");
+            if (header != null)
+            {
+                sb.append(header);
+            }
+            for (String req : reqs) {
+                if (sb.length() > 0) {
+                    sb.append(",");
+                }
+                sb.append(req);
+            }
+            System.err.println("Require-Capability: " + sb.toString());
+            analyzer.setProperty("Require-Capability", sb.toString());
         }
         // 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 )
+                Set<Clause> newAttr = hdrs.get(header);
+                for ( Clause a : newAttr )
                 {
                     String pkg = a.getName();
                     if ( "Import-Class".equals( header ) )
@@ -158,50 +291,34 @@ public class BlueprintPlugin implements 
                     PackageRef pkgRef = analyzer.getPackageRef( pkg );
                     if ( !analyzer.getReferred().containsKey( pkgRef ) )
                     {
-                        analyzer.getReferred().put( pkgRef ).putAll( a.getProperties() );
+                        Attrs attrs = analyzer.getReferred().put(pkgRef);
+                        for (Attribute attribute : a.getAttributes())
+                        {
+                            attrs.put(attribute.getName(), attribute.getValue());
+                        }
                     }
                 }
             }
             else
             {
-                Set<Attribute> orgAttr = parseHeader( analyzer.getProperty( header
), null );
-                Set<Attribute> newAttr = hdrs.get( header );
-                for ( Iterator<Attribute> it = newAttr.iterator(); it.hasNext(); )
+                Set<String> merge = Create.set();
+                for (Clause clause : parseHeader(analyzer.getProperty(header)))
                 {
-                    Attribute a = it.next();
-                    for ( Attribute b : orgAttr )
-                    {
-                        if ( b.getName().equals( a.getName() ) )
-                        {
-                            it.remove();
-                            break;
-                        }
-                    }
+                    merge.add(clause.toString());
+                }
+                for (Clause clause : hdrs.get(header))
+                {
+                    merge.add(clause.toString());
                 }
-                orgAttr.addAll( newAttr );
-                // Rebuild from orgAttr
                 StringBuilder sb = new StringBuilder();
-                for ( Attribute a : orgAttr )
+                for (String clause : merge)
                 {
                     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( "=" );
-                        if ( prop.getValue().matches( "[0-9a-zA-Z_-]+" ) )
-                        {
-                            sb.append( prop.getValue() );
-                        }
-                        else
-                        {
-                            sb.append( "\"" );
-                            sb.append( prop.getValue().replace( "\"", "\\\"" ) );
-                            sb.append( "\"" );
-                        }
-                    }
+                    sb.append(clause);
+
                 }
                 analyzer.setProperty( header, sb.toString() );
             }
@@ -274,150 +391,4 @@ public class BlueprintPlugin implements 
         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=1595765&r1=1595764&r2=1595765&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
Mon May 19 07:12:48 2014
@@ -448,6 +448,11 @@ public class BundlePlugin extends Abstra
     {
         properties.putAll( getDefaultProperties( currentProject ) );
         properties.putAll( transformDirectives( originalInstructions ) );
+        if (properties.getProperty("Bundle-Activator") != null
+                && properties.getProperty("Bundle-Activator").isEmpty())
+        {
+            properties.remove("Bundle-Activator");
+        }
 
         Builder builder = new Builder();
         synchronized ( BundlePlugin.class ) // protect setBase...getBndLastModified which
uses static DateFormat 
@@ -1261,7 +1266,9 @@ public class BundlePlugin extends Abstra
         properties.put( "classifier", classifier == null ? "" : classifier );
 
         // Add default plugins
-        header( properties, Analyzer.PLUGIN, BlueprintPlugin.class.getName() + "," + SpringXMLType.class.getName()
);
+        header( properties, Analyzer.PLUGIN, ScrPlugin.class.getName() + ","
+                                           + BlueprintPlugin.class.getName() + ","
+                                           + SpringXMLType.class.getName() );
 
         return properties;
     }

Added: felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/ScrPlugin.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/ScrPlugin.java?rev=1595765&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/ScrPlugin.java (added)
+++ felix/trunk/bundleplugin/src/main/java/org/apache/felix/bundleplugin/ScrPlugin.java Mon
May 19 07:12:48 2014
@@ -0,0 +1,173 @@
+/*
+ * 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.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.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+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.osgi.Analyzer;
+import aQute.bnd.osgi.Descriptors.PackageRef;
+import aQute.bnd.osgi.Jar;
+import aQute.bnd.osgi.Processor;
+import aQute.bnd.osgi.Resource;
+import aQute.bnd.service.AnalyzerPlugin;
+import aQute.libg.generics.Create;
+import org.apache.felix.utils.manifest.Attribute;
+import org.apache.felix.utils.manifest.Clause;
+import org.osgi.framework.Constants;
+
+import static org.apache.felix.utils.manifest.Parser.parseHeader;
+
+
+public class ScrPlugin implements AnalyzerPlugin
+{
+
+    Transformer transformer;
+
+    public ScrPlugin() throws Exception
+    {
+        transformer = getTransformer( getClass().getResource( "scr.xsl" ) );
+    }
+
+
+    public boolean analyzeJar( Analyzer analyzer ) throws Exception
+    {
+        Set<String> headers = Create.set();
+
+        String bpHeader = analyzer.getProperty( "Service-Component" );
+
+        Map<String, ? extends Map<String, String>> map = Processor.parseHeader(
bpHeader, null );
+        for ( String root : map.keySet() )
+        {
+            Resource resource = analyzer.getJar().getResource(root);
+            if ( resource != null ) {
+                process(analyzer, root, resource, headers);
+            }
+        }
+
+        // Group and analyze
+        for ( String str : headers )
+        {
+            int idx = str.indexOf( ':' );
+            if ( idx < 0 )
+            {
+                analyzer.warning( ( new StringBuilder( "Error analyzing services in scr resource:
" ) ).append( str ).toString() );
+                continue;
+            }
+            String h = str.substring( 0, idx ).trim();
+            String v = str.substring( idx + 1 ).trim();
+
+            StringBuilder sb = new StringBuilder();
+            String header = analyzer.getProperty( h );
+            if (header != null && !header.isEmpty())
+            {
+                sb.append(header);
+                sb.append(",");
+            }
+            sb.append( v );
+            analyzer.setProperty(h, 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 scr
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();
+            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 );
+    }
+
+}

Modified: 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=1595765&r1=1595764&r2=1595765&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/blueprint.xsl
(original)
+++ felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/blueprint.xsl
Mon May 19 07:12:48 2014
@@ -68,7 +68,7 @@
 			</xsl:text>
 		</xsl:for-each>
 
-        <xsl:for-each select="//bp:service">
+        <xsl:for-each select="//bp:service[@interface or bp:interfaces/bp:value]">
             <xsl:choose>
                 <xsl:when test="@interface">
                     <xsl:value-of select="concat('Export-Service:', @interface)" />
@@ -76,7 +76,13 @@
                 <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:value-of select="'Export-Service:'" />
+                            <xsl:for-each select="bp:interfaces/bp:value/text()">
+                                <xsl:value-of select="."/>
+                                <xsl:if test="position() != last()">
+                                    <xsl:value-of select="';'" />
+                                </xsl:if>
+                            </xsl:for-each>
                         </xsl:when>
                     </xsl:choose>
                 </xsl:otherwise>

Added: felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/scr.xsl
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/scr.xsl?rev=1595765&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/scr.xsl (added)
+++ felix/trunk/bundleplugin/src/main/resources/org/apache/felix/bundleplugin/scr.xsl Mon
May 19 07:12:48 2014
@@ -0,0 +1,77 @@
+<?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:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
+    <xsl:output method="text" />
+
+    <xsl:template match="/">
+
+        <xsl:for-each select="//scr:component[service/provide/@interface]">
+            <xsl:value-of select="'Provide-Capability: osgi.service;effective:=active;'"
/>
+            <xsl:choose>
+                <xsl:when test="count(service/provide/@interface) = 1">
+                    <xsl:value-of select="'objectClass=&quot;'" />
+                    <xsl:value-of select="service/provide/@interface"/>
+                    <xsl:value-of select="'&quot;'" />
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:value-of select="'objectClass:List&lt;String&gt;=&quot;'"
/>
+                    <xsl:for-each select="service/provide/@interface">
+                        <xsl:value-of select="."/>
+                        <xsl:if test="position() != last()">
+                            <xsl:value-of select="','" />
+                        </xsl:if>
+                    </xsl:for-each>
+                    <xsl:value-of select="'&quot;'" />
+                </xsl:otherwise>
+            </xsl:choose>
+            <xsl:for-each select="property[@name != 'service.pid' and @value and not(contains(@value,
'$'))]">
+                <xsl:value-of select="';'" />
+                <xsl:value-of select="@name"/>
+                <xsl:value-of select="'=&quot;'" />
+                <xsl:value-of select="@value"/>
+                <xsl:value-of select="'&quot;'" />
+            </xsl:for-each>
+            <xsl:text>
+            </xsl:text>
+        </xsl:for-each>
+
+        <xsl:for-each select="//scr:component/reference">
+            <xsl:value-of select="'Require-Capability: osgi.service;effective:=active;
'" />
+            <xsl:choose>
+                <xsl:when test="@cardinality = '0..1' or @cardinality = '0..n'">
+                    <xsl:value-of select="'resolution:=optional;'" />
+                </xsl:when>
+            </xsl:choose>
+            <xsl:choose>
+                <xsl:when test="@target">
+                    <xsl:value-of select="concat('filter:=&quot;(&amp;(objectClass=',
@interface, ')', @target, ')&quot;')"/>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:value-of select="concat('filter:=&quot;(objectClass=', @interface,
')&quot;')"/>
+                </xsl:otherwise>
+            </xsl:choose>
+            <xsl:text>
+            </xsl:text>
+        </xsl:for-each>
+
+    </xsl:template>
+
+</xsl:stylesheet>
+

Modified: 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=1595765&r1=1595764&r2=1595765&view=diff
==============================================================================
--- felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java
(original)
+++ felix/trunk/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java
Mon May 19 07:12:48 2014
@@ -28,8 +28,11 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.jar.Manifest;
 
+import aQute.libg.generics.Create;
 import junit.framework.TestCase;
 
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.manifest.Parser;
 import org.apache.maven.model.Resource;
 import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
 import org.osgi.framework.Constants;
@@ -81,6 +84,7 @@ public class BlueprintComponentTest exte
         plugin.setOutputDirectory( new File( "target/tmp/basedir/target/classes" ) );
 
         Map instructions = new HashMap();
+        instructions.put( "service_mode", "service" );
         instructions.put( "Test", "Foo" );
 
         instructions.put( "nsh_interface", "foo.bar.Namespace" );
@@ -99,7 +103,11 @@ public class BlueprintComponentTest exte
         assertNotNull( impSvc );
 
         String impPkg = manifest.getMainAttributes().getValue( Constants.IMPORT_PACKAGE );
-        List<String> pkgs = Arrays.asList( impPkg.split( "," ) );
+        List<String> pkgs = Create.list();
+        for (Clause clause : Parser.parseHeader(impPkg))
+        {
+            pkgs.add(clause.getName());
+        }
         for ( int i = 1; i <= 13; i++ )
         {
             assertTrue( pkgs.contains( "p" + i ) );



Mime
View raw message