You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by da...@apache.org on 2014/05/02 13:29:10 UTC

svn commit: r1591870 - in /felix/trunk/bundlerepository/src: main/java/org/apache/felix/bundlerepository/ main/java/org/apache/felix/bundlerepository/impl/ test/java/org/apache/felix/bundlerepository/impl/

Author: davidb
Date: Fri May  2 11:29:10 2014
New Revision: 1591870

URL: http://svn.apache.org/r1591870
Log:
[FELIX-4370] Additional work to support the OSGi Repository Service.

Added better support for directives.
This also fixes an OSGi Repository CT failure:
  RepositoryTest.testRepositoryContent2()
Also added a bunch of unit tests for areas not completely covered by the CT.


Added:
    felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/CapabilityImplTest.java
    felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/FelixRequirementAdapterTest.java
    felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/NamespaceTranslatorTest.java
    felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRequirementAdapterTest.java
Modified:
    felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java
    felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Requirement.java
    felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java
    felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixCapabilityAdapter.java
    felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixRequirementAdapter.java
    felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/NamespaceTranslator.java
    felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiCapabilityAdapter.java
    felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiRequirementAdapter.java
    felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java
    felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SpecXMLPullParser.java

Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java?rev=1591870&r1=1591869&r2=1591870&view=diff
==============================================================================
--- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java (original)
+++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java Fri May  2 11:29:10 2014
@@ -74,4 +74,12 @@ public interface Capability
      * @return a Map<String,Object>
      */
     Map<String, Object> getPropertiesAsMap();
+
+    /**
+     * Return the directives of this capability. The returned map
+     * can not be modified.
+     *
+     * @return a Map of directives or an empty map there are no directives.
+     */
+    Map<String, String> getDirectives();
 }
\ No newline at end of file

Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Requirement.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Requirement.java?rev=1591870&r1=1591869&r2=1591870&view=diff
==============================================================================
--- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Requirement.java (original)
+++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Requirement.java Fri May  2 11:29:10 2014
@@ -35,10 +35,12 @@
  */
 
 // This document is an experimental draft to enable interoperability
-// between bundle repositories. There is currently no commitment to 
-// turn this draft into an official specification.  
+// between bundle repositories. There is currently no commitment to
+// turn this draft into an official specification.
 package org.apache.felix.bundlerepository;
 
