FELIX-1531: Mandatory directive is ignored on the Export-Package when it comes to resolve the bundles

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@918062 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FilterImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FilterImpl.java
index 2dadb0c..07ed019 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FilterImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FilterImpl.java
@@ -301,14 +301,14 @@
             }
             case SUBSET : {
                 sb.append(attr);
-                sb.append(":<*");
+                sb.append("<*");
                 sb.append(encodeValue(approxString((String) value)));
 
                 break;
             }
             case SUPERSET : {
                 sb.append(attr);
-                sb.append(":*>");
+                sb.append("*>");
                 sb.append(encodeValue(approxString((String) value)));
 
                 break;
@@ -1294,17 +1294,13 @@
             skipWhiteSpace();
 
             switch (filterChars[pos]) {
-                case ':': {
-                    if (filterChars[pos + 1] == '<' && filterChars[pos + 2] == '*') {
-                        pos += 3;
-                        return new FilterImpl(FilterImpl.SUBSET, attr,
-                                parse_value());
-                    }
-                    if (filterChars[pos + 1] == '*' && filterChars[pos + 2] == '>') {
-                        pos += 3;
+                case '*': {
+                    if (filterChars[pos + 1] == '>') {
+                        pos += 2;
                         return new FilterImpl(FilterImpl.SUPERSET, attr,
                                 parse_value());
                     }
+                    break;
                 }
                 case '~' : {
                     if (filterChars[pos + 1] == '=') {
@@ -1328,6 +1324,11 @@
                         return new FilterImpl(FilterImpl.LESS, attr,
                                 parse_value());
                     }
+                    if (filterChars[pos + 1] == '*') {
+                        pos += 2;
+                        return new FilterImpl(FilterImpl.SUBSET, attr,
+                                parse_value());
+                    }
                     break;
                 }
                 case '=' : {
@@ -1369,10 +1370,10 @@
             while (c != '~' && c != '<' && c != '>' && c != '=' && c != '('
                     && c != ')') {
 
-                if (c == ':' && filterChars[pos+1] == '<' && filterChars[pos+2] == '*') {
+                if (c == '<' && filterChars[pos+1] == '*') {
                     break;
                 }
-                if (c == ':' && filterChars[pos+1] == '*' && filterChars[pos+2] == '>') {
+                if (c == '*' && filterChars[pos+1] == '>') {
                     break;
                 }
                 pos++;
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java
index cfafcac..b9675cb 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java
@@ -59,7 +59,8 @@
 
     public synchronized boolean isSatisfied(Capability capability)
     {
-        return m_name.equals(capability.getName()) && m_filter.matchCase(capability.getProperties());
+        return m_name.equals(capability.getName()) && m_filter.matchCase(capability.getProperties())
+                && (m_filter.toString().indexOf("(mandatory:<*") >= 0 || capability.getProperties().get("mandatory:") == null);
     }
 
     public synchronized boolean isExtend()
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/FilterImplTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/FilterImplTest.java
index e41fe4f..f1fa32e 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/FilterImplTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/FilterImplTest.java
@@ -56,14 +56,14 @@
         assertFalse(filterImpl.match(dict));
 
         dict = new Hashtable();
-        dict.put("mandatory", "common");
+        dict.put("mandatory:", "common");
         dict.put("package", "org.eclipse.core.runtime");
         dict.put("version", new Version("0.0.0"));
         dict.put("common", "split");
         assertTrue(filterImpl.match(dict));
 
         dict = new Hashtable();
-        dict.put("mandatory", "common,test");
+        dict.put("mandatory:", "common,test");
         dict.put("package", "org.eclipse.core.runtime");
         dict.put("version", new Version("0.0.0"));
         dict.put("common", "split");
@@ -78,14 +78,14 @@
         filterImpl = FilterImpl.newInstance(
             "(&(package=org.eclipse.core.runtime)(version>=0.0.0)(common=split)(mandatory:*>common))");
         dict = new Hashtable();
-        dict.put("mandatory", "common");
+        dict.put("mandatory:", "common");
         dict.put("package", "org.eclipse.core.runtime");
         dict.put("version", new Version("0.0.0"));
         dict.put("common", "split");
         assertTrue(filterImpl.match(dict));
 
         dict = new Hashtable();
-        dict.put("mandatory", "common,test");
+        dict.put("mandatory:", "common,test");
         dict.put("package", "org.eclipse.core.runtime");
         dict.put("version", new Version("0.0.0"));
         dict.put("common", "split");
@@ -94,14 +94,14 @@
         filterImpl = FilterImpl.newInstance(
             "(&(package=org.eclipse.core.runtime)(version>=0.0.0)(common=split)(mandatory:*>common,test))");
         dict = new Hashtable();
-        dict.put("mandatory", "common");
+        dict.put("mandatory:", "common");
         dict.put("package", "org.eclipse.core.runtime");
         dict.put("version", new Version("0.0.0"));
         dict.put("common", "split");
         assertFalse(filterImpl.match(dict));
 
         dict = new Hashtable();
-        dict.put("mandatory", "common,test");
+        dict.put("mandatory:", "common,test");
         dict.put("package", "org.eclipse.core.runtime");
         dict.put("version", new Version("0.0.0"));
         dict.put("common", "split");
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryAdminTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryAdminTest.java
index 2f6e4ae..aa1b0ca 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryAdminTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryAdminTest.java
@@ -41,11 +41,11 @@
         RepositoryAdminImpl repoAdmin = createRepositoryAdmin();
         RepositoryImpl repo = (RepositoryImpl) repoAdmin.addRepository(url);
 
-        Resource[] resources = repoAdmin.discoverResources("(category:<*dummy)");
+        Resource[] resources = repoAdmin.discoverResources("(category<*dummy)");
         assertNotNull(resources);
         assertEquals(1, resources.length);
 
-        resources = repoAdmin.discoverResources("(category:*>dummy)");
+        resources = repoAdmin.discoverResources("(category*>dummy)");
         assertNotNull(resources);
         assertEquals(1, resources.length);
     }
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/ResolverImplTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/ResolverImplTest.java
index 5bb7381..8a27bd7 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/ResolverImplTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/ResolverImplTest.java
@@ -110,6 +110,25 @@
         assertEquals(2, resolver.getOptionalResources().length);
     }
 
+    public void testMandatoryPackages() throws Exception
+    {
+        RepositoryAdminImpl repoAdmin = createRepositoryAdmin();
+        repoAdmin.addRepository(getClass().getResource("/repo_for_mandatory.xml"));
+
+        Resolver resolver = repoAdmin.resolver();
+        resolver.add(repoAdmin.requirement("bundle", "(symbolicname=res2)"));
+        assertFalse(resolver.resolve());
+
+        resolver = repoAdmin.resolver();
+        resolver.add(repoAdmin.requirement("bundle", "(symbolicname=res3)"));
+        assertTrue(resolver.resolve());
+
+        resolver = repoAdmin.resolver();
+        resolver.add(repoAdmin.requirement("bundle", "(symbolicname=res4)"));
+        assertFalse(resolver.resolve());
+
+    }
+
     public static void main(String[] args) throws Exception
     {
         new ResolverImplTest().testReferral1();
diff --git a/bundlerepository/src/test/resources/repo_for_mandatory.xml b/bundlerepository/src/test/resources/repo_for_mandatory.xml
new file mode 100644
index 0000000..96fd4b9
--- /dev/null
+++ b/bundlerepository/src/test/resources/repo_for_mandatory.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<repository lastmodified="2010" name="repo_for_optional_resources">
+
+    <resource id="res1">
+        <capability name="bundle">
+            <p n="symbolicname" v="res1" />
+        </capability>
+        <capability name="package">
+            <p n="package" v="javax.transaction" />
+            <p n="partial" v="true" />
+            <p n="mandatory:" v="partial" />
+        </capability>
+    </resource>
+
+    <resource id="res2">
+        <capability name="bundle">
+            <p n="symbolicname" v="res2" />
+        </capability>
+        <require filter="(package=javax.transaction)" name="package" optional="false" />
+    </resource>
+
+    <resource id="res3">
+        <capability name="bundle">
+            <p n="symbolicname" v="res3" />
+        </capability>
+        <require filter="(&amp;(package=javax.transaction)(partial=true)(mandatory:&lt;*partial))" name="package" optional="false" />
+    </resource>
+
+    <resource id="res4">
+        <capability name="bundle">
+            <p n="symbolicname" v="res4" />
+        </capability>
+        <require filter="(&amp;(package=a.b.c)(company=foo)(mandatory:&lt;*company))" name="package" optional="false" />
+    </resource>
+
+    <resource id="res5">
+        <capability name="bundle">
+            <p n="symbolicname" v="res5" />
+        </capability>
+        <capability name='package'>
+            <p n='company' v='foo'/>
+            <p n='mandatory:' t='set' v='company,security'/>
+            <p n='package' v='a.b.c'/>
+            <p n='security' v='true'/>
+            <p n='version' t='version' v='3.0.0'/>
+        </capability> 
+    </resource>
+
+</repository>