Fixed some bugs in the fragment conflict detection algorithm.
I thought VersionRange implemented equals, but it was using the
default implementation. Also made optionality a little more flexible
by allowing optional requirements to overlap non-optional ones.
(FELIX-29)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@772010 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java b/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
index bdbff4a..6760a1c 100644
--- a/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
+++ b/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
@@ -35,6 +35,7 @@
import org.apache.felix.moduleloader.IModule;
import org.apache.felix.moduleloader.IRequirement;
import org.apache.felix.moduleloader.IWire;
+import org.osgi.framework.Constants;
import org.osgi.framework.PackagePermission;
import org.osgi.framework.Version;
@@ -276,33 +277,53 @@
{
return true;
}
- // If optionality is not the same, then they conflict.
- if (existing.isOptional() != additional.isOptional())
+ // If optionality is not the same, then they conflict, unless
+ // the existing requirement is not optional, then it doesn't matter
+ // what subsequent requirements are since non-optional is stronger
+ // than optional.
+ if (existing.isOptional() && (existing.isOptional() != additional.isOptional()))
{
return true;
}
// Verify directives are the same.
+ // This is sort of ugly, but we need to remove
+ // the resolution directive, since it is effectively
+ // test above when checking optionality.
+ // Put directives in a map, since ordering is arbitrary.
final R4Directive[] exDirs = (existing.getDirectives() == null)
? new R4Directive[0] : existing.getDirectives();
- final R4Directive[] addDirs = (additional.getDirectives() == null)
- ? new R4Directive[0] : additional.getDirectives();
- // If different number of directives, then they conflict.
- if (exDirs.length != addDirs.length)
- {
- return true;
- }
- // Put directives in a map, since ordering is arbitrary.
final Map exDirMap = new HashMap();
for (int i = 0; i < exDirs.length; i++)
{
- exDirMap.put(exDirs[i].getName(), exDirs[i]);
+ if (!exDirs[i].getName().equals(Constants.RESOLUTION_DIRECTIVE))
+ {
+ exDirMap.put(exDirs[i].getName(), exDirs[i]);
+ }
}
- // If directive values do not match, then they conflict.
+ final R4Directive[] addDirs = (additional.getDirectives() == null)
+ ? new R4Directive[0] : additional.getDirectives();
+ final Map addDirMap = new HashMap();
for (int i = 0; i < addDirs.length; i++)
{
- final R4Directive exDir = (R4Directive) exDirMap.get(addDirs[i].getName());
+ if (!addDirs[i].getName().equals(Constants.RESOLUTION_DIRECTIVE))
+ {
+ addDirMap.put(addDirs[i].getName(), addDirs[i]);
+ }
+ }
+ // If different number of directives, then they conflict.
+ if (exDirMap.size() != addDirMap.size())
+ {
+ return true;
+ }
+ // If directive values do not match, then they conflict.
+ for (Iterator it = addDirMap.entrySet().iterator(); it.hasNext(); )
+ {
+ final Map.Entry entry = (Map.Entry) it.next();
+ final String name = (String) entry.getKey();
+ final R4Directive addDir = (R4Directive) entry.getValue();
+ final R4Directive exDir = (R4Directive) exDirMap.get(name);
if ((exDir == null) ||
- !exDir.getValue().equals(addDirs[i].getValue()))
+ !exDir.getValue().equals(addDir.getValue()))
{
return true;
}
diff --git a/framework/src/main/java/org/apache/felix/framework/util/VersionRange.java b/framework/src/main/java/org/apache/felix/framework/util/VersionRange.java
index 0a0d386..f415fa5 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/VersionRange.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/VersionRange.java
@@ -98,6 +98,46 @@
}
}
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ final VersionRange other = (VersionRange) obj;
+ if (m_low != other.m_low && (m_low == null || !m_low.equals(other.m_low)))
+ {
+ return false;
+ }
+ if (m_isLowInclusive != other.m_isLowInclusive)
+ {
+ return false;
+ }
+ if (m_high != other.m_high && (m_high == null || !m_high.equals(other.m_high)))
+ {
+ return false;
+ }
+ if (m_isHighInclusive != other.m_isHighInclusive)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int hash = 5;
+ hash = 97 * hash + (m_low != null ? m_low.hashCode() : 0);
+ hash = 97 * hash + (m_isLowInclusive ? 1 : 0);
+ hash = 97 * hash + (m_high != null ? m_high.hashCode() : 0);
+ hash = 97 * hash + (m_isHighInclusive ? 1 : 0);
+ return hash;
+ }
+
public String toString()
{
if (m_toString == null)