You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2015/06/22 22:22:33 UTC

[1/4] karaf git commit: Fix problem with the same bundle being available in 2 unrelated features

Repository: karaf
Updated Branches:
  refs/heads/master 571c46e4e -> 6574c0de0


Fix problem with the same bundle being available in 2 unrelated features

Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/4c3370c9
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/4c3370c9
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/4c3370c9

Branch: refs/heads/master
Commit: 4c3370c93ea3e624905538fa29a0a86a721590ea
Parents: 571c46e
Author: Guillaume Nodet <gn...@Guillaumes-MacBook-Pro.local>
Authored: Mon Jun 22 20:13:02 2015 +0200
Committer: Guillaume Nodet <gn...@Guillaumes-MacBook-Pro.local>
Committed: Mon Jun 22 20:13:02 2015 +0200

----------------------------------------------------------------------
 .../region/SubsystemResolveContext.java         | 46 +++++++++++++++-----
 .../features/internal/region/SubsystemTest.java | 22 ++++++++++
 .../karaf/features/internal/region/data6/a.mf   |  5 +++
 .../karaf/features/internal/region/data6/b.mf   |  5 +++
 .../karaf/features/internal/region/data6/c.mf   |  5 +++
 .../features/internal/region/data6/features.xml | 42 ++++++++++++++++++
 6 files changed, 113 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/4c3370c9/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java b/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java