+import java.util.Map;
+
 /**
  * A named requirement specifies the need for certain capabilities with the same
  * name.
@@ -48,11 +50,26 @@ package org.apache.felix.bundlerepositor
  *   <li>they have the same nsame</li>
  *   <li>the filter matches the capability properties</li>
  * </ul>
- * 
+ *
  * @version $Revision: 1.4 $
  */
 public interface Requirement
 {
+    /**
+     * Return a map of attributes. Requirements can have attributes, but these are not
+     * used for matching. They are for informational purposes only.
+     *
+     * @return The map of attributes.
+     */
+    Map<String, Object> getAttributes();
+
+    /**
+     * Return the map of directives for this requirement. This requirements map does *not*
+     * contain requirements that are modeled via direct APIs on this interface, such as the
+     * filter, cardinality and resolution.
+     * @return
+     */
+    Map<String, String> getDirectives();
 
     /**
      * Return the name of the requirement.

Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java?rev=1591870&r1=1591869&r2=1591870&view=diff
==============================================================================
--- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java (original)
+++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java Fri May  2 11:29:10 2014
@@ -19,6 +19,7 @@
 package org.apache.felix.bundlerepository.impl;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -29,8 +30,9 @@ import org.apache.felix.bundlerepository
 public class CapabilityImpl implements Capability
 {
     private String m_name = null;
-    private final Map<String, Object> m_map = new HashMap<String, Object>();
-    private final List<Property> m_list = new ArrayList<Property>();
+    private final Map<String, Object> m_attributes = new HashMap<String, Object>();
+    private final Map<String, String> m_directives = new HashMap<String, String>();
+    private final List<Property> m_propList = new ArrayList<Property>();
 
     public CapabilityImpl()
     {
@@ -62,12 +64,12 @@ public class CapabilityImpl implements C
 
     public Map<String, Object> getPropertiesAsMap()
     {
-        return m_map;
+        return m_attributes;
     }
 
     public Property[] getProperties()
     {
-        return m_list.toArray(new Property[m_list.size()]);
+        return m_propList.toArray(new Property[m_propList.size()]);
     }
 
     public void addProperty(Property prop)
@@ -75,8 +77,8 @@ public class CapabilityImpl implements C
         // m_map.put(prop.getName().toLowerCase(), prop.getConvertedValue()); // TODO is toLowerCase() on the key the right thing to do?
         // However if we definitely need to re-enable the to-lowercasing, the Felix Util FilterImpl supports treating filters
         // case-insensitively
-        m_map.put(prop.getName(), prop.getConvertedValue());
-        m_list.add(prop);
+        m_attributes.put(prop.getName(), prop.getConvertedValue());
+        m_propList.add(prop);
     }
 
     public void addProperty(String name, String value)
@@ -91,6 +93,14 @@ public class CapabilityImpl implements C
 
     public String toString()
     {
-        return m_name  + ":" + m_map.toString();
+        return m_name  + ":" + m_attributes.toString();
+    }
+
+    public void addDirective(String key, String value) {
+        m_directives.put(key, value);
+    }
+
+    public Map<String, String> getDirectives() {
+        return Collections.unmodifiableMap(m_directives);
     }
 }
\ No newline at end of file

Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixCapabilityAdapter.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixCapabilityAdapter.java?rev=1591870&r1=1591869&r2=1591870&view=diff
==============================================================================
--- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixCapabilityAdapter.java (original)
+++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixCapabilityAdapter.java Fri May  2 11:29:10 2014
@@ -13,7 +13,6 @@
  */
 package org.apache.felix.bundlerepository.impl;
 
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -80,7 +79,7 @@ public class FelixCapabilityAdapter impl
 
     public Map<String, String> getDirectives()
     {
-        return Collections.emptyMap();
+        return capability.getDirectives();
     }
 
     public String getNamespace()

Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixRequirementAdapter.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixRequirementAdapter.java?rev=1591870&r1=1591869&r2=1591870&view=diff
==============================================================================
--- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixRequirementAdapter.java (original)
+++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FelixRequirementAdapter.java Fri May  2 11:29:10 2014
@@ -36,12 +36,12 @@ public class FelixRequirementAdapter imp
             throw new NullPointerException("Missing required parameter: resource");
         this.requirement = requirement;
         this.resource = resource;
-        directives = computeDirectives();
+        this.directives = computeDirectives();
     }
 
     public Map<String, Object> getAttributes()
     {
-        return Collections.emptyMap();
+        return requirement.getAttributes();
     }
 
     public Map<String, String> getDirectives()
