FELIX-2144: add global requirements and capabilities to the resolver
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@917434 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resolver.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resolver.java
index 3976832..a5e059d 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resolver.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resolver.java
@@ -66,6 +66,43 @@
*/
Requirement[] getAddedRequirements();
+ /**
+ * Add a global capability.
+ *
+ * A global capability is one capability provided by the environment
+ * but not reflected in local resources.
+ *
+ * @param capability the new global capability
+ */
+ void addGlobalCapability(Capability capability);
+
+ /**
+ * Returns the list of global capabilities
+ * @return
+ */
+ Capability[] getGlobalCapabilities();
+
+ /**
+ * Add a global requirement.
+ *
+ * A global requirement is a requirement that must be satisfied by all
+ * resources. Such requirements are usually built using an
+ * IF x then Y
+ * which can be expressed using the following logical expression
+ * !X OR (X AND Y)
+ * which can be translated to the following filter
+ * (|(!(x))(&(x)(y))
+ *
+ * @param requirement
+ */
+ void addGlobalRequirement(Requirement requirement);
+
+ /**
+ * Returns a list of global requirements
+ * @return
+ */
+ Requirement[] getGlobalRequirements();
+
/**
* Start the resolution process and return whether the constraints have
* been successfully met or not.
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResolverImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResolverImpl.java
index 07993ef..56bfad3 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResolverImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResolverImpl.java
@@ -32,6 +32,8 @@
private final Repository[] m_repositories;
private final Set m_addedSet = new HashSet();
private final Set m_addedRequirementSet = new HashSet();
+ private final Set m_globalCapabilities = new HashSet();
+ private final Set m_globalRequirements = new HashSet();
private final Set m_failedSet = new HashSet();
private final Set m_resolveSet = new HashSet();
private final Set m_requiredSet = new HashSet();
@@ -72,6 +74,27 @@
return (Requirement[]) m_addedRequirementSet.toArray(new Requirement[m_addedRequirementSet.size()]);
}
+ public void addGlobalCapability(Capability capability)
+ {
+ m_globalCapabilities.add(capability);
+ }
+
+ public Capability[] getGlobalCapabilities()
+ {
+ return (Capability[]) m_globalCapabilities.toArray(new Capability[m_globalCapabilities.size()]);
+ }
+
+ public void addGlobalRequirement(Requirement requirement)
+ {
+ m_resolved = false;
+ m_globalRequirements.add(requirement);
+ }
+
+ public Requirement[] getGlobalRequirements()
+ {
+ return (Requirement[]) m_globalRequirements.toArray(new Requirement[m_globalRequirements.size()]);
+ }
+
public synchronized Requirement[] getUnsatisfiedRequirements()
{
if (m_resolved)
@@ -154,6 +177,7 @@
// Find resources
Resource[] locals = getResources(true);
Resource[] remotes = getResources(false);
+ remotes = filter(remotes, (Requirement[]) m_globalRequirements.toArray(new Requirement[m_globalRequirements.size()]));
// time of the resolution process start
m_resolveTimeStamp = 0;
@@ -178,10 +202,16 @@
boolean result = true;
// Add a fake resource if needed
- if (!m_addedRequirementSet.isEmpty())
+ if (!m_addedRequirementSet.isEmpty() || !m_globalCapabilities.isEmpty())
{
ResourceImpl fake = new ResourceImpl();
- for (Iterator iter = m_addedRequirementSet.iterator(); iter.hasNext(); )
+ for (Iterator iter = m_globalCapabilities.iterator(); iter.hasNext();)
+ {
+ Capability cap = (Capability) iter.next();
+ fake.addCapability(cap);
+ ((CapabilityImpl) cap).setResource(null);
+ }
+ for (Iterator iter = m_addedRequirementSet.iterator(); iter.hasNext();)
{
Requirement req = (Requirement) iter.next();
fake.addRequire(req);
@@ -215,6 +245,40 @@
return result;
}
+ private Resource[] filter(Resource[] resources, Requirement[] requirements)
+ {
+ if (requirements == null || requirements.length == 0)
+ {
+ return resources;
+ }
+ List res = new ArrayList();
+ for (int resIdx = 0; (resources != null) && resIdx < resources.length; resIdx++)
+ {
+ boolean resOk = true;
+ for (int reqIdx = 0; (requirements != null) && reqIdx < requirements.length; reqIdx++)
+ {
+ boolean reqOk = false;
+ Capability[] caps = resources[resIdx].getCapabilities();
+ for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
+ {
+ if (requirements[reqIdx].isSatisfied(caps[capIdx]))
+ {
+ reqOk = true;
+ break;
+ }
+ }
+ if (!reqOk) {
+ resOk = false;
+ break;
+ }
+ }
+ if (resOk) {
+ res.add(resources[resIdx]);
+ }
+ }
+ return (Resource[]) res.toArray(new Resource[res.size()]);
+ }
+
private boolean resolve(Resource resource, Resource[] locals, Resource[] remotes, boolean optional)
{
boolean result = true;