index c25d9f4..104fb24 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java
@@ -161,26 +161,48 @@ public class SubsystemResolveContext extends ResolveContext {
             // need to remove the one from the child if it can view
             // the parent one
             if (caps.size() > 1) {
-                Map<String, Resource> providers = new HashMap<String, Resource>();
+                Set<Resource> providers = new HashSet<>();
                 for (Capability cap : caps) {
                     Resource resource = cap.getResource();
                     String id = ResolverUtil.getSymbolicName(resource) + "|" + ResolverUtil.getVersion(resource);
-                    Resource prev = providers.get(id);
-                    if (prev != null && prev != resource) {
-                        String r1 = getRegion(prev).getName();
-                        String r2 = getRegion(resource).getName();
-                        int c = r1.compareTo(r2);
-                        if (c == 0) {
-                            // One of the resource has to be a bundle, use that one
-                            c = (prev instanceof BundleRevision) ? -1 : +1;
+                    if (!providers.contains(resource)) {
+                        Set<Resource> newRes = new HashSet<>();
+                        String r1 = getRegion(resource).getName();
+                        boolean superceded = false;
+                        for (Resource r : providers) {
+                            String id2 = ResolverUtil.getSymbolicName(r) + "|" + ResolverUtil.getVersion(r);
+                            if (id.equals(id2)) {
+                                String r2 = getRegion(r).getName();
+                                if (r1.equals(r2)) {
+                                    if (r instanceof BundleRevision) {
+                                        newRes.add(r);
+                                        superceded = true;
+                                    } else if (resource instanceof BundleRevision) {
+                                        newRes.add(resource);
+                                    } else {
+                                        throw new InternalError();
+                                    }
+                                } else if (r1.startsWith(r2)) {
+                                    newRes.add(r);
+                                    superceded = true;
+                                } else if (r2.startsWith(r1)) {
+                                    newRes.add(resource);
+                                } else {
+                                    newRes.add(r);
+                                }
+                            } else {
+                                newRes.add(r);
+                            }
                         }
-                        resource = c < 0 ? prev : resource;
+                        if (!superceded) {
+                            newRes.add(resource);
+                        }
+                        providers = newRes;
                     }
-                    providers.put(id, resource);
                 }
                 for (Iterator<Capability> it = caps.iterator(); it.hasNext();) {
                     Capability cap = it.next();
-                    if (!providers.values().contains(cap.getResource())) {
+                    if (!providers.contains(cap.getResource())) {
                         it.remove();
                     }
                 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/4c3370c9/features/core/src/test/java/org/apache/karaf/features/internal/region/SubsystemTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/region/SubsystemTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/region/SubsystemTest.java
index 846a2c9..d957ae6 100644
--- a/features/core/src/test/java/org/apache/karaf/features/internal/region/SubsystemTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/region/SubsystemTest.java
@@ -231,6 +231,28 @@ public class SubsystemTest {
         verify(resolver, expected);
     }
 
+    @Test
+    public void testFeatureOptionalAlreadyProvided2() throws Exception {
+        RepositoryImpl repo = new RepositoryImpl(getClass().getResource("data6/features.xml").toURI());
+
+        Map<String, Set<String>> features = new HashMap<String, Set<String>>();
+        addToMapSet(features, "root", "pax-http");
+        addToMapSet(features, "root", "pax-http-tomcat");
+        Map<String, Set<String>> expected = new HashMap<String, Set<String>>();
+        addToMapSet(expected, "root", "a/1.0.0");
+        addToMapSet(expected, "root", "c/1.0.0");
+
+        SubsystemResolver resolver = new SubsystemResolver(this.resolver, new TestDownloadManager(getClass(), "data6"));
+        resolver.prepare(Arrays.asList(repo.getFeatures()),
+                features,
+                Collections.<String, Set<BundleRevision>>emptyMap());
+        resolver.resolve(Collections.<String>emptySet(),
+                FeaturesService.DEFAULT_FEATURE_RESOLUTION_RANGE,
+                null, null);
+
+        verify(resolver, expected);
+    }
+
     private void verify(SubsystemResolver resolver, Map<String, Set<String>> expected) {
         Map<String, Set<String>> mapping = getBundleNamesPerRegions(resolver);
         if (!expected.equals(mapping)) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/4c3370c9/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/a.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/a.mf b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/a.mf
new file mode 100644
index 0000000..20a7811
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/a.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: a
+Bundle-Version: 1.0.0
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/4c3370c9/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/b.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/b.mf b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/b.mf
new file mode 100644
index 0000000..dc96158
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/b.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: b
+Bundle-Version: 1.0.0
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/4c3370c9/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/c.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/c.mf b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/c.mf
new file mode 100644
index 0000000..8535efa
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/c.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: c
+Bundle-Version: 1.0.0
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/4c3370c9/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/features.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/features.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/features.xml
new file mode 100644
index 0000000..08982f7
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data6/features.xml
@@ -0,0 +1,42 @@
+<?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.
+
+-->
+<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0">
+
+    <feature name="pax-http">
+        <feature dependency="true">pax-http-jetty</feature>
+        <requirement>pax-http-provider</requirement>
+    </feature>
+
+    <feature name="pax-jetty">
+        <bundle>b</bundle>
+    </feature>
+
+    <feature name="pax-http-jetty">
+        <capability>pax-http-provider;provider:=jetty</capability>
+        <feature>pax-jetty</feature>
+        <bundle>a</bundle>
+    </feature>
+
+    <feature name="pax-http-tomcat">
+        <capability>pax-http-provider;provider:=tomcat</capability>
+        <bundle>c</bundle>
+        <bundle>a</bundle>
+    </feature>
+
+</features>
\ No newline at end of file


[4/4] karaf git commit: Disable ignoreServiceReqs flag by default

Posted by gn...@apache.org.
Disable ignoreServiceReqs flag by default

Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/6574c0de
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/6574c0de
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/6574c0de

Branch: refs/heads/master
Commit: 6574c0de0e8879bfa9a4f3de159e322e6416a014
Parents: 4250c4b
Author: Guillaume Nodet <gn...@Guillaumes-MacBook-Pro.local>
Authored: Mon Jun 22 22:20:10 2015 +0200
Committer: Guillaume Nodet <gn...@Guillaumes-MacBook-Pro.local>
Committed: Mon Jun 22 22:20:10 2015 +0200

----------------------------------------------------------------------
 .../java/org/apache/karaf/features/internal/osgi/Activator.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/6574c0de/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java b/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
index 954ebce..b4f088d 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
@@ -179,7 +179,7 @@ public class Activator extends BaseActivator {
         long scheduleDelay = getLong("scheduleDelay", FeaturesService.DEFAULT_SCHEDULE_DELAY);
         int scheduleMaxRun = getInt("scheduleMaxRun", FeaturesService.DEFAULT_SCHEDULE_MAX_RUN);
         String blacklisted = getString("blacklisted", new File(System.getProperty("karaf.etc"), "blacklisted.properties").toURI().toString());
-        boolean ignoreServiceReqs = getBoolean("ignoreServiceReqs", true);
+        boolean ignoreServiceReqs = getBoolean("ignoreServiceReqs", false);
         SubsystemResolveContext.setIgnoreServiceReqs(ignoreServiceReqs);
         StateStorage stateStorage = new StateStorage() {
             @Override


[3/4] karaf git commit: Upgrade to pax-web 4.1.4-SNAPSHOT

Posted by gn...@apache.org.
Upgrade to pax-web 4.1.4-SNAPSHOT

Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/4250c4b5
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/4250c4b5
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/4250c4b5

Branch: refs/heads/master
Commit: 4250c4b5252ed44b47ab2686c4ed643dc3087ca4
Parents: 944bad9
Author: Guillaume Nodet <gn...@Guillaumes-MacBook-Pro.local>
Authored: Mon Jun 22 22:19:29 2015 +0200
Committer: Guillaume Nodet <gn...@Guillaumes-MacBook-Pro.local>
Committed: Mon Jun 22 22:19:29 2015 +0200

----------------------------------------------------------------------
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/4250c4b5/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 61374c7..a5408ef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -238,7 +238,7 @@
         <pax.logging.version>1.8.3</pax.logging.version>
         <pax.base.version>1.5.0</pax.base.version>
         <pax.url.version>2.4.1</pax.url.version>
-        <pax.web.version>4.1.3</pax.web.version>
+        <pax.web.version>4.1.4-SNAPSHOT</pax.web.version>
         <pax.tinybundle.version>2.1.0</pax.tinybundle.version>
         <portlet-api.version>2.0</portlet-api.version>
         <slf4j.version>1.7.12</slf4j.version>


[2/4] karaf git commit: Fix for pax-web / webconsole problem

Posted by gn...@apache.org.
Fix for pax-web / webconsole problem

Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/944bad9e
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/944bad9e
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/944bad9e

Branch: refs/heads/master
Commit: 944bad9ec4dc01b8f254b508617dc452d35fea23
Parents: 4c3370c
Author: Guillaume Nodet <gn...@Guillaumes-MacBook-Pro.local>
Authored: Mon Jun 22 22:19:06 2015 +0200
Committer: Guillaume Nodet <gn...@Guillaumes-MacBook-Pro.local>
Committed: Mon Jun 22 22:19:06 2015 +0200

----------------------------------------------------------------------
 .../features/internal/region/Subsystem.java     | 19 +++---
 .../region/SubsystemResolveContext.java         | 61 +++++++++++++++++---
 2 files changed, 65 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/944bad9e/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java b/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
index 71a22d3..75e497a 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
@@ -32,6 +32,7 @@ import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
+import org.apache.felix.resolver.Util;
 import org.apache.felix.utils.manifest.Clause;
 import org.apache.felix.utils.manifest.Parser;
 import org.apache.felix.utils.version.VersionRange;
@@ -95,6 +96,7 @@ public class Subsystem extends ResourceImpl {
     private final boolean acceptDependencies;
     private final Subsystem parent;
     private final Feature feature;
+    private final boolean mandatory;
     private final List<Subsystem> children = new ArrayList<>();
     private final Map<String, Set<String>> importPolicy;
     private final Map<String, Set<String>> exportPolicy;
@@ -112,14 +114,16 @@ public class Subsystem extends ResourceImpl {
         this.feature = null;
         this.importPolicy = SHARE_NONE_POLICY;
         this.exportPolicy = SHARE_NONE_POLICY;
+        this.mandatory = true;
     }
 
-    public Subsystem(String name, Feature feature, Subsystem parent) {
+    public Subsystem(String name, Feature feature, Subsystem parent, boolean mandatory) {
         super(name, TYPE_SUBSYSTEM, Version.emptyVersion);
         this.name = name;
         this.parent = parent;
         this.acceptDependencies = feature.getScoping() != null && feature.getScoping().acceptDependencies();
         this.feature = feature;
+        this.mandatory = mandatory;
         if (feature.getScoping() != null) {
             this.importPolicy = createPolicy(feature.getScoping().getImports());
             this.importPolicy.put(IDENTITY_NAMESPACE, Collections.singleton(SUBSYSTEM_OR_FEATURE_FILTER));
@@ -136,12 +140,13 @@ public class Subsystem extends ResourceImpl {
                 new VersionRange(VersionTable.getVersion(feature.getVersion()), true));
     }
 
-    public Subsystem(String name, Subsystem parent, boolean acceptDependencies) {
+    public Subsystem(String name, Subsystem parent, boolean acceptDependencies, boolean mandatory) {
         super(name, TYPE_SUBSYSTEM, Version.emptyVersion);
         this.name = name;
         this.parent = parent;
         this.acceptDependencies = acceptDependencies;
         this.feature = null;
+        this.mandatory = mandatory;
         this.importPolicy = SHARE_ALL_POLICY;
         this.exportPolicy = SHARE_NONE_POLICY;
     }
@@ -193,7 +198,7 @@ public class Subsystem extends ResourceImpl {
         }
         // Create subsystem
         String childName = getName() + "/" + name;
-        Subsystem as = new Subsystem(childName, this, acceptDependencies);
+        Subsystem as = new Subsystem(childName, this, acceptDependencies, true);
         children.add(as);
         // Add a requirement to force its resolution
         ResourceUtils.addIdentityRequirement(this, childName, TYPE_SUBSYSTEM, (VersionRange) null);
@@ -211,7 +216,7 @@ public class Subsystem extends ResourceImpl {
             ResourceUtils.addIdentityRequirement(this, name, TYPE_FEATURE, range);
         } else {
             ResourceImpl res = new ResourceImpl();
-            ResourceUtils.addIdentityRequirement(res, name, TYPE_FEATURE, range);
+            ResourceUtils.addIdentityRequirement(res, name, TYPE_FEATURE, range, false);
             dependentFeatures.addAll(res.getRequirements(null));
         }
     }
@@ -272,14 +277,14 @@ public class Subsystem extends ResourceImpl {
                 while (!ss.isAcceptDependencies()) {
                     ss = ss.getParent();
                 }
-                ss.requireFeature(dep.getName(), dep.getVersion(), mandatory && !dep.isDependency());
+                ss.requireFeature(dep.getName(), dep.getVersion(), this.mandatory && (mandatory && !dep.isDependency()));
             }
             for (Conditional cond : feature.getConditional()) {
                 Feature fcond = cond.asFeature();
                 String ssName = this.name + "#" + (fcond.hasVersion() ? fcond.getName() + "-" + fcond.getVersion() : fcond.getName());
                 Subsystem fs = getChild(ssName);
                 if (fs == null) {
-                    fs = new Subsystem(ssName, fcond, this);
+                    fs = new Subsystem(ssName, fcond, this, true);
                     fs.doBuild(features, false);
                     installable.add(fs);
                     children.add(fs);
@@ -306,7 +311,7 @@ public class Subsystem extends ResourceImpl {
                                 String ssName = this.name + "#" + (feature.hasVersion() ? feature.getName() + "-" + feature.getVersion() : feature.getName());
                                 Subsystem fs = getChild(ssName);
                                 if (fs == null) {
-                                    fs = new Subsystem(ssName, feature, this);
+                                    fs = new Subsystem(ssName, feature, this, mandatory && !SubsystemResolveContext.isOptional(requirement));
                                     fs.build(features);
                                     installable.add(fs);
                                     children.add(fs);

http://git-wip-us.apache.org/repos/asf/karaf/blob/944bad9e/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java b/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java
index 104fb24..1ed9ef5 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java
@@ -86,7 +86,7 @@ public class SubsystemResolveContext extends ResolveContext {
         // Add a heuristic to sort capabilities :
         //  if a capability comes from a resource which needs to be installed,
         //  prefer that one over any capabilities from other resources
-        findMandatory(root);
+        findMandatory();
     }
     
     public static void setIgnoreServiceReqs(boolean ignoreServiceReqs) {
@@ -101,18 +101,63 @@ public class SubsystemResolveContext extends ResolveContext {
         return globalRepository;
     }
 
-    void findMandatory(Resource res) {
-        if (mandatory.add(res)) {
-            for (Requirement req : res.getRequirements(null)) {
-                String resolution = req.getDirectives().get(REQUIREMENT_RESOLUTION_DIRECTIVE);
-                if (!RESOLUTION_OPTIONAL.equals(resolution)) {
+    void findMandatory() {
+        mandatory.add(root);
+        int nbMandatory;
+        // Iterate while we find more mandatory resources
+        do {
+            nbMandatory = mandatory.size();
+            for (Resource res : new ArrayList<>(mandatory)) {
+                // Check mandatory requirements of mandatory resources
+                for (Requirement req : res.getRequirements(null)) {
+                    if (isOptional(req)) {
+                        continue;
+                    }
                     List<Capability> caps = findProviders(req);
+                    // If there's a single provider for any kind of mandatory requirement,
+                    // this means the resource is also mandatory
                     if (caps.size() == 1) {
-                        findMandatory(caps.get(0).getResource());
+                        mandatory.add(caps.get(0).getResource());
+                    } else {
+                        // In case there are multiple providers
+                        // check if there is a single provider which has
+                        // a mandatory identity requirement on a mandatory
+                        // resource, in which case we also assume this one
+                        // is mandatory
+                        Set<Resource> mand = new HashSet<>();
+                        for (Capability cap : caps) {
+                            Resource r = cap.getResource();
+                            if (mandatory.contains(r)) {
+                                mand.add(r);
+                            } else {
+                                for (Requirement req2 : r.getRequirements(null)) {
+                                    if (!IDENTITY_NAMESPACE.equals(req2.getNamespace()) || !isOptional(req2)) {
+                                        continue;
+                                    }
+                                    List<Capability> caps2 = findProviders(req2);
+                                    if (caps2.size() == 1) {
+                                        Resource r2 =  caps2.get(0).getResource();
+                                        if (mandatory.contains(r2)) {
+                                            mand.add(r);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if (mand.size() == 1) {
+                            mandatory.add(mand.iterator().next());
+                        } else {
+                            mand.clear();
+                        }
                     }
                 }
             }
-        }
+        } while (mandatory.size() != nbMandatory);
+    }
+
+    static boolean isOptional(Requirement req) {
+        String resolution = req.getDirectives().get(REQUIREMENT_RESOLUTION_DIRECTIVE);
+        return RESOLUTION_OPTIONAL.equalsIgnoreCase(resolution);
     }
 
     void prepare(Subsystem subsystem) {