@@ -66,20 +66,35 @@ public class FelixRequirementAdapter imp
 
     private Map<String, String> computeDirectives()
     {
-        Map<String, String> result = new HashMap<String, String>(3);
+        Map<String, String> result;
+        if (requirement.getDirectives() == null)
+            result = new HashMap<String, String>();
+        else
+            result = new HashMap<String, String>(requirement.getDirectives());
+
         /*
          * (1) The Felix OBR specific "mandatory:<*" syntax must be stripped out
-         * of the filter. (2) The namespace must be translated.
+         * of the filter.
+         * (2) service references removed
+         * (3) objectClass capitalised
+         * (4) The namespaces must be translated.
          */
-        result.put(
-                Namespace.REQUIREMENT_FILTER_DIRECTIVE,
-                requirement.getFilter().replaceAll("\\(mandatory\\:\\<\\*[^\\)]*\\)", "")
-                        .replaceAll("\\(service\\=[^\\)]*\\)", "").replaceAll("objectclass", "objectClass")
-                        .replaceAll(requirement.getName() + '=', getNamespace() + '='));
-        result.put(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE, requirement.isOptional() ? Namespace.RESOLUTION_OPTIONAL
-                : Namespace.RESOLUTION_MANDATORY);
-        result.put(Namespace.REQUIREMENT_CARDINALITY_DIRECTIVE, requirement.isMultiple() ? Namespace.CARDINALITY_MULTIPLE
-                : Namespace.CARDINALITY_SINGLE);
+        String filter = requirement.getFilter().replaceAll("\\(mandatory\\:\\<\\*[^\\)]*\\)", "")
+                .replaceAll("\\(service\\=[^\\)]*\\)", "").replaceAll("objectclass", "objectClass");
+
+        for (String ns : NamespaceTranslator.getTranslatedFelixNamespaces())
+        {
+            filter = filter.replaceAll("[(][ ]*" + ns + "[ ]*=",
+                "(" + NamespaceTranslator.getOSGiNamespace(ns) + "=");
+        }
+        result.put(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter);
+
+        if (requirement.isOptional())
+            result.put(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE, Namespace.RESOLUTION_OPTIONAL);
+
+        if (requirement.isMultiple())
+            result.put(Namespace.REQUIREMENT_CARDINALITY_DIRECTIVE, Namespace.CARDINALITY_MULTIPLE);
+
         return Collections.unmodifiableMap(result);
     }
 

Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/NamespaceTranslator.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/NamespaceTranslator.java?rev=1591870&r1=1591869&r2=1591870&view=diff
==============================================================================
--- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/NamespaceTranslator.java (original)
+++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/NamespaceTranslator.java Fri May  2 11:29:10 2014
@@ -13,6 +13,8 @@
  */
 package org.apache.felix.bundlerepository.impl;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -33,7 +35,7 @@ class NamespaceTranslator
         result.put(ServiceNamespace.SERVICE_NAMESPACE, org.apache.felix.bundlerepository.Capability.SERVICE);
         result.put(BundleNamespace.BUNDLE_NAMESPACE, org.apache.felix.bundlerepository.Capability.BUNDLE);
         result.put(HostNamespace.HOST_NAMESPACE, org.apache.felix.bundlerepository.Capability.FRAGMENT);
-        return result;
+        return Collections.unmodifiableMap(result);
     }
 
     private static Map<String, String> fillFelixToOSGiMap()
@@ -43,7 +45,7 @@ class NamespaceTranslator
         result.put(org.apache.felix.bundlerepository.Capability.SERVICE, ServiceNamespace.SERVICE_NAMESPACE);
         result.put(org.apache.felix.bundlerepository.Capability.BUNDLE, BundleNamespace.BUNDLE_NAMESPACE);
         result.put(org.apache.felix.bundlerepository.Capability.FRAGMENT, HostNamespace.HOST_NAMESPACE);
-        return result;
+        return Collections.unmodifiableMap(result);
     }
 
     public static String getFelixNamespace(String osgiNamespace)
@@ -55,6 +57,11 @@ class NamespaceTranslator
             return result;
     }
 
+    public static Collection<String> getTranslatedFelixNamespaces()
+    {
+        return felixToOSGiMap.keySet();
+    }
+
     public static String getOSGiNamespace(String felixNamespace)
     {
         String result = felixToOSGiMap.get(felixNamespace);
@@ -63,4 +70,9 @@ class NamespaceTranslator
         else
             return result;
     }
+
+    public static Collection<String> getTranslatedOSGiNamespaces()
+    {
+        return osgiToFelixMap.keySet();
+    }
 }

Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiCapabilityAdapter.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiCapabilityAdapter.java?rev=1591870&r1=1591869&r2=1591870&view=diff
==============================================================================
--- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiCapabilityAdapter.java (original)
+++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiCapabilityAdapter.java Fri May  2 11:29:10 2014
@@ -15,6 +15,7 @@ package org.apache.felix.bundlerepositor
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -64,6 +65,10 @@ public class OSGiCapabilityAdapter imple
         return result;
     }
 
