Improve generic capability/requirement abstraction and prepare for
for new resolver implementation. (FELIX-2036, FELIX-2035)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@918498 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/capabilityset/Attribute.java b/framework/src/main/java/org/apache/felix/framework/capabilityset/Attribute.java
new file mode 100644
index 0000000..531592d
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/capabilityset/Attribute.java
@@ -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.framework.capabilityset;
+
+public class Attribute
+{
+ private final String m_name;
+ private final Object m_value;
+ private final boolean m_isMandatory;
+
+ public Attribute(String name, Object value, boolean isMandatory)
+ {
+ m_name = name;
+ m_value = value;
+ m_isMandatory = isMandatory;
+ }
+
+ public String getName()
+ {
+ return m_name;
+ }
+
+ public Object getValue()
+ {
+ return m_value;
+ }
+
+ public boolean isMandatory()
+ {
+ return m_isMandatory;
+ }
+
+ public String toString()
+ {
+ return m_name + "=" + m_value;
+ }
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/capabilityset/Capability.java b/framework/src/main/java/org/apache/felix/framework/capabilityset/Capability.java
new file mode 100644
index 0000000..7b67209
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/capabilityset/Capability.java
@@ -0,0 +1,40 @@
+/*
+ * 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.framework.capabilityset;
+
+import org.apache.felix.framework.resolver.Module;
+import java.util.List;
+
+public interface Capability
+{
+ static final String MODULE_NAMESPACE = "module";
+ static final String HOST_NAMESPACE = "host";
+ static final String PACKAGE_NAMESPACE = "package";
+
+ public static final String PACKAGE_ATTR = "package";
+ public static final String VERSION_ATTR = "version";
+
+ Module getModule();
+ String getNamespace();
+ Directive getDirective(String name);
+ List<Directive> getDirectives();
+ Attribute getAttribute(String name);
+ List<Attribute> getAttributes();
+ List<String> getUses();
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/capabilityset/Directive.java b/framework/src/main/java/org/apache/felix/framework/capabilityset/Directive.java
new file mode 100644
index 0000000..7a3f481
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/capabilityset/Directive.java
@@ -0,0 +1,46 @@
+/*
+ * 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.framework.capabilityset;
+
+public class Directive
+{
+ private final String m_name;
+ private final Object m_value;
+
+ public Directive(String name, Object value)
+ {
+ m_name = name;
+ m_value = value;
+ }
+
+ public String getName()
+ {
+ return m_name;
+ }
+
+ public Object getValue()
+ {
+ return m_value;
+ }
+
+ public String toString()
+ {
+ return m_name + "=" + m_value;
+ }
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/capabilityset/Requirement.java b/framework/src/main/java/org/apache/felix/framework/capabilityset/Requirement.java
new file mode 100644
index 0000000..e6e789d
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/capabilityset/Requirement.java
@@ -0,0 +1,30 @@
+/*
+ * 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.framework.capabilityset;
+
+import java.util.List;
+
+public interface Requirement
+{
+ String getNamespace();
+ SimpleFilter getFilter();
+ boolean isOptional();
+ Directive getDirective(String name);
+ List<Directive> getDirectives();
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Capability.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Capability.java
deleted file mode 100644
index c87d3bc..0000000
--- a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Capability.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * 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.framework.util.manifestparser;
-
-import java.util.*;
-
-import org.apache.felix.framework.util.Util;
-import org.apache.felix.moduleloader.ICapability;
-import org.apache.felix.moduleloader.IModule;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-
-public class Capability implements ICapability, Comparable
-{
- private final IModule m_module;
- private final String m_namespace;
- private final R4Directive[] m_directives;
- private final R4Attribute[] m_attributes;
- private final String[] m_uses;
- private final String[][] m_includeFilter;
- private final String[][] m_excludeFilter;
- private volatile Map m_attrMap;
-
- // Cached properties for performance reasons.
- private final String m_pkgName;
- private final Version m_pkgVersion;
-
- public Capability(IModule module, String namespace, R4Directive[] dirs, R4Attribute[] attrs)
- {
- m_module = module;
- m_namespace = namespace;
- m_directives = dirs;
- m_attributes = attrs;
-
- // Find all export directives: uses, mandatory, include, and exclude.
- String mandatory = "";
- String[] uses = new String[0];
- String[][] includeFilter = null, excludeFilter = null;
- for (int dirIdx = 0; (m_directives != null) && (dirIdx < m_directives.length); dirIdx++)
- {
- if (m_directives[dirIdx].getName().equals(Constants.USES_DIRECTIVE))
- {
- // Parse these uses directive.
- StringTokenizer tok = new StringTokenizer(m_directives[dirIdx].getValue(), ",");
- uses = new String[tok.countTokens()];
- for (int i = 0; i < uses.length; i++)
- {
- uses[i] = tok.nextToken().trim();
- }
- }
- else if (m_directives[dirIdx].getName().equals(Constants.MANDATORY_DIRECTIVE))
- {
- mandatory = m_directives[dirIdx].getValue();
- }
- else if (m_directives[dirIdx].getName().equals(Constants.INCLUDE_DIRECTIVE))
- {
- String[] ss = ManifestParser.parseDelimitedString(m_directives[dirIdx].getValue(), ",");
- includeFilter = new String[ss.length][];
- for (int filterIdx = 0; filterIdx < ss.length; filterIdx++)
- {
- includeFilter[filterIdx] = Util.parseSubstring(ss[filterIdx]);
- }
- }
- else if (m_directives[dirIdx].getName().equals(Constants.EXCLUDE_DIRECTIVE))
- {
- String[] ss = ManifestParser.parseDelimitedString(m_directives[dirIdx].getValue(), ",");
- excludeFilter = new String[ss.length][];
- for (int filterIdx = 0; filterIdx < ss.length; filterIdx++)
- {
- excludeFilter[filterIdx] = Util.parseSubstring(ss[filterIdx]);
- }
- }
- }
-
- // Set final values.
- m_uses = uses;
- m_includeFilter = includeFilter;
- m_excludeFilter = excludeFilter;
-
- // Parse mandatory directive and mark specified
- // attributes as mandatory.
- StringTokenizer tok = new StringTokenizer(mandatory, ", ");
- while (tok.hasMoreTokens())
- {
- // Get attribute name.
- String attrName = tok.nextToken().trim();
- // Find attribute and mark it as mandatory.
- boolean found = false;
- for (int i = 0; (!found) && (i < m_attributes.length); i++)
- {
- if (m_attributes[i].getName().equals(attrName))
- {
- m_attributes[i] = new R4Attribute(
- m_attributes[i].getName(),
- m_attributes[i].getValue(), true);
- found = true;
- }
- }
- // If a specified mandatory attribute was not found,
- // then error.
- if (!found)
- {
- throw new IllegalArgumentException(
- "Mandatory attribute '" + attrName + "' does not exist.");
- }
- }
-
- // For performance reasons, find the package name and version properties.
- String pkgName = null;
- Version pkgVersion = Version.emptyVersion;
- for (int i = 0; i < m_attributes.length; i++)
- {
- if (m_attributes[i].getName().equals(ICapability.PACKAGE_PROPERTY))
- {
- pkgName = (String) m_attributes[i].getValue();
- }
- else if (m_attributes[i].getName().equals(ICapability.VERSION_PROPERTY))
- {
- pkgVersion = (Version) m_attributes[i].getValue();
- }
- }
-
- // Set final values.
- m_pkgName = pkgName;
- m_pkgVersion = pkgVersion;
- }
-
- public IModule getModule()
- {
- return m_module;
- }
-
- public String getNamespace()
- {
- return m_namespace;
- }
-
-// TODO: RB - Determine how to eliminate these non-generic methods;
-// at least make sure they are not used in the generic resolver.
- public String getPackageName()
- {
- return m_pkgName;
- }
-
- public Version getPackageVersion()
- {
- return m_pkgVersion;
- }
-
- public R4Directive[] getDirectives()
- {
- // TODO: RB - We should return copies of the arrays probably.
- return m_directives;
- }
-
- public R4Attribute[] getAttributes()
- {
- // TODO: RB - We should return copies of the arrays probably.
- return m_attributes;
- }
-
- public String[] getUses()
- {
- // TODO: RB - We should return copies of the arrays probably.
- return m_uses;
- }
-
- public boolean isIncluded(String name)
- {
- if ((m_includeFilter == null) && (m_excludeFilter == null))
- {
- return true;
- }
-
- // Get the class name portion of the target class.
- String className = Util.getClassName(name);
-
- // If there are no include filters then all classes are included
- // by default, otherwise try to find one match.
- boolean included = (m_includeFilter == null);
- for (int i = 0;
- (!included) && (m_includeFilter != null) && (i < m_includeFilter.length);
- i++)
- {
- included = Util.checkSubstring(m_includeFilter[i], className);
- }
-
- // If there are no exclude filters then no classes are excluded
- // by default, otherwise try to find one match.
- boolean excluded = false;
- for (int i = 0;
- (!excluded) && (m_excludeFilter != null) && (i < m_excludeFilter.length);
- i++)
- {
- excluded = Util.checkSubstring(m_excludeFilter[i], className);
- }
- return included && !excluded;
- }
-
-// TODO: RB - Terminology mismatch property vs. attribute.
- public Map getProperties()
- {
- if (m_attrMap == null)
- {
- m_attrMap = new Map() {
-
- public int size()
- {
- // A name and version attribute is always present, since it has a
- // default value.
- return m_attributes.length + 2;
- }
-
- public boolean isEmpty()
- {
- // A version attribute is always present, since it has a
- // default value.
- return false;
- }
-
- public boolean containsKey(Object key)
- {
- return (get(key) != null);
- }
-
- public boolean containsValue(Object value)
- {
- // Check the package name.
- if (m_pkgName.equals(value))
- {
- return true;
- }
-
- // Check the package version.
- if (m_pkgVersion.equals(value))
- {
- return true;
- }
-
- // Check all attributes.
- for (int i = 0; i < m_attributes.length; i++)
- {
- if (m_attributes[i].getValue().equals(value))
- {
- return true;
- }
- }
-
- return false;
- }
-
- public Object get(Object key)
- {
- if (ICapability.PACKAGE_PROPERTY.equals(key))
- {
- return m_pkgName;
- }
- else if (ICapability.VERSION_PROPERTY.equals(key))
- {
- return m_pkgVersion;
- }
-
- for (int i = 0; i < m_attributes.length; i++)
- {
- if (m_attributes[i].getName().equals(key))
- {
- return m_attributes[i].getValue();
- }
- }
-
- return null;
- }
-
- public Object put(Object key, Object value)
- {
- throw new UnsupportedOperationException("Map.put() not implemented.");
- }
-
- public Object remove(Object key)
- {
- throw new UnsupportedOperationException("Map.remove() not implemented.");
- }
-
- public void putAll(Map t)
- {
- throw new UnsupportedOperationException("Map.putAll() not implemented.");
- }
-
- public void clear()
- {
- throw new UnsupportedOperationException("Map.clear() not implemented.");
- }
-
- public Set keySet()
- {
- Set set = new HashSet();
- set.add(ICapability.PACKAGE_PROPERTY);
- set.add(ICapability.VERSION_PROPERTY);
- for (int i = 0; i < m_attributes.length; i++)
- {
- set.add(m_attributes[i].getName());
- }
- return set;
- }
-
- public Collection values()
- {
- throw new UnsupportedOperationException("Map.values() not implemented.");
- }
-
- public Set entrySet()
- {
- throw new UnsupportedOperationException("Map.entrySet() not implemented.");
- }
- };
- }
- return m_attrMap;
- }
-
- public int compareTo(Object o)
- {
- Capability cap = (Capability) o;
- Version thisVersion = null;
- Version version = null;
- if (getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
- {
- thisVersion = getPackageVersion();
- version = cap.getPackageVersion();
- }
- else if (getNamespace().equals(ICapability.MODULE_NAMESPACE))
- {
- thisVersion = (Version) getProperties().get(Constants.BUNDLE_VERSION_ATTRIBUTE);
- version = (Version) cap.getProperties().get(Constants.BUNDLE_VERSION_ATTRIBUTE);
- }
- if ((thisVersion != null) && (version != null))
- {
- int cmp = thisVersion.compareTo(version);
- if (cmp < 0)
- {
- return 1;
- }
- else if (cmp > 0)
- {
- return -1;
- }
- else
- {
- long thisId = m_module.getBundle().getBundleId();
- long id = cap.getModule().getBundle().getBundleId();
- if (thisId < id)
- {
- return -1;
- }
- else if (thisId > id)
- {
- return 1;
- }
- return 0;
- }
- }
- else
- {
- return -1;
- }
- }
-
- public String toString()
- {
- StringBuffer sb = new StringBuffer();
- sb.append(getNamespace());
- for (int i = 0; (m_directives != null) && (i < m_directives.length); i++)
- {
- sb.append(";");
- sb.append(m_directives[i].getName());
- sb.append(":=\"");
- sb.append(m_directives[i].getValue());
- sb.append("\"");
- }
- for (int i = 0; (m_attributes != null) && (i < m_attributes.length); i++)
- {
- sb.append(";");
- sb.append(m_attributes[i].getName());
- sb.append("=\"");
- sb.append(m_attributes[i].getValue());
- sb.append("\"");
- }
- return sb.toString();
- }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/CapabilityImpl.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/CapabilityImpl.java
new file mode 100644
index 0000000..4dd4561
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/CapabilityImpl.java
@@ -0,0 +1,229 @@
+/*
+ * 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.framework.util.manifestparser;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
+import org.apache.felix.framework.capabilityset.Attribute;
+import org.apache.felix.framework.capabilityset.Capability;
+import org.apache.felix.framework.capabilityset.Directive;
+import org.apache.felix.framework.resolver.Module;
+import org.apache.felix.framework.util.Util;
+import org.osgi.framework.Constants;
+
+public class CapabilityImpl implements Capability
+{
+ private final Module m_module;
+ private final String m_namespace;
+ private final List<Directive> m_dirs;
+ private final List<Directive> m_dirsConst;
+ private final List<Attribute> m_attrs;
+ private final List<Attribute> m_attrsConst;
+ private final List<String> m_uses;
+ private final List<List<String>> m_includeFilter;
+ private final List<List<String>> m_excludeFilter;
+
+ public CapabilityImpl(Module module, String namespace,
+ List<Directive> dirs, List<Attribute> attrs)
+ {
+ m_namespace = namespace;
+ m_module = module;
+ m_dirs = dirs;
+ m_dirsConst = Collections.unmodifiableList(m_dirs);
+ m_attrs = attrs;
+ m_attrsConst = Collections.unmodifiableList(m_attrs);
+
+ // Find all export directives: uses, mandatory, include, and exclude.
+ String mandatory = "";
+ List<String> uses = new ArrayList(0);
+ List<List<String>> includeFilter = null, excludeFilter = null;
+ for (int dirIdx = 0; dirIdx < m_dirs.size(); dirIdx++)
+ {
+ if (m_dirs.get(dirIdx).getName().equals(Constants.USES_DIRECTIVE))
+ {
+ // Parse these uses directive.
+ StringTokenizer tok = new StringTokenizer(
+ (String) m_dirs.get(dirIdx).getValue(), ",");
+ uses = new ArrayList<String>(tok.countTokens());
+ while (tok.hasMoreTokens())
+ {
+ uses.add(tok.nextToken().trim());
+ }
+ }
+ else if (m_dirs.get(dirIdx).getName().equals(Constants.MANDATORY_DIRECTIVE))
+ {
+ mandatory = (String) m_dirs.get(dirIdx).getValue();
+ }
+ else if (m_dirs.get(dirIdx).getName().equals(Constants.INCLUDE_DIRECTIVE)
+ || m_dirs.get(dirIdx).getName().equals(Constants.EXCLUDE_DIRECTIVE))
+ {
+ List<List<String>> filterList = null;
+
+ List<String> filters = ManifestParser.parseDelimitedString(
+ (String) m_dirs.get(dirIdx).getValue(), ",");
+ filterList = new ArrayList<List<String>>(filters.size());
+
+ for (int filterIdx = 0; filterIdx < filters.size(); filterIdx++)
+ {
+ List<String> substrings = Util.parseSubstring(filters.get(filterIdx));
+ filterList.add(substrings);
+ }
+
+ if (m_dirs.get(dirIdx).getName().equals(Constants.INCLUDE_DIRECTIVE))
+ {
+ includeFilter = filterList;
+ }
+ else
+ {
+ excludeFilter = filterList;
+ }
+ }
+ }
+
+ // Set final values.
+ m_uses = uses;
+ m_includeFilter = includeFilter;
+ m_excludeFilter = excludeFilter;
+
+ // Parse mandatory directive and mark specified
+ // attributes as mandatory.
+ StringTokenizer tok = new StringTokenizer(mandatory, ", ");
+ while (tok.hasMoreTokens())
+ {
+ // Get attribute name.
+ String attrName = tok.nextToken().trim();
+ // Find attribute and mark it as mandatory.
+ boolean found = false;
+ for (int i = 0; (!found) && (i < m_attrs.size()); i++)
+ {
+ if (m_attrs.get(i).getName().equals(attrName))
+ {
+ m_attrs.set(i, new Attribute(
+ m_attrs.get(i).getName(),
+ m_attrs.get(i).getValue(), true));
+ found = true;
+ }
+ }
+ // If a specified mandatory attribute was not found,
+ // then error.
+ if (!found)
+ {
+ throw new IllegalArgumentException(
+ "Mandatory attribute '" + attrName + "' does not exist.");
+ }
+ }
+ }
+
+ public Module getModule()
+ {
+ return m_module;
+ }
+
+ public String getNamespace()
+ {
+ return m_namespace;
+ }
+
+ public Directive getDirective(String name)
+ {
+ for (int i = 0; i < m_dirs.size(); i++)
+ {
+ if (m_dirs.get(i).getName().equals(name))
+ {
+ return m_dirs.get(i);
+ }
+ }
+ return null;
+ }
+
+ public List<Directive> getDirectives()
+ {
+ return m_dirsConst;
+ }
+
+ public Attribute getAttribute(String name)
+ {
+ for (int i = 0; i < m_attrs.size(); i++)
+ {
+ if (m_attrs.get(i).getName().equals(name))
+ {
+ return m_attrs.get(i);
+ }
+ }
+ return null;
+ }
+
+ public List<Attribute> getAttributes()
+ {
+ return m_attrsConst;
+ }
+
+ public List<String> getUses()
+ {
+ return m_uses;
+ }
+
+ public boolean isIncluded(String name)
+ {
+ if ((m_includeFilter == null) && (m_excludeFilter == null))
+ {
+ return true;
+ }
+
+ // Get the class name portion of the target class.
+ String className = Util.getClassName(name);
+
+ // If there are no include filters then all classes are included
+ // by default, otherwise try to find one match.
+ boolean included = (m_includeFilter == null);
+ for (int i = 0;
+ (!included) && (m_includeFilter != null) && (i < m_includeFilter.size());
+ i++)
+ {
+ included = Util.checkSubstring(m_includeFilter.get(i), className);
+ }
+
+ // If there are no exclude filters then no classes are excluded
+ // by default, otherwise try to find one match.
+ boolean excluded = false;
+ for (int i = 0;
+ (!excluded) && (m_excludeFilter != null) && (i < m_excludeFilter.size());
+ i++)
+ {
+ excluded = Util.checkSubstring(m_excludeFilter.get(i), className);
+ }
+ return included && !excluded;
+ }
+
+ public String toString()
+ {
+ if (m_module == null)
+ {
+ return m_attrs.toString();
+ }
+ if (m_namespace.equals(Capability.PACKAGE_NAMESPACE))
+ {
+ return "[" + m_module + "] "
+ + m_namespace + "; " + getAttribute(Capability.PACKAGE_ATTR);
+ }
+ return "[" + m_module + "] " + m_namespace + "; " + m_attrs;
+ }
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
index f9d9809..0d21277 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
@@ -19,13 +19,17 @@
package org.apache.felix.framework.util.manifestparser;
import java.util.*;
+import java.util.ArrayList;
+import java.util.Map.Entry;
import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.capabilityset.Capability;
+import org.apache.felix.framework.capabilityset.Attribute;
+import org.apache.felix.framework.capabilityset.Directive;
+import org.apache.felix.framework.resolver.Module;
+import org.apache.felix.framework.capabilityset.Requirement;
import org.apache.felix.framework.util.FelixConstants;
import org.apache.felix.framework.util.VersionRange;
-import org.apache.felix.moduleloader.ICapability;
-import org.apache.felix.moduleloader.IModule;
-import org.apache.felix.moduleloader.IRequirement;
import org.osgi.framework.*;
public class ManifestParser
@@ -33,19 +37,19 @@
private final Logger m_logger;
private final Map m_configMap;
private final Map m_headerMap;
- private volatile int m_activationPolicy = IModule.EAGER_ACTIVATION;
+ private volatile int m_activationPolicy = Module.EAGER_ACTIVATION;
private volatile String m_activationIncludeDir;
private volatile String m_activationExcludeDir;
private volatile boolean m_isExtension = false;
private volatile String m_bundleSymbolicName;
private volatile Version m_bundleVersion;
- private volatile ICapability[] m_capabilities;
- private volatile IRequirement[] m_requirements;
- private volatile IRequirement[] m_dynamicRequirements;
- private volatile R4LibraryClause[] m_libraryHeaders;
+ private volatile List<Capability> m_capabilities;
+ private volatile List<Requirement> m_requirements;
+ private volatile List<Requirement> m_dynamicRequirements;
+ private volatile List<R4LibraryClause> m_libraryClauses;
private volatile boolean m_libraryHeadersOptional = false;
- public ManifestParser(Logger logger, Map configMap, IModule owner, Map headerMap)
+ public ManifestParser(Logger logger, Map configMap, Module owner, Map headerMap)
throws BundleException
{
m_logger = logger;
@@ -61,8 +65,7 @@
}
// Create lists to hold capabilities and requirements.
- List capList = new ArrayList();
- List reqList = new ArrayList();
+ List<Capability> capList = new ArrayList();
//
// Parse bundle version.
@@ -90,11 +93,11 @@
// Parse bundle symbolic name.
//
- ICapability moduleCap = parseBundleSymbolicName(owner, m_headerMap);
+ Capability moduleCap = parseBundleSymbolicName(owner, m_headerMap);
if (moduleCap != null)
{
m_bundleSymbolicName = (String)
- moduleCap.getProperties().get(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE);
+ moduleCap.getAttribute(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE).getValue();
// Add a module capability and a host capability to all
// non-fragment bundles. A host capability is the same
@@ -105,140 +108,111 @@
if (headerMap.get(Constants.FRAGMENT_HOST) == null)
{
capList.add(moduleCap);
- capList.add(new Capability(
- owner, ICapability.HOST_NAMESPACE, null,
- ((Capability) moduleCap).getAttributes()));
+ capList.add(new CapabilityImpl(
+ owner, Capability.HOST_NAMESPACE, new ArrayList<Directive>(0),
+ ((CapabilityImpl) moduleCap).getAttributes()));
}
}
+ // Verify that bundle symbolic name is specified.
+ if (getManifestVersion().equals("2") && (m_bundleSymbolicName == null))
+ {
+ throw new BundleException(
+ "R4 bundle manifests must include bundle symbolic name.");
+ }
+
+ //
+ // Parse Fragment-Host.
+ //
+
+ List<Requirement> hostReqs = parseFragmentHost(m_logger, m_headerMap);
+
+ //
+ // Parse Require-Bundle
+ //
+
+ List<ParsedHeaderClause> requireClauses =
+ parseStandardHeader((String) headerMap.get(Constants.REQUIRE_BUNDLE));
+ requireClauses = normalizeRequireClauses(m_logger, requireClauses, getManifestVersion());
+ List<Requirement> requireReqs = convertRequires(requireClauses);
+
+ //
+ // Parse Import-Package.
+ //
+
+ List<ParsedHeaderClause> importClauses =
+ parseStandardHeader((String) headerMap.get(Constants.IMPORT_PACKAGE));
+ importClauses = normalizeImportClauses(m_logger, importClauses, getManifestVersion());
+ List<Requirement> importReqs = convertImports(importClauses);
+
+ //
+ // Parse DynamicImport-Package.
+ //
+
+ List<ParsedHeaderClause> dynamicClauses =
+ parseStandardHeader((String) headerMap.get(Constants.DYNAMICIMPORT_PACKAGE));
+ dynamicClauses = normalizeDynamicImportClauses(m_logger, dynamicClauses, getManifestVersion());
+ m_dynamicRequirements = convertImports(dynamicClauses);
+
//
// Parse Export-Package.
//
// Get exported packages from bundle manifest.
- ICapability[] exportCaps = parseExportHeader(
- owner, (String) headerMap.get(Constants.EXPORT_PACKAGE));
+ List<ParsedHeaderClause> exportClauses =
+ parseStandardHeader((String) headerMap.get(Constants.EXPORT_PACKAGE));
+ exportClauses = normalizeExportClauses(logger, exportClauses,
+ getManifestVersion(), m_bundleSymbolicName, m_bundleVersion);
+ List<Capability> exportCaps = convertExports(exportClauses, owner);
- // Verify that "java.*" packages are not exported.
- for (int capIdx = 0; capIdx < exportCaps.length; capIdx++)
+ //
+ // Calculate implicit imports.
+ //
+
+ if (!getManifestVersion().equals("2"))
{
- // Verify that the named package has not already been declared.
- String pkgName = (String)
- exportCaps[capIdx].getProperties().get(ICapability.PACKAGE_PROPERTY);
- // Verify that java.* packages are not exported.
- if (pkgName.startsWith("java."))
- {
- throw new BundleException(
- "Exporting java.* packages not allowed: " + pkgName);
- }
- capList.add(exportCaps[capIdx]);
+ List<ParsedHeaderClause> implicitClauses =
+ calculateImplicitImports(exportCaps, importClauses);
+ importReqs.addAll(convertImports(implicitClauses));
+
+ List<ParsedHeaderClause> allImportClauses =
+ new ArrayList<ParsedHeaderClause>(implicitClauses.size() + importClauses.size());
+ allImportClauses.addAll(importClauses);
+ allImportClauses.addAll(implicitClauses);
+
+ exportCaps = calculateImplicitUses(exportCaps, allImportClauses);
}
- // Create an array of all capabilities.
- m_capabilities = (ICapability[]) capList.toArray(new ICapability[capList.size()]);
+ // Combine all capabilities.
+ m_capabilities = new ArrayList(
+ capList.size() + exportCaps.size());
+ m_capabilities.addAll(capList);
+ m_capabilities.addAll(exportCaps);
- //
- // Parse Fragment-Host.
- //
-
- IRequirement req = parseFragmentHost(m_logger, m_headerMap);
- if (req != null)
- {
- reqList.add(req);
- }
-
- //
- // Parse Require-Bundle
- //
-
- IRequirement[] bundleReq = parseRequireBundleHeader(
- (String) headerMap.get(Constants.REQUIRE_BUNDLE));
- for (int reqIdx = 0; reqIdx < bundleReq.length; reqIdx++)
- {
- reqList.add(bundleReq[reqIdx]);
- }
-
- //
- // Parse Import-Package.
- //
-
- // Get import packages from bundle manifest.
- IRequirement[] importReqs = parseImportHeader(
- (String) headerMap.get(Constants.IMPORT_PACKAGE));
-
- // Verify there are no duplicate import declarations.
- Set dupeSet = new HashSet();
- for (int reqIdx = 0; reqIdx < importReqs.length; reqIdx++)
- {
- // Verify that the named package has not already been declared.
- String pkgName = ((Requirement) importReqs[reqIdx]).getTargetName();
- if (!dupeSet.contains(pkgName))
- {
- // Verify that java.* packages are not imported.
- if (pkgName.startsWith("java."))
- {
- throw new BundleException(
- "Importing java.* packages not allowed: " + pkgName);
- }
- dupeSet.add(pkgName);
- }
- else
- {
- throw new BundleException("Duplicate import - " + pkgName);
- }
- // If it has not already been imported, then add it to the list
- // of requirements.
- reqList.add(importReqs[reqIdx]);
- }
-
- // Create an array of all requirements.
- m_requirements = (IRequirement[]) reqList.toArray(new IRequirement[reqList.size()]);
-
- //
- // Parse DynamicImport-Package.
- //
-
- // Get dynamic import packages from bundle manifest.
- m_dynamicRequirements = parseImportHeader(
- (String) headerMap.get(Constants.DYNAMICIMPORT_PACKAGE));
-
- // Dynamic imports can have duplicates, so just check for import
- // of java.*.
- for (int reqIdx = 0; reqIdx < m_dynamicRequirements.length; reqIdx++)
- {
- // Verify that java.* packages are not imported.
- String pkgName = ((Requirement) m_dynamicRequirements[reqIdx]).getTargetName();
- if (pkgName.startsWith("java."))
- {
- throw new BundleException(
- "Dynamically importing java.* packages not allowed: " + pkgName);
- }
- else if (!pkgName.equals("*") && pkgName.endsWith("*") && !pkgName.endsWith(".*"))
- {
- throw new BundleException(
- "Partial package name wild carding is not allowed: " + pkgName);
- }
- }
+ // Combine all requirements.
+ m_requirements = new ArrayList(
+ importReqs.size() + requireReqs.size() + hostReqs.size());
+ m_requirements.addAll(importReqs);
+ m_requirements.addAll(requireReqs);
+ m_requirements.addAll(hostReqs);
//
// Parse Bundle-NativeCode.
//
// Get native library entry names for module library sources.
- m_libraryHeaders =
+ m_libraryClauses =
parseLibraryStrings(
m_logger,
parseDelimitedString((String) m_headerMap.get(Constants.BUNDLE_NATIVECODE), ","));
// Check to see if there was an optional native library clause, which is
// represented by a null library header; if so, record it and remove it.
- if ((m_libraryHeaders.length > 0) &&
- (m_libraryHeaders[m_libraryHeaders.length - 1].getLibraryEntries() == null))
+ if ((m_libraryClauses.size() > 0) &&
+ (m_libraryClauses.get(m_libraryClauses.size() - 1).getLibraryEntries() == null))
{
m_libraryHeadersOptional = true;
- R4LibraryClause[] tmp = new R4LibraryClause[m_libraryHeaders.length - 1];
- System.arraycopy(m_libraryHeaders, 0, tmp, 0, m_libraryHeaders.length - 1);
- m_libraryHeaders = tmp;
+ m_libraryClauses.remove(m_libraryClauses.size() - 1);
}
//
@@ -249,15 +223,450 @@
// m_excludedPolicyClasses.
parseActivationPolicy(headerMap);
- // Do final checks and normalization of manifest.
- if (getManifestVersion().equals("2"))
+ m_isExtension = checkExtensionBundle(headerMap);
+ }
+
+ private static List<ParsedHeaderClause> normalizeImportClauses(
+ Logger logger, List<ParsedHeaderClause> clauses, String mv)
+ throws BundleException
+ {
+ // Verify that the values are equals if the package specifies
+ // both version and specification-version attributes.
+ Map<String, Attribute> attrMap = new HashMap();
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
{
- checkAndNormalizeR4();
+ // Put attributes for current clause in a map for easy lookup.
+ attrMap.clear();
+ for (int attrIdx = 0;
+ attrIdx < clauses.get(clauseIdx).m_attrs.size();
+ attrIdx++)
+ {
+ Attribute attr = clauses.get(clauseIdx).m_attrs.get(attrIdx);
+ attrMap.put(attr.getName(), attr);
+ }
+
+ // Check for "version" and "specification-version" attributes
+ // and verify they are the same if both are specified.
+ Attribute v = attrMap.get(Constants.VERSION_ATTRIBUTE);
+ Attribute sv = attrMap.get(Constants.PACKAGE_SPECIFICATION_VERSION);
+ if ((v != null) && (sv != null))
+ {
+ // Verify they are equal.
+ if (!((String) v.getValue()).trim().equals(((String) sv.getValue()).trim()))
+ {
+ throw new IllegalArgumentException(
+ "Both version and specification-version are specified, but they are not equal.");
+ }
+ }
+
+ // Ensure that only the "version" attribute is used and convert
+ // it to the VersionRange type.
+ if ((v != null) || (sv != null))
+ {
+ attrMap.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+ v = (v == null) ? sv : v;
+ attrMap.put(Constants.VERSION_ATTRIBUTE,
+ new Attribute(
+ Constants.VERSION_ATTRIBUTE,
+ VersionRange.parse(v.getValue().toString()),
+ v.isMandatory()));
+ }
+
+ // If bundle version is specified, then convert its type to VersionRange.
+ v = attrMap.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+ if (v != null)
+ {
+ attrMap.put(Constants.BUNDLE_VERSION_ATTRIBUTE,
+ new Attribute(
+ Constants.BUNDLE_VERSION_ATTRIBUTE,
+ VersionRange.parse(v.getValue().toString()),
+ v.isMandatory()));
+ }
+
+ // Re-copy the attributes in case they changed.
+ clauses.get(clauseIdx).m_attrs.clear();
+ clauses.get(clauseIdx).m_attrs.addAll(attrMap.values());
}
- else
+
+ // Verify java.* is not imported, nor any duplicate imports.
+ Set dupeSet = new HashSet();
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
{
- checkAndNormalizeR3();
+ // Verify that the named package has not already been declared.
+ List<String> paths = clauses.get(clauseIdx).m_paths;
+ for (int pathIdx = 0; pathIdx < paths.size(); pathIdx++)
+ {
+ String pkgName = paths.get(pathIdx);
+ if (!dupeSet.contains(pkgName))
+ {
+ // Verify that java.* packages are not imported.
+ if (pkgName.startsWith("java."))
+ {
+ throw new BundleException(
+ "Importing java.* packages not allowed: " + pkgName);
+ }
+ // Make sure a package name was specified.
+ else if (clauses.get(clauseIdx).m_paths.get(pathIdx).length() == 0)
+ {
+ throw new BundleException(
+ "Imported package names cannot be zero length.");
+ }
+ dupeSet.add(pkgName);
+ }
+ else
+ {
+ throw new BundleException("Duplicate import: " + pkgName);
+ }
+ }
}
+
+ if (!mv.equals("2"))
+ {
+ // Check to make sure that R3 bundles have only specified
+ // the 'specification-version' attribute and no directives
+ // on their imports; ignore all unknown attributes.
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
+ {
+ // R3 bundles cannot have directives on their imports.
+ if (clauses.get(clauseIdx).m_dirs.size() != 0)
+ {
+ throw new BundleException("R3 imports cannot contain directives.");
+ }
+
+ // Remove and ignore all attributes other than version.
+ // NOTE: This is checking for "version" rather than "specification-version"
+ // because the package class normalizes to "version" to avoid having
+ // future special cases. This could be changed if more strict behavior
+ // is required.
+ if (clauses.get(clauseIdx).m_attrs.size() != 0)
+ {
+ // R3 package requirements should only have version attributes.
+ Attribute pkgVersion =
+ new Attribute(Capability.VERSION_ATTR,
+ new VersionRange(Version.emptyVersion, true, null, true), false);
+ for (int attrIdx = 0;
+ attrIdx < clauses.get(clauseIdx).m_attrs.size();
+ attrIdx++)
+ {
+ if (clauses.get(clauseIdx).m_attrs.get(attrIdx)
+ .getName().equals(Capability.VERSION_ATTR))
+ {
+ pkgVersion = clauses.get(clauseIdx).m_attrs.get(attrIdx);
+ }
+ else
+ {
+ logger.log(Logger.LOG_WARNING,
+ "Unknown R3 import attribute: "
+ + clauses.get(clauseIdx).m_attrs.get(attrIdx).getName());
+ }
+ }
+
+ // Recreate the import to remove any other attributes
+ // and add version if missing.
+ ArrayList<Attribute> attrs = new ArrayList<Attribute>(1);
+ attrs.add(pkgVersion);
+ clauses.set(clauseIdx, new ParsedHeaderClause(
+ clauses.get(clauseIdx).m_paths,
+ clauses.get(clauseIdx).m_dirs,
+ attrs));
+ }
+ }
+ }
+
+ return clauses;
+ }
+
+ private static List<Requirement> convertImports(List<ParsedHeaderClause> clauses)
+ {
+ // Now convert generic header clauses into requirements.
+ List reqList = new ArrayList();
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
+ {
+ for (int pathIdx = 0;
+ pathIdx < clauses.get(clauseIdx).m_paths.size();
+ pathIdx++)
+ {
+ // Prepend the package name to the array of attributes.
+ List<Attribute> attrs = clauses.get(clauseIdx).m_attrs;
+ List<Attribute> newAttrs = new ArrayList<Attribute>(attrs.size() + 1);
+ newAttrs.add(new Attribute(
+ Capability.PACKAGE_ATTR,
+ clauses.get(clauseIdx).m_paths.get(pathIdx), false));
+ newAttrs.addAll(attrs);
+
+ // Create package requirement and add to requirement list.
+ reqList.add(
+ new RequirementImpl(
+ Capability.PACKAGE_NAMESPACE,
+ clauses.get(clauseIdx).m_dirs,
+ newAttrs));
+ }
+ }
+
+ return reqList;
+ }
+
+ private static List<ParsedHeaderClause> normalizeDynamicImportClauses(
+ Logger logger, List<ParsedHeaderClause> clauses, String mv)
+ throws BundleException
+ {
+ // Verify that the values are equals if the package specifies
+ // both version and specification-version attributes.
+ Map<String, Attribute> attrMap = new HashMap();
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
+ {
+ // Put attributes for current clause in a map for easy lookup.
+ attrMap.clear();
+ for (int attrIdx = 0;
+ attrIdx < clauses.get(clauseIdx).m_attrs.size();
+ attrIdx++)
+ {
+ Attribute attr = clauses.get(clauseIdx).m_attrs.get(attrIdx);
+ attrMap.put(attr.getName(), attr);
+ }
+
+ // Check for "version" and "specification-version" attributes
+ // and verify they are the same if both are specified.
+ Attribute v = attrMap.get(Constants.VERSION_ATTRIBUTE);
+ Attribute sv = attrMap.get(Constants.PACKAGE_SPECIFICATION_VERSION);
+ if ((v != null) && (sv != null))
+ {
+ // Verify they are equal.
+ if (!((String) v.getValue()).trim().equals(((String) sv.getValue()).trim()))
+ {
+ throw new IllegalArgumentException(
+ "Both version and specification-version are specified, but they are not equal.");
+ }
+ }
+
+ // Ensure that only the "version" attribute is used and convert
+ // it to the VersionRange type.
+ if ((v != null) || (sv != null))
+ {
+ attrMap.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+ v = (v == null) ? sv : v;
+ attrMap.put(Constants.VERSION_ATTRIBUTE,
+ new Attribute(
+ Constants.VERSION_ATTRIBUTE,
+ VersionRange.parse(v.getValue().toString()),
+ v.isMandatory()));
+ }
+
+ // If bundle version is specified, then convert its type to VersionRange.
+ v = attrMap.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+ if (v != null)
+ {
+ attrMap.put(Constants.BUNDLE_VERSION_ATTRIBUTE,
+ new Attribute(
+ Constants.BUNDLE_VERSION_ATTRIBUTE,
+ VersionRange.parse(v.getValue().toString()),
+ v.isMandatory()));
+ }
+
+ // Re-copy the attributes in case they changed.
+ clauses.get(clauseIdx).m_attrs.clear();
+ clauses.get(clauseIdx).m_attrs.addAll(attrMap.values());
+ }
+
+ // Dynamic imports can have duplicates, so just check for import
+ // of java.*.
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
+ {
+ // Verify that java.* packages are not imported.
+ List<String> paths = clauses.get(clauseIdx).m_paths;
+ for (int pathIdx = 0; pathIdx < paths.size(); pathIdx++)
+ {
+ String pkgName = paths.get(pathIdx);
+ if (pkgName.startsWith("java."))
+ {
+ throw new BundleException(
+ "Dynamically importing java.* packages not allowed: " + pkgName);
+ }
+ else if (!pkgName.equals("*") && pkgName.endsWith("*") && !pkgName.endsWith(".*"))
+ {
+ throw new BundleException(
+ "Partial package name wild carding is not allowed: " + pkgName);
+ }
+ }
+ }
+
+ if (!mv.equals("2"))
+ {
+ // Check to make sure that R3 bundles have only specified
+ // the 'specification-version' attribute and no directives
+ // on their imports; ignore all unknown attributes.
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
+ {
+ // R3 bundles cannot have directives on their imports.
+ if (clauses.get(clauseIdx).m_dirs.size() != 0)
+ {
+ throw new BundleException("R3 imports cannot contain directives.");
+ }
+ }
+ }
+
+ return clauses;
+ }
+
+ private static List<ParsedHeaderClause> normalizeExportClauses(
+ Logger logger, List<ParsedHeaderClause> clauses,
+ String mv, String bsn, Version bv)
+ throws BundleException
+ {
+ // Verify that "java.*" packages are not exported.
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
+ {
+ // Verify that the named package has not already been declared.
+ for (int pathIdx = 0; pathIdx < clauses.get(clauseIdx).m_paths.size(); pathIdx++)
+ {
+ // Verify that java.* packages are not exported.
+ if (clauses.get(clauseIdx).m_paths.get(pathIdx).startsWith("java."))
+ {
+ throw new BundleException(
+ "Exporting java.* packages not allowed: "
+ + clauses.get(clauseIdx).m_paths.get(pathIdx));
+ }
+ else if (clauses.get(clauseIdx).m_paths.get(pathIdx).length() == 0)
+ {
+ throw new BundleException(
+ "Exported package names cannot be zero length.");
+ }
+ }
+ }
+
+ // If both version and specification-version attributes are specified,
+ // then verify that the values are equal.
+ Map<String, Attribute> attrMap = new HashMap();
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
+ {
+ // Put attributes for current clause in a map for easy lookup.
+ attrMap.clear();
+ for (int attrIdx = 0;
+ attrIdx < clauses.get(clauseIdx).m_attrs.size();
+ attrIdx++)
+ {
+ Attribute attr = clauses.get(clauseIdx).m_attrs.get(attrIdx);
+ attrMap.put(attr.getName(), attr);
+ }
+
+ // Check for "version" and "specification-version" attributes
+ // and verify they are the same if both are specified.
+ Attribute v = attrMap.get(Constants.VERSION_ATTRIBUTE);
+ Attribute sv = attrMap.get(Constants.PACKAGE_SPECIFICATION_VERSION);
+ if ((v != null) && (sv != null))
+ {
+ // Verify they are equal.
+ if (!((String) v.getValue()).trim().equals(((String) sv.getValue()).trim()))
+ {
+ throw new IllegalArgumentException(
+ "Both version and specification-version are specified, but they are not equal.");
+ }
+ }
+
+ // Always add the default version if not specified.
+ if ((v == null) && (sv == null))
+ {
+ v = new Attribute(
+ Constants.VERSION_ATTRIBUTE, Version.emptyVersion, false);
+ }
+
+ // Ensure that only the "version" attribute is used and convert
+ // it to the appropriate type.
+ if ((v != null) || (sv != null))
+ {
+ // Convert version attribute to type Version.
+ attrMap.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+ v = (v == null) ? sv : v;
+ attrMap.put(Constants.VERSION_ATTRIBUTE,
+ new Attribute(
+ Constants.VERSION_ATTRIBUTE,
+ Version.parseVersion(v.getValue().toString()),
+ v.isMandatory()));
+
+ // Re-copy the attributes since they have changed.
+ clauses.get(clauseIdx).m_attrs.clear();
+ clauses.get(clauseIdx).m_attrs.addAll(attrMap.values());
+ }
+ }
+
+ // If this is an R4 bundle, then make sure it doesn't specify
+ // bundle symbolic name or bundle version attributes.
+ if (mv.equals("2"))
+ {
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
+ {
+ // R3 package capabilities should only have a version attribute.
+ List<Attribute> attrs = clauses.get(clauseIdx).m_attrs;
+ for (int attrIdx = 0; attrIdx < attrs.size(); attrIdx++)
+ {
+ // Find symbolic name and version attribute, if present.
+ if (attrs.get(attrIdx).getName().equals(Constants.BUNDLE_VERSION_ATTRIBUTE) ||
+ attrs.get(attrIdx).getName().equals(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE))
+ {
+ throw new BundleException(
+ "Exports must not specify bundle symbolic name or bundle version.");
+ }
+ }
+
+ // Now that we know that there are no bundle symbolic name and version
+ // attributes, add them since the spec says they are there implicitly.
+ attrs.add(new Attribute(
+ Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, bsn, false));
+ attrs.add(new Attribute(
+ Constants.BUNDLE_VERSION_ATTRIBUTE, bv, false));
+ ((ArrayList) attrs).trimToSize();
+ }
+ }
+ else if (!mv.equals("2"))
+ {
+ // Check to make sure that R3 bundles have only specified
+ // the 'specification-version' attribute and no directives
+ // on their exports; ignore all unknown attributes.
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
+ {
+ // R3 bundles cannot have directives on their exports.
+ if (clauses.get(clauseIdx).m_dirs.size() != 0)
+ {
+ throw new BundleException("R3 exports cannot contain directives.");
+ }
+
+ // Remove and ignore all attributes other than version.
+ // NOTE: This is checking for "version" rather than "specification-version"
+ // because the package class normalizes to "version" to avoid having
+ // future special cases. This could be changed if more strict behavior
+ // is required.
+ if (clauses.get(clauseIdx).m_attrs.size() != 0)
+ {
+ // R3 package capabilities should only have a version attribute.
+ List<Attribute> attrs = clauses.get(clauseIdx).m_attrs;
+ Attribute pkgVersion = new Attribute(Capability.VERSION_ATTR, Version.emptyVersion, false);
+ for (int attrIdx = 0; attrIdx < attrs.size(); attrIdx++)
+ {
+ if (attrs.get(attrIdx).getName().equals(Capability.VERSION_ATTR))
+ {
+ pkgVersion = attrs.get(attrIdx);
+ }
+ else
+ {
+ logger.log(
+ Logger.LOG_WARNING,
+ "Unknown R3 export attribute: "
+ + attrs.get(attrIdx).getName());
+ }
+ }
+
+ // Recreate the export to remove any other attributes
+ // and add version if missing.
+ List<Attribute> newAttrs = new ArrayList<Attribute>(2);
+ newAttrs.add(pkgVersion);
+ clauses.set(clauseIdx, new ParsedHeaderClause(
+ clauses.get(clauseIdx).m_paths,
+ clauses.get(clauseIdx).m_dirs,
+ newAttrs));
+ }
+ }
+ }
+ return clauses;
}
public String getManifestVersion()
@@ -302,24 +711,24 @@
return m_bundleVersion;
}
- public ICapability[] getCapabilities()
+ public List<Capability> getCapabilities()
{
return m_capabilities;
}
- public IRequirement[] getRequirements()
+ public List<Requirement> getRequirements()
{
return m_requirements;
}
- public IRequirement[] getDynamicRequirements()
+ public List<Requirement> getDynamicRequirements()
{
return m_dynamicRequirements;
}
- public R4LibraryClause[] getLibraryClauses()
+ public List<R4LibraryClause> getLibraryClauses()
{
- return m_libraryHeaders;
+ return m_libraryClauses;
}
/**
@@ -348,18 +757,18 @@
* @return <tt>null</tt> if there are no native libraries, a zero-length
* array if no libraries matched, or an array of selected libraries.
**/
- public R4Library[] getLibraries()
+ public List<R4Library> getLibraries()
{
- R4Library[] libs = null;
+ ArrayList<R4Library> libs = null;
try
{
R4LibraryClause clause = getSelectedLibraryClause();
if (clause != null)
{
String[] entries = clause.getLibraryEntries();
- libs = new R4Library[entries.length];
+ libs = new ArrayList<R4Library>(entries.length);
int current = 0;
- for (int i = 0; i < libs.length; i++)
+ for (int i = 0; i < entries.length; i++)
{
String name = getName(entries[i]);
boolean found = false;
@@ -369,23 +778,18 @@
}
if (!found)
{
- libs[current++] = new R4Library(
+ libs.add(new R4Library(
clause.getLibraryEntries()[i],
clause.getOSNames(), clause.getProcessors(), clause.getOSVersions(),
- clause.getLanguages(), clause.getSelectionFilter());
+ clause.getLanguages(), clause.getSelectionFilter()));
}
}
- if (current < libs.length)
- {
- R4Library[] tmp = new R4Library[current];
- System.arraycopy(libs, 0, tmp, 0, current);
- libs = tmp;
- }
+ libs.trimToSize();
}
}
catch (Exception ex)
{
- libs = new R4Library[0];
+ libs = new ArrayList<R4Library>(0);
}
return libs;
}
@@ -402,16 +806,16 @@
private R4LibraryClause getSelectedLibraryClause() throws BundleException
{
- if ((m_libraryHeaders != null) && (m_libraryHeaders.length > 0))
+ if ((m_libraryClauses != null) && (m_libraryClauses.size() > 0))
{
List clauseList = new ArrayList();
// Search for matching native clauses.
- for (int i = 0; i < m_libraryHeaders.length; i++)
+ for (int i = 0; i < m_libraryClauses.size(); i++)
{
- if (m_libraryHeaders[i].match(m_configMap))
+ if (m_libraryClauses.get(i).match(m_configMap))
{
- clauseList.add(m_libraryHeaders[i]);
+ clauseList.add(m_libraryClauses.get(i));
}
}
@@ -468,9 +872,9 @@
for (int k = 0; (osversions != null) && (k < osversions.length); k++)
{
VersionRange range = VersionRange.parse(osversions[k]);
- if ((range.getLow()).compareTo(osVersionRangeMaxFloor) >= 0)
+ if ((range.getFloor()).compareTo(osVersionRangeMaxFloor) >= 0)
{
- osVersionRangeMaxFloor = range.getLow();
+ osVersionRangeMaxFloor = range.getFloor();
}
}
}
@@ -492,7 +896,7 @@
for (int k = 0; k < osversions.length; k++)
{
VersionRange range = VersionRange.parse(osversions[k]);
- if ((range.getLow()).compareTo(osVersionRangeMaxFloor) >= 0)
+ if ((range.getFloor()).compareTo(osVersionRangeMaxFloor) >= 0)
{
selection.add("" + indexList.get(i));
}
@@ -541,306 +945,130 @@
}
}
- private void checkAndNormalizeR3() throws BundleException
+ private static List<ParsedHeaderClause> calculateImplicitImports(
+ List<Capability> exports, List<ParsedHeaderClause> imports)
+ throws BundleException
{
- // Check to make sure that R3 bundles have only specified
- // the 'specification-version' attribute and no directives
- // on their exports; ignore all unknown attributes.
- for (int capIdx = 0;
- (m_capabilities != null) && (capIdx < m_capabilities.length);
- capIdx++)
- {
- if (m_capabilities[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
- {
- // R3 bundles cannot have directives on their exports.
- if (((Capability) m_capabilities[capIdx]).getDirectives().length != 0)
- {
- throw new BundleException("R3 exports cannot contain directives.");
- }
-
- // Remove and ignore all attributes other than version.
- // NOTE: This is checking for "version" rather than "specification-version"
- // because the package class normalizes to "version" to avoid having
- // future special cases. This could be changed if more strict behavior
- // is required.
- if (((Capability) m_capabilities[capIdx]).getAttributes() != null)
- {
- // R3 package capabilities should only have name and
- // version attributes.
- R4Attribute pkgName = null;
- R4Attribute pkgVersion = new R4Attribute(ICapability.VERSION_PROPERTY, Version.emptyVersion, false);
- for (int attrIdx = 0;
- attrIdx < ((Capability) m_capabilities[capIdx]).getAttributes().length;
- attrIdx++)
- {
- if (((Capability) m_capabilities[capIdx]).getAttributes()[attrIdx]
- .getName().equals(ICapability.PACKAGE_PROPERTY))
- {
- pkgName = ((Capability) m_capabilities[capIdx]).getAttributes()[attrIdx];
- }
- else if (((Capability) m_capabilities[capIdx]).getAttributes()[attrIdx]
- .getName().equals(ICapability.VERSION_PROPERTY))
- {
- pkgVersion = ((Capability) m_capabilities[capIdx]).getAttributes()[attrIdx];
- }
- else
- {
- m_logger.log(Logger.LOG_WARNING,
- "Unknown R3 export attribute: "
- + ((Capability) m_capabilities[capIdx]).getAttributes()[attrIdx].getName());
- }
- }
-
- // Recreate the export to remove any other attributes
- // and add version if missing.
- m_capabilities[capIdx] = new Capability(
- m_capabilities[capIdx].getModule(),
- ICapability.PACKAGE_NAMESPACE,
- null,
- new R4Attribute[] { pkgName, pkgVersion } );
- }
- }
- }
-
- // Check to make sure that R3 bundles have only specified
- // the 'specification-version' attribute and no directives
- // on their imports; ignore all unknown attributes.
- for (int reqIdx = 0; (m_requirements != null) && (reqIdx < m_requirements.length); reqIdx++)
- {
- if (m_requirements[reqIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
- {
- // R3 bundles cannot have directives on their imports.
- if (((Requirement) m_requirements[reqIdx]).getDirectives().length != 0)
- {
- throw new BundleException("R3 imports cannot contain directives.");
- }
-
- // Remove and ignore all attributes other than version.
- // NOTE: This is checking for "version" rather than "specification-version"
- // because the package class normalizes to "version" to avoid having
- // future special cases. This could be changed if more strict behavior
- // is required.
- if (((Requirement) m_requirements[reqIdx]).getAttributes() != null)
- {
- // R3 package requirements should only have name and
- // version attributes.
- R4Attribute pkgName = null;
- R4Attribute pkgVersion =
- new R4Attribute(ICapability.VERSION_PROPERTY,
- new VersionRange(Version.emptyVersion, true, null, true), false);
- for (int attrIdx = 0;
- attrIdx < ((Requirement) m_requirements[reqIdx]).getAttributes().length;
- attrIdx++)
- {
- if (((Requirement) m_requirements[reqIdx]).getAttributes()[attrIdx]
- .getName().equals(ICapability.PACKAGE_PROPERTY))
- {
- pkgName = ((Requirement) m_requirements[reqIdx]).getAttributes()[attrIdx];
- }
- else if (((Requirement) m_requirements[reqIdx]).getAttributes()[attrIdx]
- .getName().equals(ICapability.VERSION_PROPERTY))
- {
- pkgVersion = ((Requirement) m_requirements[reqIdx]).getAttributes()[attrIdx];
- }
- else
- {
- m_logger.log(Logger.LOG_WARNING,
- "Unknown R3 import attribute: "
- + ((Requirement) m_requirements[reqIdx]).getAttributes()[attrIdx].getName());
- }
- }
-
- // Recreate the import to remove any other attributes
- // and add version if missing.
- m_requirements[reqIdx] = new Requirement(
- ICapability.PACKAGE_NAMESPACE,
- null,
- new R4Attribute[] { pkgName, pkgVersion });
- }
- }
- }
+ List<ParsedHeaderClause> clauseList = new ArrayList();
// Since all R3 exports imply an import, add a corresponding
// requirement for each existing export capability. Do not
// duplicate imports.
Map map = new HashMap();
// Add existing imports.
- for (int i = 0; i < m_requirements.length; i++)
+ for (int impIdx = 0; impIdx < imports.size(); impIdx++)
{
- if (m_requirements[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ for (int pathIdx = 0; pathIdx < imports.get(impIdx).m_paths.size(); pathIdx++)
{
map.put(
- ((Requirement) m_requirements[i]).getTargetName(),
- m_requirements[i]);
+ imports.get(impIdx).m_paths.get(pathIdx),
+ imports.get(impIdx).m_paths.get(pathIdx));
}
}
// Add import requirement for each export capability.
- for (int i = 0; i < m_capabilities.length; i++)
+ for (int i = 0; i < exports.size(); i++)
{
- if (m_capabilities[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
- (map.get(m_capabilities[i].getProperties().get(ICapability.PACKAGE_PROPERTY)) == null))
+ if (map.get(exports.get(i).getAttribute(Capability.PACKAGE_ATTR).getValue()) == null)
{
// Convert Version to VersionRange.
- R4Attribute[] attrs = (R4Attribute[]) ((Capability) m_capabilities[i]).getAttributes().clone();
- for (int attrIdx = 0; (attrs != null) && (attrIdx < attrs.length); attrIdx++)
+ List<Attribute> attrs = new ArrayList<Attribute>(exports.get(i).getAttributes());
+ for (int attrIdx = 0; (attrs != null) && (attrIdx < attrs.size()); attrIdx++)
{
- if (attrs[attrIdx].getName().equals(Constants.VERSION_ATTRIBUTE))
+ if (attrs.get(attrIdx).getName().equals(Constants.VERSION_ATTRIBUTE))
{
- attrs[attrIdx] = new R4Attribute(
- attrs[attrIdx].getName(),
- VersionRange.parse(attrs[attrIdx].getValue().toString()),
- attrs[attrIdx].isMandatory());
+ attrs.set(attrIdx, new Attribute(
+ attrs.get(attrIdx).getName(),
+ VersionRange.parse(attrs.get(attrIdx).getValue().toString()),
+ attrs.get(attrIdx).isMandatory()));
}
}
- map.put(
- m_capabilities[i].getProperties().get(ICapability.PACKAGE_PROPERTY),
- new Requirement(ICapability.PACKAGE_NAMESPACE, null, attrs));
+ List<String> paths = new ArrayList();
+ paths.add((String)
+ exports.get(i).getAttribute(Capability.PACKAGE_ATTR).getValue());
+ clauseList.add(
+ new ParsedHeaderClause(paths, new ArrayList<Directive>(0), attrs));
}
}
- m_requirements =
- (IRequirement[]) map.values().toArray(new IRequirement[map.size()]);
+ return clauseList;
+ }
+
+ private static List<Capability> calculateImplicitUses(
+ List<Capability> exports, List<ParsedHeaderClause> imports)
+ throws BundleException
+ {
// Add a "uses" directive onto each export of R3 bundles
// that references every other import (which will include
// exports, since export implies import); this is
// necessary since R3 bundles assumed a single class space,
// but R4 allows for multiple class spaces.
String usesValue = "";
- for (int i = 0; (m_requirements != null) && (i < m_requirements.length); i++)
+ for (int i = 0; i < imports.size(); i++)
{
- if (m_requirements[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ for (int pathIdx = 0; pathIdx < imports.get(i).m_paths.size(); pathIdx++)
{
usesValue = usesValue
+ ((usesValue.length() > 0) ? "," : "")
- + ((Requirement) m_requirements[i]).getTargetName();
+ + imports.get(i).m_paths.get(pathIdx);
}
}
- R4Directive uses = new R4Directive(
+ Directive uses = new Directive(
Constants.USES_DIRECTIVE, usesValue);
- for (int i = 0; (m_capabilities != null) && (i < m_capabilities.length); i++)
+ for (int i = 0; i < exports.size(); i++)
{
- if (m_capabilities[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
- {
- m_capabilities[i] = new Capability(
- m_capabilities[i].getModule(),
- ICapability.PACKAGE_NAMESPACE,
- new R4Directive[] { uses },
- ((Capability) m_capabilities[i]).getAttributes());
- }
+ List<Directive> dirList = new ArrayList<Directive>(1);
+ dirList.add(uses);
+ exports.set(i, new CapabilityImpl(
+ exports.get(i).getModule(),
+ Capability.PACKAGE_NAMESPACE,
+ dirList,
+ exports.get(i).getAttributes()));
}
- // Check to make sure that R3 bundles have no attributes or
- // directives on their dynamic imports.
- for (int i = 0;
- (m_dynamicRequirements != null) && (i < m_dynamicRequirements.length);
- i++)
- {
- if (((Requirement) m_dynamicRequirements[i]).getDirectives().length != 0)
- {
- throw new BundleException("R3 dynamic imports cannot contain directives.");
- }
- if (((Requirement) m_dynamicRequirements[i]).getAttributes().length != 0)
- {
-// throw new BundleException("R3 dynamic imports cannot contain attributes.");
- }
- }
+ return exports;
}
- private void checkAndNormalizeR4() throws BundleException
+ private static boolean checkExtensionBundle(Map headerMap) throws BundleException
{
- // Verify that bundle symbolic name is specified.
- if (m_bundleSymbolicName == null)
- {
- throw new BundleException("R4 bundle manifests must include bundle symbolic name.");
- }
-
- m_capabilities = checkAndNormalizeR4Exports(
- m_capabilities, m_bundleSymbolicName, m_bundleVersion);
-
- R4Directive extension = parseExtensionBundleHeader((String)
- m_headerMap.get(Constants.FRAGMENT_HOST));
+ Directive extension = parseExtensionBundleHeader(
+ (String) headerMap.get(Constants.FRAGMENT_HOST));
if (extension != null)
{
- if (!(Constants.EXTENSION_FRAMEWORK.equals(extension.getValue()) ||
+ if (!(Constants.EXTENSION_FRAMEWORK.equals(extension.getValue()) ||
Constants.EXTENSION_BOOTCLASSPATH.equals(extension.getValue())))
{
throw new BundleException(
"Extension bundle must have either 'extension:=framework' or 'extension:=bootclasspath'");
}
- checkExtensionBundle();
- m_isExtension = true;
- }
- }
-
- private static ICapability[] checkAndNormalizeR4Exports(
- ICapability[] caps, String bsn, Version bv)
- throws BundleException
- {
- // Verify that the exports do not specify bundle symbolic name
- // or bundle version.
- for (int i = 0; (caps != null) && (i < caps.length); i++)
- {
- if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ if (headerMap.containsKey(Constants.IMPORT_PACKAGE) ||
+ headerMap.containsKey(Constants.REQUIRE_BUNDLE) ||
+ headerMap.containsKey(Constants.BUNDLE_NATIVECODE) ||
+ headerMap.containsKey(Constants.DYNAMICIMPORT_PACKAGE) ||
+ headerMap.containsKey(Constants.BUNDLE_ACTIVATOR))
{
- R4Attribute[] attrs = ((Capability) caps[i]).getAttributes();
- for (int attrIdx = 0; attrIdx < attrs.length; attrIdx++)
- {
- // Find symbolic name and version attribute, if present.
- if (attrs[attrIdx].getName().equals(Constants.BUNDLE_VERSION_ATTRIBUTE) ||
- attrs[attrIdx].getName().equals(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE))
- {
- throw new BundleException(
- "Exports must not specify bundle symbolic name or bundle version.");
- }
- }
-
- // Now that we know that there are no bundle symbolic name and version
- // attributes, add them since the spec says they are there implicitly.
- R4Attribute[] newAttrs = new R4Attribute[attrs.length + 2];
- System.arraycopy(attrs, 0, newAttrs, 0, attrs.length);
- newAttrs[attrs.length] = new R4Attribute(
- Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, bsn, false);
- newAttrs[attrs.length + 1] = new R4Attribute(
- Constants.BUNDLE_VERSION_ATTRIBUTE, bv, false);
- caps[i] = new Capability(
- caps[i].getModule(),
- ICapability.PACKAGE_NAMESPACE,
- ((Capability) caps[i]).getDirectives(),
- newAttrs);
+ throw new BundleException("Invalid extension bundle manifest");
}
+ return true;
}
-
- return caps;
+ return false;
}
- private void checkExtensionBundle() throws BundleException
- {
- if (m_headerMap.containsKey(Constants.IMPORT_PACKAGE) ||
- m_headerMap.containsKey(Constants.REQUIRE_BUNDLE) ||
- m_headerMap.containsKey(Constants.BUNDLE_NATIVECODE) ||
- m_headerMap.containsKey(Constants.DYNAMICIMPORT_PACKAGE) ||
- m_headerMap.containsKey(Constants.BUNDLE_ACTIVATOR))
- {
- throw new BundleException("Invalid extension bundle manifest");
- }
- }
-
- private static ICapability parseBundleSymbolicName(IModule owner, Map headerMap)
+ private static Capability parseBundleSymbolicName(Module owner, Map headerMap)
throws BundleException
{
- Object[][][] clauses = parseStandardHeader(
+ List<ParsedHeaderClause> clauses = parseStandardHeader(
(String) headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
- if (clauses.length > 0)
+ if (clauses.size() > 0)
{
- if (clauses.length > 1)
+ if (clauses.size() > 1)
{
throw new BundleException(
"Cannot have multiple symbolic names: "
+ headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
}
- else if (clauses[0][CLAUSE_PATHS_INDEX].length > 1)
+ else if (clauses.get(0).m_paths.size() > 1)
{
throw new BundleException(
"Cannot have multiple symbolic names: "
@@ -869,42 +1097,42 @@
}
// Create a module capability and return it.
- String symName = (String) clauses[0][CLAUSE_PATHS_INDEX][0];
- R4Attribute[] attrs = new R4Attribute[2];
- attrs[0] = new R4Attribute(
- Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, symName, false);
- attrs[1] = new R4Attribute(
- Constants.BUNDLE_VERSION_ATTRIBUTE, bundleVersion, false);
- return new Capability(
+ String symName = (String) clauses.get(0).m_paths.get(0);
+ List<Attribute> attrs = new ArrayList<Attribute>(2);
+ attrs.add(new Attribute(
+ Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, symName, false));
+ attrs.add(new Attribute(
+ Constants.BUNDLE_VERSION_ATTRIBUTE, bundleVersion, false));
+ return new CapabilityImpl(
owner,
- ICapability.MODULE_NAMESPACE,
- (R4Directive[]) clauses[0][CLAUSE_DIRECTIVES_INDEX],
+ Capability.MODULE_NAMESPACE,
+ clauses.get(0).m_dirs,
attrs);
}
return null;
}
- private static IRequirement parseFragmentHost(Logger logger, Map headerMap)
+ private static List<Requirement> parseFragmentHost(Logger logger, Map headerMap)
throws BundleException
{
- IRequirement req = null;
+ List<Requirement> reqs = new ArrayList();
String mv = getManifestVersion(headerMap);
if ((mv != null) && mv.equals("2"))
{
- Object[][][] clauses = parseStandardHeader(
+ List<ParsedHeaderClause> clauses = parseStandardHeader(
(String) headerMap.get(Constants.FRAGMENT_HOST));
- if (clauses.length > 0)
+ if (clauses.size() > 0)
{
// Make sure that only one fragment host symbolic name is specified.
- if (clauses.length > 1)
+ if (clauses.size() > 1)
{
throw new BundleException(
"Fragments cannot have multiple hosts: "
+ headerMap.get(Constants.FRAGMENT_HOST));
}
- else if (clauses[0][CLAUSE_PATHS_INDEX].length > 1)
+ else if (clauses.get(0).m_paths.size() > 1)
{
throw new BundleException(
"Fragments cannot have multiple hosts: "
@@ -914,31 +1142,31 @@
// If the bundle version matching attribute is specified, then
// convert it to the proper type.
for (int attrIdx = 0;
- attrIdx < clauses[0][CLAUSE_ATTRIBUTES_INDEX].length;
+ attrIdx < clauses.get(0).m_attrs.size();
attrIdx++)
{
- R4Attribute attr = (R4Attribute) clauses[0][CLAUSE_ATTRIBUTES_INDEX][attrIdx];
+ Attribute attr = clauses.get(0).m_attrs.get(attrIdx);
if (attr.getName().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
{
- clauses[0][CLAUSE_ATTRIBUTES_INDEX][attrIdx] =
- new R4Attribute(
+ clauses.get(0).m_attrs.set(attrIdx,
+ new Attribute(
Constants.BUNDLE_VERSION_ATTRIBUTE,
VersionRange.parse(attr.getValue().toString()),
- attr.isMandatory());
+ attr.isMandatory()));
}
}
// Prepend the host symbolic name to the array of attributes.
- R4Attribute[] attrs = (R4Attribute[]) clauses[0][CLAUSE_ATTRIBUTES_INDEX];
- R4Attribute[] newAttrs = new R4Attribute[attrs.length + 1];
- newAttrs[0] = new R4Attribute(
+ List<Attribute> attrs = clauses.get(0).m_attrs;
+ List<Attribute> newAttrs = new ArrayList<Attribute>(attrs.size() + 1);
+ newAttrs.add(new Attribute(
Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE,
- clauses[0][CLAUSE_PATHS_INDEX][0], false);
- System.arraycopy(attrs, 0, newAttrs, 1, attrs.length);
+ clauses.get(0).m_paths.get(0), false));
+ newAttrs.addAll(attrs);
- req = new Requirement(ICapability.HOST_NAMESPACE,
- (R4Directive[]) clauses[0][CLAUSE_DIRECTIVES_INDEX],
- newAttrs);
+ reqs.add(new RequirementImpl(Capability.HOST_NAMESPACE,
+ clauses.get(0).m_dirs,
+ newAttrs));
}
}
else
@@ -946,17 +1174,19 @@
logger.log(Logger.LOG_WARNING, "Only R4 bundles can be fragments.");
}
- return req;
+ return reqs;
}
- public static ICapability[] parseExportHeader(
- IModule owner, String header, String bsn, Version bv)
- throws BundleException
+ public static List<Capability> parseExportHeader(
+ Logger logger, Module owner, String header, String bsn, Version bv)
{
- ICapability[] caps = parseExportHeader(owner, header);
+
+ List<Capability> caps = null;
try
{
- caps = checkAndNormalizeR4Exports(caps, bsn, bv);
+ List<ParsedHeaderClause> exportClauses = parseStandardHeader(header);
+ exportClauses = normalizeExportClauses(logger, exportClauses, "2", bsn, bv);
+ caps = convertExports(exportClauses, owner);
}
catch (BundleException ex)
{
@@ -965,279 +1195,121 @@
return caps;
}
- private static ICapability[] parseExportHeader(IModule owner, String header)
+ private static List<Capability> convertExports(
+ List<ParsedHeaderClause> clauses, Module owner)
{
- Object[][][] clauses = parseStandardHeader(header);
-
-// TODO: FRAMEWORK - Perhaps verification/normalization should be completely
-// separated from parsing, since verification/normalization may vary.
-
- // If both version and specification-version attributes are specified,
- // then verify that the values are equal.
- Map attrMap = new HashMap();
- for (int clauseIdx = 0; clauseIdx < clauses.length; clauseIdx++)
- {
- // Put attributes for current clause in a map for easy lookup.
- attrMap.clear();
- for (int attrIdx = 0;
- attrIdx < clauses[clauseIdx][CLAUSE_ATTRIBUTES_INDEX].length;
- attrIdx++)
- {
- R4Attribute attr = (R4Attribute) clauses[clauseIdx][CLAUSE_ATTRIBUTES_INDEX][attrIdx];
- attrMap.put(attr.getName(), attr);
- }
-
- // Check for "version" and "specification-version" attributes
- // and verify they are the same if both are specified.
- R4Attribute v = (R4Attribute) attrMap.get(Constants.VERSION_ATTRIBUTE);
- R4Attribute sv = (R4Attribute) attrMap.get(Constants.PACKAGE_SPECIFICATION_VERSION);
- if ((v != null) && (sv != null))
- {
- // Verify they are equal.
- if (!((String) v.getValue()).trim().equals(((String) sv.getValue()).trim()))
- {
- throw new IllegalArgumentException(
- "Both version and specificat-version are specified, but they are not equal.");
- }
- }
-
- // Always add the default version if not specified.
- if ((v == null) && (sv == null))
- {
- v = new R4Attribute(
- Constants.VERSION_ATTRIBUTE, Version.emptyVersion, false);
- }
-
- // Ensure that only the "version" attribute is used and convert
- // it to the appropriate type.
- if ((v != null) || (sv != null))
- {
- // Convert version attribute to type Version.
- attrMap.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
- v = (v == null) ? sv : v;
- attrMap.put(Constants.VERSION_ATTRIBUTE,
- new R4Attribute(
- Constants.VERSION_ATTRIBUTE,
- Version.parseVersion(v.getValue().toString()),
- v.isMandatory()));
-
- // Re-copy the attribute array since it has changed.
- clauses[clauseIdx][CLAUSE_ATTRIBUTES_INDEX] =
- attrMap.values().toArray(new R4Attribute[attrMap.size()]);
- }
- }
-
- // Now convert generic header clauses into capabilities.
- List capList = new ArrayList();
- for (int clauseIdx = 0; clauseIdx < clauses.length; clauseIdx++)
+ List<Capability> capList = new ArrayList();
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
{
for (int pathIdx = 0;
- pathIdx < clauses[clauseIdx][CLAUSE_PATHS_INDEX].length;
+ pathIdx < clauses.get(clauseIdx).m_paths.size();
pathIdx++)
{
- // Make sure a package name was specified.
- if (((String) clauses[clauseIdx][CLAUSE_PATHS_INDEX][pathIdx]).length() == 0)
- {
- throw new IllegalArgumentException(
- "An empty package name was specified: " + header);
- }
// Prepend the package name to the array of attributes.
- R4Attribute[] attrs = (R4Attribute[]) clauses[clauseIdx][CLAUSE_ATTRIBUTES_INDEX];
- R4Attribute[] newAttrs = new R4Attribute[attrs.length + 1];
- newAttrs[0] = new R4Attribute(
- ICapability.PACKAGE_PROPERTY,
- clauses[clauseIdx][CLAUSE_PATHS_INDEX][pathIdx], false);
- System.arraycopy(attrs, 0, newAttrs, 1, attrs.length);
+ List<Attribute> attrs = clauses.get(clauseIdx).m_attrs;
+ List<Attribute> newAttrs = new ArrayList<Attribute>(attrs.size() + 1);
+ newAttrs.add(new Attribute(
+ Capability.PACKAGE_ATTR,
+ clauses.get(clauseIdx).m_paths.get(pathIdx), false));
+ newAttrs.addAll(attrs);
// Create package capability and add to capability list.
capList.add(
- new Capability(
+ new CapabilityImpl(
owner,
- ICapability.PACKAGE_NAMESPACE,
- (R4Directive[]) clauses[clauseIdx][CLAUSE_DIRECTIVES_INDEX],
+ Capability.PACKAGE_NAMESPACE,
+ clauses.get(clauseIdx).m_dirs,
newAttrs));
}
}
- return (ICapability[]) capList.toArray(new ICapability[capList.size()]);
+ return capList;
}
- private static IRequirement[] parseImportHeader(String header)
+ private static List<ParsedHeaderClause> normalizeRequireClauses(
+ Logger logger, List<ParsedHeaderClause> clauses, String mv)
{
- Object[][][] clauses = parseStandardHeader(header);
-
-// TODO: FRAMEWORK - Perhaps verification/normalization should be completely
-// separated from parsing, since verification/normalization may vary.
-
- // Verify that the values are equals if the package specifies
- // both version and specification-version attributes.
- Map attrMap = new HashMap();
- for (int clauseIdx = 0; clauseIdx < clauses.length; clauseIdx++)
+ // R3 bundles cannot require other bundles.
+ if (!mv.equals("2"))
{
- // Put attributes for current clause in a map for easy lookup.
- attrMap.clear();
- for (int attrIdx = 0;
- attrIdx < clauses[clauseIdx][CLAUSE_ATTRIBUTES_INDEX].length;
- attrIdx++)
- {
- R4Attribute attr = (R4Attribute) clauses[clauseIdx][CLAUSE_ATTRIBUTES_INDEX][attrIdx];
- attrMap.put(attr.getName(), attr);
- }
-
- // Check for "version" and "specification-version" attributes
- // and verify they are the same if both are specified.
- R4Attribute v = (R4Attribute) attrMap.get(Constants.VERSION_ATTRIBUTE);
- R4Attribute sv = (R4Attribute) attrMap.get(Constants.PACKAGE_SPECIFICATION_VERSION);
- if ((v != null) && (sv != null))
- {
- // Verify they are equal.
- if (!((String) v.getValue()).trim().equals(((String) sv.getValue()).trim()))
- {
- throw new IllegalArgumentException(
- "Both version and specificat-version are specified, but they are not equal.");
- }
- }
-
- // Ensure that only the "version" attribute is used and convert
- // it to the VersionRange type.
- if ((v != null) || (sv != null))
- {
- attrMap.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
- v = (v == null) ? sv : v;
- attrMap.put(Constants.VERSION_ATTRIBUTE,
- new R4Attribute(
- Constants.VERSION_ATTRIBUTE,
- VersionRange.parse(v.getValue().toString()),
- v.isMandatory()));
- }
-
- // If bundle version is specified, then convert its type to VersionRange.
- v = (R4Attribute) attrMap.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
- if (v != null)
- {
- attrMap.put(Constants.BUNDLE_VERSION_ATTRIBUTE,
- new R4Attribute(
- Constants.BUNDLE_VERSION_ATTRIBUTE,
- VersionRange.parse(v.getValue().toString()),
- v.isMandatory()));
- }
-
- // Re-copy the attribute array in case it has changed.
- clauses[clauseIdx][CLAUSE_ATTRIBUTES_INDEX] =
- attrMap.values().toArray(new R4Attribute[attrMap.size()]);
+ clauses.clear();
}
-
- // Now convert generic header clauses into requirements.
- List reqList = new ArrayList();
- for (int clauseIdx = 0; clauseIdx < clauses.length; clauseIdx++)
+ else
{
- for (int pathIdx = 0;
- pathIdx < clauses[clauseIdx][CLAUSE_PATHS_INDEX].length;
- pathIdx++)
+ // Convert bundle version attribute to VersionRange type.
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
{
- // Make sure a package name was specified.
- if (((String) clauses[clauseIdx][CLAUSE_PATHS_INDEX][pathIdx]).length() == 0)
+ for (int attrIdx = 0;
+ attrIdx < clauses.get(clauseIdx).m_attrs.size();
+ attrIdx++)
{
- throw new IllegalArgumentException(
- "An empty package name was specified: " + header);
+ Attribute attr = clauses.get(clauseIdx).m_attrs.get(attrIdx);
+ if (attr.getName().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
+ {
+ clauses.get(clauseIdx).m_attrs.set(attrIdx,
+ new Attribute(
+ Constants.BUNDLE_VERSION_ATTRIBUTE,
+ VersionRange.parse(attr.getValue().toString()),
+ attr.isMandatory()));
+ }
}
- // Prepend the package name to the array of attributes.
- R4Attribute[] attrs = (R4Attribute[]) clauses[clauseIdx][CLAUSE_ATTRIBUTES_INDEX];
- R4Attribute[] newAttrs = new R4Attribute[attrs.length + 1];
- newAttrs[0] = new R4Attribute(
- ICapability.PACKAGE_PROPERTY,
- clauses[clauseIdx][CLAUSE_PATHS_INDEX][pathIdx], false);
- System.arraycopy(attrs, 0, newAttrs, 1, attrs.length);
-
- // Create package requirement and add to requirement list.
- reqList.add(
- new Requirement(
- ICapability.PACKAGE_NAMESPACE,
- (R4Directive[]) clauses[clauseIdx][CLAUSE_DIRECTIVES_INDEX],
- newAttrs));
}
}
- return (IRequirement[]) reqList.toArray(new IRequirement[reqList.size()]);
+ return clauses;
}
- private static IRequirement[] parseRequireBundleHeader(String header)
+ private static List<Requirement> convertRequires(List<ParsedHeaderClause> clauses)
{
- Object[][][] clauses = parseStandardHeader(header);
-
-// TODO: FRAMEWORK - Perhaps verification/normalization should be completely
-// separated from parsing, since verification/normalization may vary.
-
- // Convert bundle version attribute to VersionRange type.
- for (int clauseIdx = 0; clauseIdx < clauses.length; clauseIdx++)
+ List<Requirement> reqList = new ArrayList();
+ for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
{
- for (int attrIdx = 0;
- attrIdx < clauses[clauseIdx][CLAUSE_ATTRIBUTES_INDEX].length;
- attrIdx++)
- {
- R4Attribute attr = (R4Attribute) clauses[clauseIdx][CLAUSE_ATTRIBUTES_INDEX][attrIdx];
- if (attr.getName().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
- {
- clauses[clauseIdx][CLAUSE_ATTRIBUTES_INDEX][attrIdx] =
- new R4Attribute(
- Constants.BUNDLE_VERSION_ATTRIBUTE,
- VersionRange.parse(attr.getValue().toString()),
- attr.isMandatory());
- }
- }
- }
+ List<Attribute> attrs = clauses.get(clauseIdx).m_attrs;
- // Now convert generic header clauses into requirements.
- List reqList = new ArrayList();
- for (int clauseIdx = 0; clauseIdx < clauses.length; clauseIdx++)
- {
for (int pathIdx = 0;
- pathIdx < clauses[clauseIdx][CLAUSE_PATHS_INDEX].length;
+ pathIdx < clauses.get(clauseIdx).m_paths.size();
pathIdx++)
{
// Prepend the symbolic name to the array of attributes.
- R4Attribute[] attrs = (R4Attribute[]) clauses[clauseIdx][CLAUSE_ATTRIBUTES_INDEX];
- R4Attribute[] newAttrs = new R4Attribute[attrs.length + 1];
- newAttrs[0] = new R4Attribute(
+ List<Attribute> newAttrs = new ArrayList<Attribute>(attrs.size() + 1);
+ newAttrs.add(new Attribute(
Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE,
- clauses[clauseIdx][CLAUSE_PATHS_INDEX][pathIdx], false);
- System.arraycopy(attrs, 0, newAttrs, 1, attrs.length);
+ clauses.get(clauseIdx).m_paths.get(pathIdx), false));
+ newAttrs.addAll(attrs);
// Create package requirement and add to requirement list.
reqList.add(
- new Requirement(
- ICapability.MODULE_NAMESPACE,
- (R4Directive[]) clauses[clauseIdx][CLAUSE_DIRECTIVES_INDEX],
+ new RequirementImpl(
+ Capability.MODULE_NAMESPACE,
+ clauses.get(clauseIdx).m_dirs,
newAttrs));
}
}
- return (IRequirement[]) reqList.toArray(new IRequirement[reqList.size()]);
+ return reqList;
}
- public static R4Directive parseExtensionBundleHeader(String header)
+ public static Directive parseExtensionBundleHeader(String header)
throws BundleException
{
- Object[][][] clauses = parseStandardHeader(header);
+ List<ParsedHeaderClause> clauses = parseStandardHeader(header);
- R4Directive result = null;
+ Directive result = null;
- if (clauses.length == 1)
+ if (clauses.size() == 1)
{
// See if there is the "extension" directive.
- for (int i = 0;
- (result == null) && (i < clauses[0][CLAUSE_DIRECTIVES_INDEX].length);
- i++)
+ List<Directive> dirs = clauses.get(0).m_dirs;
+ for (int dirIdx = 0; (result == null) && (dirIdx < dirs.size()); dirIdx++)
{
- if (Constants.EXTENSION_DIRECTIVE.equals(((R4Directive)
- clauses[0][CLAUSE_DIRECTIVES_INDEX][i]).getName()))
+ if (Constants.EXTENSION_DIRECTIVE.equals(dirs.get(dirIdx).getName()))
{
// If the extension directive is specified, make sure
// the target is the system bundle.
- if (FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(clauses[0][CLAUSE_PATHS_INDEX][0]) ||
- Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(clauses[0][CLAUSE_PATHS_INDEX][0]))
+ if (FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(clauses.get(0).m_paths.get(0)) ||
+ Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(clauses.get(0).m_paths.get(0)))
{
- result = (R4Directive) clauses[0][CLAUSE_DIRECTIVES_INDEX][i];
+ result = (Directive) dirs.get(dirIdx);
}
else
{
@@ -1253,32 +1325,30 @@
private void parseActivationPolicy(Map headerMap)
{
- m_activationPolicy = IModule.EAGER_ACTIVATION;
+ m_activationPolicy = Module.EAGER_ACTIVATION;
- Object[][][] clauses = parseStandardHeader(
+ List<ParsedHeaderClause> clauses = parseStandardHeader(
(String) headerMap.get(Constants.BUNDLE_ACTIVATIONPOLICY));
- if (clauses.length > 0)
+ if (clauses.size() > 0)
{
// Just look for a "path" matching the lazy policy, ignore
// everything else.
- for (int i = 0;
- i < clauses[0][CLAUSE_PATHS_INDEX].length;
- i++)
+ for (int clauseIdx = 0; clauseIdx < clauses.get(0).m_paths.size(); clauseIdx++)
{
- if (clauses[0][CLAUSE_PATHS_INDEX][i].equals(Constants.ACTIVATION_LAZY))
+ if (clauses.get(0).m_paths.get(clauseIdx).equals(Constants.ACTIVATION_LAZY))
{
- m_activationPolicy = IModule.LAZY_ACTIVATION;
- for (int j = 0; j < clauses[0][CLAUSE_DIRECTIVES_INDEX].length; j++)
+ m_activationPolicy = Module.LAZY_ACTIVATION;
+ for (int dirIdx = 0; dirIdx < clauses.get(0).m_dirs.size(); dirIdx++)
{
- R4Directive dir = (R4Directive) clauses[0][CLAUSE_DIRECTIVES_INDEX][j];
+ Directive dir = clauses.get(0).m_dirs.get(dirIdx);
if (dir.getName().equalsIgnoreCase(Constants.INCLUDE_DIRECTIVE))
{
- m_activationIncludeDir = dir.getValue();
+ m_activationIncludeDir = (String) dir.getValue();
}
else if (dir.getName().equalsIgnoreCase(Constants.EXCLUDE_DIRECTIVE))
{
- m_activationExcludeDir = dir.getValue();
+ m_activationExcludeDir = (String) dir.getValue();
}
}
break;
@@ -1293,9 +1363,9 @@
// Like this: path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2,
// path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
- private static Object[][][] parseStandardHeader(String header)
+ private static List<ParsedHeaderClause> parseStandardHeader(String header)
{
- Object[][][] clauses = null;
+ List<ParsedHeaderClause> clauses = new ArrayList();
if (header != null)
{
@@ -1305,26 +1375,24 @@
"A header cannot be an empty string.");
}
- String[] clauseStrings = parseDelimitedString(
+ List<String> clauseStrings = parseDelimitedString(
header, FelixConstants.CLASS_PATH_SEPARATOR);
- List completeList = new ArrayList();
- for (int i = 0; (clauseStrings != null) && (i < clauseStrings.length); i++)
+ for (int i = 0; (clauseStrings != null) && (i < clauseStrings.size()); i++)
{
- completeList.add(parseStandardHeaderClause(clauseStrings[i]));
+ clauses.add(parseStandardHeaderClause(clauseStrings.get(i)));
}
- clauses = (Object[][][]) completeList.toArray(new Object[completeList.size()][][]);
}
- return (clauses == null) ? new Object[0][][] : clauses;
+ return clauses;
}
// Like this: path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
- private static Object[][] parseStandardHeaderClause(String clauseString)
+ private static ParsedHeaderClause parseStandardHeaderClause(String clauseString)
throws IllegalArgumentException
{
// Break string into semi-colon delimited pieces.
- String[] pieces = parseDelimitedString(
+ List<String> pieces = parseDelimitedString(
clauseString, FelixConstants.PACKAGE_SEPARATOR);
// Count the number of different paths; paths
@@ -1332,9 +1400,9 @@
// that paths come first, before directives and
// attributes.
int pathCount = 0;
- for (int pieceIdx = 0; pieceIdx < pieces.length; pieceIdx++)
+ for (int pieceIdx = 0; pieceIdx < pieces.size(); pieceIdx++)
{
- if (pieces[pieceIdx].indexOf('=') >= 0)
+ if (pieces.get(pieceIdx).indexOf('=') >= 0)
{
break;
}
@@ -1349,23 +1417,26 @@
}
// Create an array of paths.
- String[] paths = new String[pathCount];
- System.arraycopy(pieces, 0, paths, 0, pathCount);
+ List<String> paths = new ArrayList<String>(pathCount);
+ for (int pathIdx = 0; pathIdx < pathCount; pathIdx++)
+ {
+ paths.add(pieces.get(pathIdx));
+ }
// Parse the directives/attributes.
- Map dirsMap = new HashMap();
- Map attrsMap = new HashMap();
+ Map<String, Directive> dirsMap = new HashMap();
+ Map<String, Attribute> attrsMap = new HashMap();
int idx = -1;
String sep = null;
- for (int pieceIdx = pathCount; pieceIdx < pieces.length; pieceIdx++)
+ for (int pieceIdx = pathCount; pieceIdx < pieces.size(); pieceIdx++)
{
// Check if it is a directive.
- if ((idx = pieces[pieceIdx].indexOf(FelixConstants.DIRECTIVE_SEPARATOR)) >= 0)
+ if ((idx = pieces.get(pieceIdx).indexOf(FelixConstants.DIRECTIVE_SEPARATOR)) >= 0)
{
sep = FelixConstants.DIRECTIVE_SEPARATOR;
}
// Check if it is an attribute.
- else if ((idx = pieces[pieceIdx].indexOf(FelixConstants.ATTRIBUTE_SEPARATOR)) >= 0)
+ else if ((idx = pieces.get(pieceIdx).indexOf(FelixConstants.ATTRIBUTE_SEPARATOR)) >= 0)
{
sep = FelixConstants.ATTRIBUTE_SEPARATOR;
}
@@ -1375,8 +1446,8 @@
throw new IllegalArgumentException("Not a directive/attribute: " + clauseString);
}
- String key = pieces[pieceIdx].substring(0, idx).trim();
- String value = pieces[pieceIdx].substring(idx + sep.length()).trim();
+ String key = pieces.get(pieceIdx).substring(0, idx).trim();
+ String value = pieces.get(pieceIdx).substring(idx + sep.length()).trim();
// Remove quotes, if value is quoted.
if (value.startsWith("\"") && value.endsWith("\""))
@@ -1393,7 +1464,7 @@
throw new IllegalArgumentException(
"Duplicate directive: " + key);
}
- dirsMap.put(key, new R4Directive(key, value));
+ dirsMap.put(key, new Directive(key, value));
}
else
{
@@ -1403,25 +1474,22 @@
throw new IllegalArgumentException(
"Duplicate attribute: " + key);
}
- attrsMap.put(key, new R4Attribute(key, value, false));
+ attrsMap.put(key, new Attribute(key, value, false));
}
}
- // Create directive array.
- R4Directive[] dirs = (R4Directive[])
- dirsMap.values().toArray(new R4Directive[dirsMap.size()]);
+ List<Directive> dirs = new ArrayList<Directive>(dirsMap.size());
+ for (Entry<String, Directive> entry : dirsMap.entrySet())
+ {
+ dirs.add(entry.getValue());
+ }
+ List<Attribute> attrs = new ArrayList<Attribute>(attrsMap.size());
+ for (Entry<String, Attribute> entry : attrsMap.entrySet())
+ {
+ attrs.add(entry.getValue());
+ }
- // Create attribute array.
- R4Attribute[] attrs = (R4Attribute[])
- attrsMap.values().toArray(new R4Attribute[attrsMap.size()]);
-
- // Create an array to hold the parsed paths, directives, and attributes.
- Object[][] clause = new Object[3][];
- clause[CLAUSE_PATHS_INDEX] = paths;
- clause[CLAUSE_DIRECTIVES_INDEX] = dirs;
- clause[CLAUSE_ATTRIBUTES_INDEX] = attrs;
-
- return clause;
+ return new ParsedHeaderClause(paths, dirs, attrs);
}
/**
@@ -1433,14 +1501,14 @@
* @param delim the characters delimiting the tokens.
* @return an array of string tokens or null if there were no tokens.
**/
- public static String[] parseDelimitedString(String value, String delim)
+ public static List<String> parseDelimitedString(String value, String delim)
{
if (value == null)
{
value = "";
}
- List list = new ArrayList();
+ List<String> list = new ArrayList();
int CHAR = 1;
int DELIMITER = 2;
@@ -1489,7 +1557,7 @@
list.add(sb.toString().trim());
}
- return (String[]) list.toArray(new String[list.size()]);
+ return list;
}
/**
@@ -1499,22 +1567,23 @@
* @return an array of <tt>LibraryInfo</tt> objects for the
* passed in strings.
**/
- private static R4LibraryClause[] parseLibraryStrings(Logger logger, String[] libStrs)
+ private static List<R4LibraryClause> parseLibraryStrings(
+ Logger logger, List<String> libStrs)
throws IllegalArgumentException
{
if (libStrs == null)
{
- return new R4LibraryClause[0];
+ return new ArrayList<R4LibraryClause>(0);
}
- List libList = new ArrayList();
+ List<R4LibraryClause> libList = new ArrayList(libStrs.size());
- for (int i = 0; i < libStrs.length; i++)
+ for (int i = 0; i < libStrs.size(); i++)
{
- R4LibraryClause clause = R4LibraryClause.parse(logger, libStrs[i]);
+ R4LibraryClause clause = R4LibraryClause.parse(logger, libStrs.get(i));
libList.add(clause);
}
- return (R4LibraryClause[]) libList.toArray(new R4LibraryClause[libList.size()]);
+ return libList;
}
}
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ParsedHeaderClause.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ParsedHeaderClause.java
new file mode 100644
index 0000000..c97bc60
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ParsedHeaderClause.java
@@ -0,0 +1,37 @@
+/*
+ * 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.framework.util.manifestparser;
+
+import java.util.List;
+import org.apache.felix.framework.capabilityset.Attribute;
+import org.apache.felix.framework.capabilityset.Directive;
+
+public class ParsedHeaderClause
+{
+ public final List<String> m_paths;
+ public final List<Directive> m_dirs;
+ public final List<Attribute> m_attrs;
+
+ public ParsedHeaderClause(List<String> paths, List<Directive> dirs, List<Attribute> attrs)
+ {
+ m_paths = paths;
+ m_dirs = dirs;
+ m_attrs = attrs;
+ }
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4Attribute.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4Attribute.java
deleted file mode 100644
index ec5b751..0000000
--- a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4Attribute.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.framework.util.manifestparser;
-
-public class R4Attribute
-{
- private final String m_name;
- private final Object m_value;
- private final boolean m_isMandatory;
-
- public R4Attribute(String name, Object value, boolean isMandatory)
- {
- m_name = name;
- m_value = value;
- m_isMandatory = isMandatory;
- }
-
- public String getName()
- {
- return m_name;
- }
-
- public Object getValue()
- {
- return m_value;
- }
-
- public boolean isMandatory()
- {
- return m_isMandatory;
- }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4Directive.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4Directive.java
deleted file mode 100644
index cf83899..0000000
--- a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4Directive.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.framework.util.manifestparser;
-
-public class R4Directive
-{
- private final String m_name;
- private final String m_value;
-
- public R4Directive(String name, String value)
- {
- m_name = name;
- m_value = value;
- }
-
- public String getName()
- {
- return m_name;
- }
-
- public String getValue()
- {
- return m_value;
- }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4Library.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4Library.java
index 0e3ecd1..214fe9c 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4Library.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4Library.java
@@ -18,6 +18,7 @@
*/
package org.apache.felix.framework.util.manifestparser;
+import java.util.List;
import java.util.Map;
import org.osgi.framework.Constants;
@@ -84,7 +85,7 @@
public boolean match(Map configMap, String name)
{
String libname = System.mapLibraryName(name);
- String[] exts = ManifestParser.parseDelimitedString(
+ List<String> exts = ManifestParser.parseDelimitedString(
(String) configMap.get(Constants.FRAMEWORK_LIBRARY_EXTENSIONS), ",");
int extIdx = 0;
@@ -111,15 +112,15 @@
// If we have other native library extensions to try, then
// calculate the new native library name.
- if ((exts != null) && (extIdx < exts.length))
+ if ((exts != null) && (extIdx < exts.size()))
{
int idx = libname.lastIndexOf(".");
libname = (idx < 0)
- ? libname + "." + exts[extIdx++]
- : libname.substring(0, idx) + "." + exts[extIdx++];
+ ? libname + "." + exts.get(extIdx++)
+ : libname.substring(0, idx) + "." + exts.get(extIdx++);
}
}
- while ((exts != null) && (extIdx < exts.length));
+ while ((exts != null) && (extIdx < exts.size()));
return false;
}
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Requirement.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Requirement.java
deleted file mode 100644
index 42cb756..0000000
--- a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Requirement.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * 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.framework.util.manifestparser;
-
-import org.apache.felix.framework.util.MapToDictionary;
-import org.apache.felix.framework.util.VersionRange;
-import org.apache.felix.moduleloader.ICapability;
-import org.apache.felix.moduleloader.IRequirement;
-import org.osgi.framework.*;
-
-public class Requirement implements IRequirement
-{
- private final String m_namespace;
- private final R4Directive[] m_directives;
- private final R4Attribute[] m_attributes;
- private final boolean m_isOptional;
-
- private final String m_targetName;
- private final VersionRange m_targetVersionRange;
- private volatile Filter m_filter;
-
- public Requirement(String namespace, String filterStr) throws InvalidSyntaxException
- {
- m_namespace = namespace;
- m_filter = FrameworkUtil.createFilter(filterStr);
- m_directives = null;
- m_attributes = null;
- m_isOptional = false;
- m_targetName = null;
- m_targetVersionRange = null;
- }
-
- public Requirement(String namespace, R4Directive[] directives, R4Attribute[] attributes)
- {
- m_namespace = namespace;
- m_directives = directives;
- m_attributes = attributes;
- m_filter = null;
-
- // Find all import directives: resolution.
- boolean optional = false;
- for (int i = 0; (m_directives != null) && (i < m_directives.length); i++)
- {
- if (m_directives[i].getName().equals(Constants.RESOLUTION_DIRECTIVE))
- {
- optional = m_directives[i].getValue().equals(Constants.RESOLUTION_OPTIONAL);
- }
- }
- m_isOptional = optional;
-
- String targetName = null;
- VersionRange targetVersionRange = VersionRange.infiniteRange;
- for (int i = 0; i < m_attributes.length; i++)
- {
- if (m_namespace.equals(ICapability.MODULE_NAMESPACE))
- {
- if (m_attributes[i].getName().equals(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE))
- {
- targetName = (String) m_attributes[i].getValue();
- }
- else if (m_attributes[i].getName().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
- {
- targetVersionRange = (VersionRange) m_attributes[i].getValue();
- }
- }
- else if (m_namespace.equals(ICapability.PACKAGE_NAMESPACE))
- {
- if (m_attributes[i].getName().equals(ICapability.PACKAGE_PROPERTY))
- {
- targetName = (String) m_attributes[i].getValue();
- }
- else if (m_attributes[i].getName().equals(ICapability.VERSION_PROPERTY))
- {
- targetVersionRange = (VersionRange) m_attributes[i].getValue();
- }
- }
- else if (m_namespace.equals(ICapability.HOST_NAMESPACE))
- {
- if (m_attributes[i].getName().equals(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE))
- {
- targetName = (String) m_attributes[i].getValue();
- }
- else if (m_attributes[i].getName().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
- {
- targetVersionRange = (VersionRange) m_attributes[i].getValue();
- }
- }
- }
- m_targetName = targetName;
- m_targetVersionRange = targetVersionRange;
- }
-
- public String getNamespace()
- {
- return m_namespace;
- }
-
- public Filter getFilter()
- {
- if (m_filter == null)
- {
- m_filter = convertToFilter();
- }
- return m_filter;
- }
-
-// TODO: RB - We need to verify that the resolver code does not
-// touch these implementation-specific methods.
-
- public String getTargetName()
- {
- return m_targetName;
- }
-
- public VersionRange getTargetVersionRange()
- {
- return m_targetVersionRange;
- }
-
- public R4Directive[] getDirectives()
- {
- // TODO: RB - We should return copies of the arrays probably.
- return m_directives;
- }
-
- public R4Attribute[] getAttributes()
- {
- // TODO: RB - We should return copies of the arrays probably.
- return m_attributes;
- }
-
- public boolean isMultiple()
- {
- return false;
- }
-
- public boolean isOptional()
- {
- return m_isOptional;
- }
-
- public String getComment()
- {
- return "Comment for " + toString();
- }
-
- public boolean isSatisfied(ICapability capability)
- {
- // If the requirement was constructed with a filter, then
- // we must use that filter for evaluation.
- if ((m_attributes == null) && (m_filter != null))
- {
- return m_namespace.equals(capability.getNamespace()) &&
- getFilter().match(new MapToDictionary(capability.getProperties()));
- }
- // Otherwise, if the requirement was constructed with attributes, then
- // perform the evaluation manually instead of using the filter for
- // performance reasons.
- else if (m_attributes != null)
- {
- return capability.getNamespace().equals(getNamespace()) &&
- doAttributesMatch((Capability) capability);
- }
-
- return false;
- }
-
- private boolean doAttributesMatch(Capability ec)
- {
- // Grab the capability's attributes.
- R4Attribute[] capAttrs = ec.getAttributes();
-
- // Cycle through all attributes of this import package
- // and make sure its values match the attribute values
- // of the specified export package.
- for (int reqAttrIdx = 0; reqAttrIdx < m_attributes.length; reqAttrIdx++)
- {
- // Get current attribute from this import package.
- R4Attribute reqAttr = m_attributes[reqAttrIdx];
-
- // Check if the export package has the same attribute.
- boolean found = false;
- for (int capAttrIdx = 0;
- (!found) && (capAttrIdx < capAttrs.length);
- capAttrIdx++)
- {
- // Get current attribute for the export package.
- R4Attribute capAttr = capAttrs[capAttrIdx];
- // Check if the attribute names are equal.
- if (reqAttr.getName().equals(capAttr.getName()))
- {
- // We only recognize version types. If the value of the
- // attribute is a version/version range, then we use the
- // "in range" comparison, otherwise we simply use equals().
- if (capAttr.getValue() instanceof Version)
- {
- if (!((VersionRange) reqAttr.getValue()).isInRange((Version) capAttr.getValue()))
- {
- return false;
- }
- }
- else if (capAttr.getValue() instanceof Object[])
- {
- Object[] values = (Object[]) capAttr.getValue();
- boolean matched = false;
- for (int valIdx = 0; !matched && (valIdx < values.length); valIdx++)
- {
- if (reqAttr.getValue().equals(values[valIdx]))
- {
- matched = true;
- }
- }
- if (!matched)
- {
- return false;
- }
- }
- else if (!reqAttr.getValue().equals(capAttr.getValue()))
- {
- return false;
- }
- found = true;
- }
- }
- // If the attribute was not found, then return false.
- if (!found)
- {
- return false;
- }
- }
-
- // Now, cycle through all attributes of the export package and verify that
- // all mandatory attributes are present in this import package.
- for (int capAttrIdx = 0; capAttrIdx < capAttrs.length; capAttrIdx++)
- {
- // Get current attribute for this package.
- R4Attribute capAttr = capAttrs[capAttrIdx];
-
- // If the export attribute is mandatory, then make sure
- // this import package has the attribute.
- if (capAttr.isMandatory())
- {
- boolean found = false;
- for (int reqAttrIdx = 0;
- (!found) && (reqAttrIdx < m_attributes.length);
- reqAttrIdx++)
- {
- // Get current attribute from specified package.
- R4Attribute reqAttr = m_attributes[reqAttrIdx];
-
- // Check if the attribute names are equal
- // and set found flag.
- if (capAttr.getName().equals(reqAttr.getName()))
- {
- found = true;
- }
- }
- // If not found, then return false.
- if (!found)
- {
- return false;
- }
- }
- }
-
- return true;
- }
-
- private Filter convertToFilter()
- {
- StringBuffer sb = new StringBuffer();
- if ((m_attributes != null) && (m_attributes.length > 1))
- {
- sb.append("(&");
- }
- for (int i = 0; (m_attributes != null) && (i < m_attributes.length); i++)
- {
- // If this is a package import, then convert wild-carded
- // dynamically imported package names to an OR comparison.
- if (m_namespace.equals(ICapability.PACKAGE_NAMESPACE) &&
- m_attributes[i].getName().equals(ICapability.PACKAGE_PROPERTY) &&
- m_attributes[i].getValue().toString().endsWith(".*"))
- {
- int idx = m_attributes[i].getValue().toString().indexOf(".*");
- sb.append("(|(package=");
- sb.append(m_attributes[i].getValue().toString().substring(0, idx));
- sb.append(")(package=");
- sb.append(m_attributes[i].getValue().toString());
- sb.append("))");
- }
- else if (m_attributes[i].getValue() instanceof VersionRange)
- {
- VersionRange vr = (VersionRange) m_attributes[i].getValue();
- if (vr.isLowInclusive())
- {
- sb.append("(");
- sb.append(m_attributes[i].getName());
- sb.append(">=");
- sb.append(vr.getLow().toString());
- sb.append(")");
- }
- else
- {
- sb.append("(!(");
- sb.append(m_attributes[i].getName());
- sb.append("<=");
- sb.append(vr.getLow().toString());
- sb.append("))");
- }
-
- if (vr.getHigh() != null)
- {
- if (vr.isHighInclusive())
- {
- sb.append("(");
- sb.append(m_attributes[i].getName());
- sb.append("<=");
- sb.append(vr.getHigh().toString());
- sb.append(")");
- }
- else
- {
- sb.append("(!(");
- sb.append(m_attributes[i].getName());
- sb.append(">=");
- sb.append(vr.getHigh().toString());
- sb.append("))");
- }
- }
- }
- else
- {
- sb.append("(");
- sb.append(m_attributes[i].getName());
- sb.append("=");
- sb.append(m_attributes[i].getValue().toString());
- sb.append(")");
- }
- }
-
- if ((m_attributes != null) && (m_attributes.length > 1))
- {
- sb.append(")");
- }
-
- try
- {
- return FrameworkUtil.createFilter(sb.toString());
- }
- catch (InvalidSyntaxException ex)
- {
- // This should never happen, so we can safely ignore.
- }
-
- return null;
- }
-
- public String toString()
- {
- return getNamespace() + "; " + getFilter().toString();
- }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/RequirementImpl.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/RequirementImpl.java
new file mode 100644
index 0000000..995dabb
--- /dev/null
+++ b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/RequirementImpl.java
@@ -0,0 +1,187 @@
+/*
+ * 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.framework.util.manifestparser;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.felix.framework.capabilityset.Attribute;
+import org.apache.felix.framework.capabilityset.Directive;
+import org.apache.felix.framework.capabilityset.Requirement;
+import org.apache.felix.framework.capabilityset.SimpleFilter;
+import org.apache.felix.framework.util.VersionRange;
+import org.osgi.framework.Constants;
+
+public class RequirementImpl implements Requirement
+{
+ private final String m_namespace;
+ private final SimpleFilter m_filter;
+ private final boolean m_optional;
+ private final List<Directive> m_dirs;
+ private final List<Directive> m_dirsConst;
+
+// TODO: FELIX3 - Get rid of dynamic argument.
+ public RequirementImpl(
+ String namespace, List<Directive> dirs, List<Attribute> attrs)
+ {
+ m_namespace = namespace;
+ m_dirs = dirs;
+ m_dirsConst = Collections.unmodifiableList(m_dirs);
+ m_filter = convertToFilter(attrs);
+
+ // Find resolution import directives.
+ boolean optional = false;
+ for (int dirIdx = 0; dirIdx < m_dirs.size(); dirIdx++)
+ {
+ if (m_dirs.get(dirIdx).getName().equals(Constants.RESOLUTION_DIRECTIVE))
+ {
+ optional = m_dirs.get(dirIdx).getValue().equals(Constants.RESOLUTION_OPTIONAL);
+ }
+ }
+ m_optional = optional;
+ }
+
+ public String getNamespace()
+ {
+ return m_namespace;
+ }
+
+ public SimpleFilter getFilter()
+ {
+ return m_filter;
+ }
+
+ public boolean isOptional()
+ {
+ return m_optional;
+ }
+
+ public Directive getDirective(String name)
+ {
+ for (int i = 0; i < m_dirs.size(); i++)
+ {
+ if (m_dirs.get(i).getName().equals(name))
+ {
+ return m_dirs.get(i);
+ }
+ }
+ return null;
+ }
+
+ public List<Directive> getDirectives()
+ {
+ return m_dirsConst;
+ }
+
+ public String toString()
+ {
+ return m_namespace + "; " + getFilter().toString();
+ }
+
+ private static SimpleFilter convertToFilter(List<Attribute> attrs)
+ {
+ // Rather than building a filter string to be parsed into a SimpleFilter,
+ // we will just create the parsed SimpleFilter directly.
+
+ List<SimpleFilter> filters = new ArrayList<SimpleFilter>();
+
+ for (Attribute attr : attrs)
+ {
+ if (attr.getValue() instanceof VersionRange)
+ {
+ VersionRange vr = (VersionRange) attr.getValue();
+ if (vr.isFloorInclusive())
+ {
+ filters.add(
+ new SimpleFilter(
+ attr.getName(),
+ vr.getFloor().toString(),
+ SimpleFilter.GTE));
+ }
+ else
+ {
+ SimpleFilter not =
+ new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT);
+ ((List) not.getValue()).add(
+ new SimpleFilter(
+ attr.getName(),
+ vr.getFloor().toString(),
+ SimpleFilter.LTE));
+ filters.add(not);
+ }
+
+ if (vr.getCeiling() != null)
+ {
+ if (vr.isCeilingInclusive())
+ {
+ filters.add(
+ new SimpleFilter(
+ attr.getName(),
+ vr.getCeiling().toString(),
+ SimpleFilter.LTE));
+ }
+ else
+ {
+ SimpleFilter not =
+ new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT);
+ ((List) not.getValue()).add(
+ new SimpleFilter(
+ attr.getName(),
+ vr.getCeiling().toString(),
+ SimpleFilter.GTE));
+ filters.add(not);
+ }
+ }
+ }
+ else
+ {
+ List<String> values = SimpleFilter.parseSubstring(attr.getValue().toString());
+ if (values.size() > 1)
+ {
+ filters.add(
+ new SimpleFilter(
+ attr.getName(),
+ values,
+ SimpleFilter.SUBSTRING));
+ }
+ else
+ {
+ filters.add(
+ new SimpleFilter(
+ attr.getName(),
+ values.get(0),
+ SimpleFilter.EQ));
+ }
+ }
+ }
+
+ SimpleFilter sf = null;
+
+ if (filters.size() == 1)
+ {
+ sf = filters.get(0);
+ }
+ else if (attrs.size() > 1)
+ {
+ sf = new SimpleFilter(null, filters, SimpleFilter.AND);
+ }
+
+ return sf;
+ }
+}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/ICapability.java b/framework/src/main/java/org/apache/felix/moduleloader/ICapability.java
deleted file mode 100644
index fdc8509..0000000
--- a/framework/src/main/java/org/apache/felix/moduleloader/ICapability.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.moduleloader;
-
-import java.util.Map;
-
-public interface ICapability
-{
- public static final String MODULE_NAMESPACE = "module";
- public static final String HOST_NAMESPACE = "host";
- public static final String PACKAGE_NAMESPACE = "package";
-
- public static final String PACKAGE_PROPERTY = "package";
- public static final String VERSION_PROPERTY = "version";
-
- IModule getModule();
- String getNamespace();
- Map getProperties();
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/moduleloader/IRequirement.java b/framework/src/main/java/org/apache/felix/moduleloader/IRequirement.java
deleted file mode 100644
index a278fb1..0000000
--- a/framework/src/main/java/org/apache/felix/moduleloader/IRequirement.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.moduleloader;
-
-import org.osgi.framework.Filter;
-
-public interface IRequirement
-{
- String getNamespace();
- Filter getFilter();
- boolean isMultiple();
- boolean isOptional();
- String getComment();
- boolean isSatisfied(ICapability capability);
-}
\ No newline at end of file