+    public Map<String, String> getDirectives() {
+        return Collections.unmodifiableMap(capability.getDirectives());
+    }
+
     @Override
     public int hashCode()
     {

Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiRequirementAdapter.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiRequirementAdapter.java?rev=1591870&r1=1591869&r2=1591870&view=diff
==============================================================================
--- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiRequirementAdapter.java (original)
+++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/OSGiRequirementAdapter.java Fri May  2 11:29:10 2014
@@ -13,6 +13,9 @@
  */
 package org.apache.felix.bundlerepository.impl;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.felix.bundlerepository.Capability;
 import org.apache.felix.bundlerepository.Requirement;
 import org.osgi.framework.Constants;
@@ -21,10 +24,40 @@ import org.osgi.resource.Namespace;
 class OSGiRequirementAdapter implements Requirement
 {
     private final org.osgi.resource.Requirement requirement;
+    private final HashMap<String, String> cleanedDirectives;
+    private final String filter;
 
     public OSGiRequirementAdapter(org.osgi.resource.Requirement requirement)
     {
         this.requirement = requirement;
+
+        String f = requirement.getDirectives().get(Constants.FILTER_DIRECTIVE);
+        if (f != null)
+        {
+            for (String ns : NamespaceTranslator.getTranslatedOSGiNamespaces())
+            {
+                f = f.replaceAll("[(][ ]*" + ns + "[ ]*=",
+                    "(" + NamespaceTranslator.getFelixNamespace(ns) + "=");
+            }
+        }
+        filter = f;
+
+        cleanedDirectives = new HashMap<String, String>(requirement.getDirectives());
+        // Remove directives that are represented as APIs on this class.
+        cleanedDirectives.remove(Constants.FILTER_DIRECTIVE);
+        cleanedDirectives.remove(Namespace.REQUIREMENT_CARDINALITY_DIRECTIVE);
+        cleanedDirectives.remove(Constants.RESOLUTION_DIRECTIVE);
+    }
+
+    public Map<String, Object> getAttributes()
+    {
+        return requirement.getAttributes();
+    }
+
+    public Map<String, String> getDirectives()
+    {
+
+        return cleanedDirectives;
     }
 
     public String getComment()
@@ -34,7 +67,7 @@ class OSGiRequirementAdapter implements 
 
     public String getFilter()
     {
-        return requirement.getDirectives().get(Constants.FILTER_DIRECTIVE);
+        return filter;
     }
 
     public String getName()

Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java?rev=1591870&r1=1591869&r2=1591870&view=diff
==============================================================================
--- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java (original)
+++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java Fri May  2 11:29:10 2014
@@ -18,6 +18,8 @@
  */
 package org.apache.felix.bundlerepository.impl;
 
+import java.util.Collections;
+import java.util.Map;
 import java.util.regex.Pattern;
 
 import org.apache.felix.bundlerepository.Capability;
@@ -37,16 +39,37 @@ public class RequirementImpl implements 
     private boolean m_optional = false;
     private FilterImpl m_filter = null;
     private String m_comment = null;
+    private Map<String, Object> m_attributes;
+    private Map<String, String> m_directives;
 
     public RequirementImpl()
     {
     }
 
-    public RequirementImpl(String name) 
+    public RequirementImpl(String name)
     {
         setName(name);
     }
 
+    public Map<String, Object> getAttributes()
+    {
+        return m_attributes;
+    }
+
+    public void setAttributes(Map<String, Object> attributes) {
+        m_attributes = Collections.unmodifiableMap(attributes);
+    }
+
+    public Map<String, String> getDirectives()
+    {
+        return m_directives;
+    }
+
+    public void setDirectives(Map<String, String> directives)
+    {
+        m_directives = Collections.unmodifiableMap(directives);
+    }
+
     public String getName()
     {
         return m_name;

Modified: felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SpecXMLPullParser.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SpecXMLPullParser.java?rev=1591870&r1=1591869&r2=1591870&view=diff
==============================================================================
--- felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SpecXMLPullParser.java (original)
+++ felix/trunk/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SpecXMLPullParser.java Fri May  2 11:29:10 2014
@@ -139,12 +139,17 @@ public class SpecXMLPullParser
 
         capability.setName(NamespaceTranslator.getFelixNamespace(namespace));
         Map<String, Object> attributes = new HashMap<String, Object>();
-        parseAttributesDirectives(reader, attributes, CAPABILITY);
+        Map<String, String> directives = new HashMap<String, String>();
+        parseAttributesDirectives(reader, attributes, directives, CAPABILITY);
 
         for (Map.Entry<String, Object> entry : attributes.entrySet())
         {
             capability.addProperty(new FelixPropertyAdapter(entry.getKey(), entry.getValue()));
         }
+        for (Map.Entry<String, String> entry : directives.entrySet())
+        {
+            capability.addDirective(entry.getKey(), entry.getValue());
+        }
 
         return capability;
     }
@@ -152,7 +157,8 @@ public class SpecXMLPullParser
     private static void parseIdentityNamespace(XmlPullParser reader, ResourceImpl resource) throws Exception
     {
         Map<String, Object> attributes = new HashMap<String, Object>();
-        parseAttributesDirectives(reader, attributes, CAPABILITY);
+        parseAttributesDirectives(reader, attributes, new HashMap<String, String>(), CAPABILITY);
+        // TODO need to cater for the singleton directive...
 
         for (Map.Entry<String, Object> entry : attributes.entrySet())
         {
@@ -166,7 +172,7 @@ public class SpecXMLPullParser
     private static void parseContentNamespace(XmlPullParser reader, ResourceImpl resource) throws Exception
     {
         Map<String, Object> attributes = new HashMap<String, Object>();
-        parseAttributesDirectives(reader, attributes, CAPABILITY);
+        parseAttributesDirectives(reader, attributes, new HashMap<String, String>(), CAPABILITY);
 
         for (Map.Entry<String, Object> entry : attributes.entrySet())
         {
@@ -180,7 +186,7 @@ public class SpecXMLPullParser
         }
     }
 
-    private static void parseAttributesDirectives(XmlPullParser reader, Map<String, Object> attributes, String parentTag) throws XmlPullParserException, IOException
+    private static void parseAttributesDirectives(XmlPullParser reader, Map<String, Object> attributes, Map<String, String> directives, String parentTag) throws XmlPullParserException, IOException
     {
         int event;
         while ((event = reader.nextTag()) == XmlPullParser.START_TAG)
@@ -194,6 +200,13 @@ public class SpecXMLPullParser
                 attributes.put(name, getTypedValue(type, value));
                 PullParser.sanityCheckEndElement(reader, reader.nextTag(), ATTRIBUTE);
             }
+            else if (DIRECTIVE.equals(element))
+            {
+                String name = reader.getAttributeValue(null, "name");
+                String value = reader.getAttributeValue(null, "value");
+                directives.put(name, value);
+                PullParser.sanityCheckEndElement(reader, reader.nextTag(), DIRECTIVE);
+            }
             else
             {
                 PullParser.ignoreTag(reader);
@@ -304,33 +317,26 @@ public class SpecXMLPullParser
 
         requirement.setName(NamespaceTranslator.getFelixNamespace(namespace));
 
+        Map<String, Object> attributes = new HashMap<String, Object>();
         Map<String, String> directives = new HashMap<String, String>();
-        int event;
-        while ((event = reader.nextTag()) == XmlPullParser.START_TAG)
+        parseAttributesDirectives(reader, attributes, directives, REQUIREMENT);
+        requirement.setAttributes(attributes);
+
+        String filter = directives.remove(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
+        for (String ns : NamespaceTranslator.getTranslatedOSGiNamespaces())
         {
-            String element = reader.getName();
-            if (DIRECTIVE.equals(element))
-            {
-                String name = reader.getAttributeValue(null, "name");
-                String value = reader.getAttributeValue(null, "value");
-                directives.put(name, value);
-                PullParser.sanityCheckEndElement(reader, reader.nextTag(), DIRECTIVE);
-            }
-            else
-            {
-                PullParser.ignoreTag(reader);
-            }
+            filter = filter.replaceAll("[(][ ]*" + ns + "[ ]*=",
+                    "(" + NamespaceTranslator.getFelixNamespace(ns) + "=");
         }
-
-        requirement.setExtend(false);
-        // TODO transform the namespaces in the filter!
-        requirement.setFilter(directives.get(Namespace.REQUIREMENT_FILTER_DIRECTIVE));
+        requirement.setFilter(filter);
         requirement.setMultiple(Namespace.CARDINALITY_MULTIPLE.equals(
-            directives.get(Namespace.REQUIREMENT_CARDINALITY_DIRECTIVE)));
+            directives.remove(Namespace.REQUIREMENT_CARDINALITY_DIRECTIVE)));
         requirement.setOptional(Namespace.RESOLUTION_OPTIONAL.equals(
-            directives.get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE)));
+            directives.remove(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE)));
+        requirement.setDirectives(directives);
+
+        requirement.setExtend(false);
 
-        PullParser.sanityCheckEndElement(reader, event, REQUIREMENT);
         return requirement;
     }
 }

Added: felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/CapabilityImplTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/CapabilityImplTest.java?rev=1591870&view=auto
==============================================================================
--- felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/CapabilityImplTest.java (added)
+++ felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/CapabilityImplTest.java Fri May  2 11:29:10 2014
@@ -0,0 +1,48 @@
+/*
+ * 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.bundlerepository.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+public class CapabilityImplTest extends TestCase
+{
+    public void testDirectives()
+    {
+        CapabilityImpl c = new CapabilityImpl();
+
+        assertEquals(0, c.getDirectives().size());
+        c.addDirective("x", "y");
+        assertEquals(1, c.getDirectives().size());
+        assertEquals("y", c.getDirectives().get("x"));
+
+        c.addDirective("x", "z");
+        assertEquals(1, c.getDirectives().size());
+        assertEquals("z", c.getDirectives().get("x"));
+
+        c.addDirective("Y", "A b C");
+
+        Map<String, String> expected = new HashMap<String, String>();
+        expected.put("x", "z");
+        expected.put("Y", "A b C");
+        assertEquals(expected, c.getDirectives());
+    }
+}

Added: felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/FelixRequirementAdapterTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/FelixRequirementAdapterTest.java?rev=1591870&view=auto
==============================================================================
--- felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/FelixRequirementAdapterTest.java (added)
+++ felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/FelixRequirementAdapterTest.java Fri May  2 11:29:10 2014
@@ -0,0 +1,73 @@
+/*
+ * 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.bundlerepository.impl;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+public class FelixRequirementAdapterTest extends TestCase
+{
+    public void testDirectiveTranslation()
+    {
+        assertFilter("(foo=bar)", "(foo=bar)");
+        assertFilter("(package=x.y.z)", "(osgi.wiring.package=x.y.z)");
+        // TODO should this be symbolicname?
+        assertFilter("( bundle = abc  )", "(osgi.wiring.bundle= abc  )");
+        assertFilter("(|(bundle=x)(&(bundle=y)(fragment=z)))",
+                "(|(osgi.wiring.bundle=x)(&(osgi.wiring.bundle=y)(osgi.wiring.host=z)))");
+    }
+
+    private void assertFilter(String obr, String osgi)
+    {
+        Resource resource = new OSGiResourceImpl(
+            Collections.<Capability>emptyList(),
+            Collections.<Requirement>emptyList());
+
+        RequirementImpl requirement = new RequirementImpl();
+        requirement.setFilter(obr);
+        assertEquals(osgi, new FelixRequirementAdapter(requirement, resource).getDirectives().get("filter"));
+    }
+
+    public void testOtherDirectives()
+    {
+        Resource resource = new OSGiResourceImpl(
+            Collections.<Capability>emptyList(),
+            Collections.<Requirement>emptyList());
+
+        RequirementImpl requirement = new RequirementImpl();
+        requirement.setFilter("(a=b)");
+        Map<String, String> other = new HashMap<String, String>();
+        other.put("xyz", "abc");
+        requirement.setDirectives(other);
+
+        FelixRequirementAdapter adapter = new FelixRequirementAdapter(requirement, resource);
+
+        Map<String, String> expected = new HashMap<String, String>();
+        expected.put("filter", "(a=b)");
+        expected.put("xyz", "abc");
+        assertEquals(expected, adapter.getDirectives());
+    }
+}

Added: felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/NamespaceTranslatorTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/NamespaceTranslatorTest.java?rev=1591870&view=auto
==============================================================================
--- felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/NamespaceTranslatorTest.java (added)
+++ felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/NamespaceTranslatorTest.java Fri May  2 11:29:10 2014
@@ -0,0 +1,53 @@
+/*
+ * 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.bundlerepository.impl;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+public class NamespaceTranslatorTest extends TestCase
+{
+    public void testNamespaceTranslator()
+    {
+        Map<String, String> expected = new HashMap<String, String>();
+        expected.put("osgi.wiring.bundle", "bundle");
+        expected.put("osgi.wiring.package", "package");
+        expected.put("osgi.wiring.host", "fragment");
+        expected.put("osgi.service", "service");
+
+        assertEquals(new HashSet<String>(expected.keySet()),
+            new HashSet<String>(NamespaceTranslator.getTranslatedOSGiNamespaces()));
+        assertEquals(new HashSet<String>(expected.values()),
+            new HashSet<String>(NamespaceTranslator.getTranslatedFelixNamespaces()));
+
+        for (Map.Entry<String, String> entry : expected.entrySet())
+        {
+            assertEquals(entry.getValue(),
+                NamespaceTranslator.getFelixNamespace(entry.getKey()));
+            assertEquals(entry.getKey(),
+                NamespaceTranslator.getOSGiNamespace(entry.getValue()));
+        }
+
+        assertEquals("bheuaark", NamespaceTranslator.getFelixNamespace("bheuaark"));
+        assertEquals("bheuaark", NamespaceTranslator.getOSGiNamespace("bheuaark"));
+    }
+}

Added: felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRequirementAdapterTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRequirementAdapterTest.java?rev=1591870&view=auto
==============================================================================
--- felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRequirementAdapterTest.java (added)
+++ felix/trunk/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/OSGiRequirementAdapterTest.java Fri May  2 11:29:10 2014
@@ -0,0 +1,53 @@
+/*
+ * 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.bundlerepository.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.osgi.resource.Requirement;
+
+public class OSGiRequirementAdapterTest extends TestCase
+{
+    public void testDirectives()
+    {
+        Map<String, Object> attrs = new HashMap<String, Object>();
+        Map<String, String> dirs = new HashMap<String, String>();
+        dirs.put("cardinality", "multiple");
+        dirs.put("filter", "(osgi.wiring.package=y)");
+        dirs.put("foo", "bar");
+        dirs.put("resolution", "optional");
+        dirs.put("test", "test");
+
+        Requirement req = new OSGiRequirementImpl("osgi.wiring.package", attrs, dirs);
+        OSGiRequirementAdapter adapter = new OSGiRequirementAdapter(req);
+
+        assertEquals("(package=y)", adapter.getFilter());
+        assertTrue(adapter.isMultiple());
+        assertTrue(adapter.isOptional());
+        assertEquals("package", adapter.getName());
+
+        Map<String, String> expected = new HashMap<String, String>();
+        expected.put("foo", "bar");
+        expected.put("test", "test");
+        assertEquals(expected, adapter.getDirectives());
+    }
+}