felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pa...@apache.org
Subject svn commit: r1103918 [6/12] - in /felix/trunk/framework: ./ src/main/java/org/apache/felix/framework/ src/main/java/org/apache/felix/framework/cache/ src/main/java/org/apache/felix/framework/capabilityset/ src/main/java/org/apache/felix/framework/resol...
Date Mon, 16 May 2011 21:49:05 GMT
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/Util.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/Util.java?rev=1103918&r1=1103917&r2=1103918&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/Util.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/Util.java Mon May 16 21:49:02 2011
@@ -22,22 +22,21 @@ import java.io.*;
 import java.net.URL;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.capabilityset.Capability;
 import org.apache.felix.framework.capabilityset.CapabilitySet;
-import org.apache.felix.framework.wiring.BundleCapabilityImpl;
-import org.apache.felix.framework.wiring.BundleRequirementImpl;
+import org.apache.felix.framework.resolver.Module;
+import org.apache.felix.framework.capabilityset.Requirement;
+import org.apache.felix.framework.resolver.Wire;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRequirement;
-import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.framework.wiring.BundleWire;
 
 public class Util
 {
@@ -87,11 +86,11 @@ public class Util
     }
 
     /**
-     * Converts a revision identifier to a bundle identifier. Revision IDs
+     * Converts a module identifier to a bundle identifier. Module IDs
      * are typically <tt>&lt;bundle-id&gt;.&lt;revision&gt;</tt>; this
      * method returns only the portion corresponding to the bundle ID.
     **/
-    public static long getBundleIdFromRevisionId(String id)
+    public static long getBundleIdFromModuleId(String id)
     {
         try
         {
@@ -281,21 +280,15 @@ public class Util
         return allow;
     }
 
-    public static BundleCapability getSatisfyingCapability(
-        BundleRevision br, BundleRequirementImpl req)
+    public static Capability getSatisfyingCapability(Module m, Requirement req)
     {
-        List<BundleCapability> caps = (br.getWiring() != null)
-            ? br.getWiring().getCapabilities(null)
-            : br.getDeclaredCapabilities(null);
-        if (caps != null)
+        List<Capability> caps = m.getCapabilities();
+        for (int i = 0; (caps != null) && (i < caps.size()); i++)
         {
-            for (BundleCapability cap : caps)
+            if (caps.get(i).getNamespace().equals(req.getNamespace())
+                && CapabilitySet.matches(caps.get(i), req.getFilter()))
             {
-                if (cap.getNamespace().equals(req.getNamespace())
-                    && CapabilitySet.matches((BundleCapabilityImpl) cap, req.getFilter()))
-                {
-                    return cap;
-                }
+                return caps.get(i);
             }
         }
         return null;
@@ -304,65 +297,33 @@ public class Util
     /**
      * Returns all the capabilities from a module that has a specified namespace.
      *
-     * @param br    module providing capabilities
+     * @param module    module providing capabilities
      * @param namespace capability namespace
      * @return array of matching capabilities or empty if none found
      */
-    public static List<BundleCapability> getCapabilityByNamespace(
-        BundleRevision br, String namespace)
+    public static List<Capability> getCapabilityByNamespace(Module module, String namespace)
     {
-        final List<BundleCapability> matching = new ArrayList();
-        final List<BundleCapability> caps = (br.getWiring() != null)
-            ? br.getWiring().getCapabilities(null)
-            : br.getDeclaredCapabilities(null);
-        if (caps != null)
+        final List<Capability> matching = new ArrayList();
+        final List<Capability> caps = module.getCapabilities();
+        for (int capIdx = 0; (caps != null) && (capIdx < caps.size()); capIdx++)
         {
-            for (BundleCapability cap : caps)
+            if (caps.get(capIdx).getNamespace().equals(namespace))
             {
-                if (cap.getNamespace().equals(namespace))
-                {
-                    matching.add(cap);
-                }
+                matching.add(caps.get(capIdx));
             }
         }
         return matching;
     }
 
-    public static List<BundleRequirement> getDynamicRequirements(
-        List<BundleRequirement> reqs)
-    {
-        List<BundleRequirement> result = new ArrayList<BundleRequirement>();
-        if (reqs != null)
-        {
-            for (BundleRequirement req : reqs)
-            {
-                String resolution = req.getDirectives().get(Constants.RESOLUTION_DIRECTIVE);
-                if ((resolution != null) && resolution.equals("dynamic"))
-                {
-                    result.add(req);
-                }
-            }
-        }
-        return result;
-    }
-
-    public static BundleWire getWire(BundleRevision br, String name)
+    public static Wire getWire(Module m, String name)
     {
-        if (br.getWiring() != null)
+        List<Wire> wires = m.getWires();
+        for (int i = 0; (wires != null) && (i < wires.size()); i++)
         {
-            List<BundleWire> wires = br.getWiring().getRequiredWires(null);
-            if (wires != null)
+            if (wires.get(i).getCapability().getNamespace().equals(Capability.PACKAGE_NAMESPACE) &&
+                wires.get(i).getCapability().getAttribute(Capability.PACKAGE_ATTR).getValue().equals(name))
             {
-                for (BundleWire w : wires)
-                {
-                    if (w.getCapability().getNamespace()
-                            .equals(BundleCapabilityImpl.PACKAGE_NAMESPACE) &&
-                        w.getCapability().getAttributes()
-                            .get(BundleCapabilityImpl.PACKAGE_ATTR).equals(name))
-                    {
-                        return w;
-                    }
-                }
+                return wires.get(i);
             }
         }
         return null;
@@ -614,8 +575,9 @@ public class Util
      * @return <code>true</code> if the module declares a fragment host, <code>false</code>
      *      otherwise.
      */
-    public static boolean isFragment(BundleRevision revision)
+    public static boolean isFragment(Module module)
     {
-        return ((revision.getTypes() & BundleRevision.TYPE_FRAGMENT) > 0);
+        Map headerMap = module.getHeaders();
+        return headerMap.containsKey(Constants.FRAGMENT_HOST);
     }
 }
\ No newline at end of file

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java?rev=1103918&r1=1103917&r2=1103918&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java Mon May 16 21:49:02 2011
@@ -21,35 +21,35 @@ package org.apache.felix.framework.util.
 import java.util.*;
 import java.util.ArrayList;
 import java.util.Map.Entry;
-import org.apache.felix.framework.BundleRevisionImpl;
 
 import org.apache.felix.framework.Logger;
-import org.apache.felix.framework.wiring.BundleCapabilityImpl;
+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.framework.wiring.BundleRequirementImpl;
 import org.osgi.framework.*;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRequirement;
-import org.osgi.framework.wiring.BundleRevision;
 
 public class ManifestParser
 {
     private final Logger m_logger;
     private final Map m_configMap;
     private final Map m_headerMap;
-    private volatile int m_activationPolicy = BundleRevisionImpl.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 List<BundleCapability> m_capabilities;
-    private volatile List<BundleRequirement> m_requirements;
+    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, BundleRevision owner, Map headerMap)
+    public ManifestParser(Logger logger, Map configMap, Module owner, Map headerMap)
         throws BundleException
     {
         m_logger = logger;
@@ -65,7 +65,7 @@ public class ManifestParser
         }
 
         // Create lists to hold capabilities and requirements.
-        List<BundleCapabilityImpl> capList = new ArrayList();
+        List<Capability> capList = new ArrayList();
 
         //
         // Parse bundle version.
@@ -76,8 +76,7 @@ public class ManifestParser
         {
             try
             {
-                m_bundleVersion = Version.parseVersion(
-                    (String) headerMap.get(Constants.BUNDLE_VERSION));
+                m_bundleVersion = Version.parseVersion((String) headerMap.get(Constants.BUNDLE_VERSION));
             }
             catch (RuntimeException ex)
             {
@@ -94,41 +93,37 @@ public class ManifestParser
         // Parse bundle symbolic name.
         //
 
-        BundleCapabilityImpl requireCap = parseBundleSymbolicName(owner, m_headerMap);
-        if (requireCap != null)
+        Capability moduleCap = parseBundleSymbolicName(owner, m_headerMap);
+        if (moduleCap != null)
         {
             m_bundleSymbolicName = (String)
-                requireCap.getAttributes().get(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE);
+                moduleCap.getAttribute(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE).getValue();
 
-            // Add a bundle capability and a host capability to all
+            // Add a module capability and a host capability to all
             // non-fragment bundles. A host capability is the same
-            // as a require capability, but with a different capability
-            // namespace. Bundle capabilities resolve required-bundle
+            // as a module capability, but with a different capability
+            // namespace. Module capabilities resolve required-bundle
             // dependencies, while host capabilities resolve fragment-host
             // dependencies.
             if (headerMap.get(Constants.FRAGMENT_HOST) == null)
             {
-                capList.add(requireCap);
-                capList.add(new BundleCapabilityImpl(
-                    owner, BundleCapabilityImpl.HOST_NAMESPACE,
-                    Collections.EMPTY_MAP,
-// TODO: OSGi R4.3 - Wraps map as unmodifiable twice.
-                    requireCap.getAttributes()));
+                capList.add(moduleCap);
+                capList.add(new CapabilityImpl(
+                    owner, Capability.HOST_NAMESPACE, new ArrayList<Directive>(0),
+                    ((CapabilityImpl) moduleCap).getAttributes()));
             }
 
             // Add a singleton capability if the bundle is a singleton.
             // This is sort of a hack, but we need this for the resolver
             // to be able to resolve singletons. It is not possible to
-            // attach this information to the bundle or host capabilities
+            // attach this information to the module or host capabilities
             // because fragments don't have those capabilities, but fragments
             // can be singletons too.
-            if (isSingleton(requireCap))
+            if (isSingleton(moduleCap))
             {
-                capList.add(new BundleCapabilityImpl(
-                    owner, BundleCapabilityImpl.SINGLETON_NAMESPACE,
-                    Collections.EMPTY_MAP,
-// TODO: OSGi R4.3 - Wraps map as unmodifiable twice.
-                    requireCap.getAttributes()));
+                capList.add(new CapabilityImpl(
+                    owner, Capability.SINGLETON_NAMESPACE, new ArrayList<Directive>(0),
+                    ((CapabilityImpl) moduleCap).getAttributes()));
             }
         }
 
@@ -143,7 +138,7 @@ public class ManifestParser
         // Parse Fragment-Host.
         //
 
-        List<BundleRequirementImpl> hostReqs = parseFragmentHost(m_logger, owner, m_headerMap);
+        List<Requirement> hostReqs = parseFragmentHost(m_logger, owner, m_headerMap);
 
         //
         // Parse Require-Bundle
@@ -152,7 +147,7 @@ public class ManifestParser
         List<ParsedHeaderClause> requireClauses =
             parseStandardHeader((String) headerMap.get(Constants.REQUIRE_BUNDLE));
         requireClauses = normalizeRequireClauses(m_logger, requireClauses, getManifestVersion());
-        List<BundleRequirementImpl> requireReqs = convertRequires(requireClauses, owner);
+        List<Requirement> requireReqs = convertRequires(requireClauses, owner);
 
         //
         // Parse Import-Package.
@@ -161,7 +156,7 @@ public class ManifestParser
         List<ParsedHeaderClause> importClauses =
             parseStandardHeader((String) headerMap.get(Constants.IMPORT_PACKAGE));
         importClauses = normalizeImportClauses(m_logger, importClauses, getManifestVersion());
-        List<BundleRequirement> importReqs = convertImports(importClauses, owner);
+        List<Requirement> importReqs = convertImports(importClauses, owner);
 
         //
         // Parse DynamicImport-Package.
@@ -170,7 +165,7 @@ public class ManifestParser
         List<ParsedHeaderClause> dynamicClauses =
             parseStandardHeader((String) headerMap.get(Constants.DYNAMICIMPORT_PACKAGE));
         dynamicClauses = normalizeDynamicImportClauses(m_logger, dynamicClauses, getManifestVersion());
-        List<BundleRequirement> dynamicReqs = convertImports(dynamicClauses, owner);
+        m_dynamicRequirements = convertImports(dynamicClauses, owner);
 
         //
         // Parse Export-Package.
@@ -181,7 +176,7 @@ public class ManifestParser
             parseStandardHeader((String) headerMap.get(Constants.EXPORT_PACKAGE));
         exportClauses = normalizeExportClauses(logger, exportClauses,
             getManifestVersion(), m_bundleSymbolicName, m_bundleVersion);
-        List<BundleCapability> exportCaps = convertExports(exportClauses, owner);
+        List<Capability> exportCaps = convertExports(exportClauses, owner);
 
         //
         // Calculate implicit imports.
@@ -209,17 +204,16 @@ public class ManifestParser
 
         // Combine all requirements.
         m_requirements = new ArrayList(
-             importReqs.size() + requireReqs.size() + hostReqs.size() + dynamicReqs.size());
+             importReqs.size() + requireReqs.size() + hostReqs.size());
         m_requirements.addAll(importReqs);
         m_requirements.addAll(requireReqs);
         m_requirements.addAll(hostReqs);
-        m_requirements.addAll(dynamicReqs);
 
         //
         // Parse Bundle-NativeCode.
         //
 
-        // Parse native library clauses.
+        // Get native library entry names for module library sources.
         m_libraryClauses =
             parseLibraryStrings(
                 m_logger,
@@ -245,14 +239,18 @@ public class ManifestParser
         m_isExtension = checkExtensionBundle(headerMap);
     }
 
-    private static boolean isSingleton(BundleCapabilityImpl cap)
+    private static boolean isSingleton(Capability cap)
     {
-        if (cap.getNamespace().equals(BundleCapabilityImpl.BUNDLE_NAMESPACE))
+        if (cap.getNamespace().equals(Capability.MODULE_NAMESPACE))
         {
-            String value = cap.getDirectives().get(Constants.SINGLETON_DIRECTIVE);
-            if ((value != null) && Boolean.valueOf(value))
+            final List<Directive> dirs = cap.getDirectives();
+            for (int dirIdx = 0; (dirs != null) && (dirIdx < dirs.size()); dirIdx++)
             {
-                return true;
+                if (dirs.get(dirIdx).getName().equalsIgnoreCase(Constants.SINGLETON_DIRECTIVE)
+                    && Boolean.valueOf((String) dirs.get(dirIdx).getValue()))
+                {
+                    return true;
+                }
             }
         }
         return false;
@@ -264,17 +262,27 @@ public class ManifestParser
     {
         // Verify that the values are equals if the package specifies
         // both version and specification-version attributes.
-        Set dupeSet = new HashSet();
-        for (ParsedHeaderClause clause : clauses)
+        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.
-            Object v = clause.m_attrs.get(Constants.VERSION_ATTRIBUTE);
-            Object sv = clause.m_attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
+            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).trim().equals(((String) sv).trim()))
+                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.");
@@ -285,26 +293,40 @@ public class ManifestParser
             // it to the VersionRange type.
             if ((v != null) || (sv != null))
             {
-                clause.m_attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+                attrMap.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
                 v = (v == null) ? sv : v;
-                clause.m_attrs.put(
-                    Constants.VERSION_ATTRIBUTE,
-                    VersionRange.parse(v.toString()));
+                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 = clause.m_attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+            v = attrMap.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
             if (v != null)
             {
-                clause.m_attrs.put(
-                    Constants.BUNDLE_VERSION_ATTRIBUTE,
-                    VersionRange.parse(v.toString()));
+                attrMap.put(Constants.BUNDLE_VERSION_ATTRIBUTE,
+                    new Attribute(
+                        Constants.BUNDLE_VERSION_ATTRIBUTE,
+                        VersionRange.parse(v.getValue().toString()),
+                        v.isMandatory()));
             }
 
-            // Verify java.* is not imported, nor any duplicate imports.
-            for (int pathIdx = 0; pathIdx < clause.m_paths.size(); pathIdx++)
+            // Re-copy the attributes in case they changed.
+            clauses.get(clauseIdx).m_attrs.clear();
+            clauses.get(clauseIdx).m_attrs.addAll(attrMap.values());
+        }
+
+        // Verify java.* is not imported, nor any duplicate imports.
+        Set dupeSet = new HashSet();
+        for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
+        {
+            // 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 = clause.m_paths.get(pathIdx);
+                String pkgName = paths.get(pathIdx);
                 if (!dupeSet.contains(pkgName))
                 {
                     // Verify that java.* packages are not imported.
@@ -314,7 +336,7 @@ public class ManifestParser
                             "Importing java.* packages not allowed: " + pkgName);
                     }
                     // Make sure a package name was specified.
-                    else if (clause.m_paths.get(pathIdx).length() == 0)
+                    else if (clauses.get(clauseIdx).m_paths.get(pathIdx).length() == 0)
                     {
                         throw new BundleException(
                             "Imported package names cannot be zero length.");
@@ -326,11 +348,17 @@ public class ManifestParser
                     throw new BundleException("Duplicate import: " + pkgName);
                 }
             }
+        }
 
-            if (!mv.equals("2"))
+        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 (!clause.m_dirs.isEmpty())
+                if (clauses.get(clauseIdx).m_dirs.size() != 0)
                 {
                     throw new BundleException("R3 imports cannot contain directives.");
                 }
@@ -340,26 +368,37 @@ public class ManifestParser
                 // because the package class normalizes to "version" to avoid having
                 // future special cases. This could be changed if more strict behavior
                 // is required.
-                if (!clause.m_attrs.isEmpty())
+                if (clauses.get(clauseIdx).m_attrs.size() != 0)
                 {
                     // R3 package requirements should only have version attributes.
-                    Object pkgVersion = clause.m_attrs.get(BundleCapabilityImpl.VERSION_ATTR);
-                    pkgVersion = (pkgVersion == null)
-                        ? new VersionRange(Version.emptyVersion, true, null, true)
-                        : pkgVersion;
-                    for (Entry<String, Object> entry : clause.m_attrs.entrySet())
+                    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 (!entry.getKey().equals(BundleCapabilityImpl.VERSION_ATTR))
+                        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: "
-                                    + entry.getKey());
+                                    + clauses.get(clauseIdx).m_attrs.get(attrIdx).getName());
                         }
                     }
 
-                    // Remove all other attributes except package version.
-                    clause.m_attrs.clear();
-                    clause.m_attrs.put(BundleCapabilityImpl.VERSION_ATTR, pkgVersion);
+                    // 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));
                 }
             }
         }
@@ -367,8 +406,8 @@ public class ManifestParser
         return clauses;
     }
 
-    private static List<BundleRequirement> convertImports(
-        List<ParsedHeaderClause> clauses, BundleRevision owner)
+    private static List<Requirement> convertImports(
+        List<ParsedHeaderClause> clauses, Module owner)
     {
         // Now convert generic header clauses into requirements.
         List reqList = new ArrayList();
@@ -379,23 +418,18 @@ public class ManifestParser
                 pathIdx++)
             {
                 // Prepend the package name to the array of attributes.
-                Map<String, Object> attrs = clauses.get(clauseIdx).m_attrs;
-                // Note that we use a linked hash map here to ensure the
-                // package attribute is first, which will make indexing
-                // more efficient.
-// TODO: OSGi R4.3 - This is a hack...perhaps we should use the standard "key"
-//       notion where namespace is also the name of the key attribute.
-                Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
-                newAttrs.put(
-                    BundleCapabilityImpl.PACKAGE_ATTR,
-                    clauses.get(clauseIdx).m_paths.get(pathIdx));
-                newAttrs.putAll(attrs);
+                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 BundleRequirementImpl(
+                    new RequirementImpl(
                         owner,
-                        BundleCapabilityImpl.PACKAGE_NAMESPACE,
+                        Capability.PACKAGE_NAMESPACE,
                         clauses.get(clauseIdx).m_dirs,
                         newAttrs));
             }
@@ -410,30 +444,27 @@ public class ManifestParser
     {
         // Verify that the values are equals if the package specifies
         // both version and specification-version attributes.
-        for (ParsedHeaderClause clause : clauses)
+        Map<String, Attribute> attrMap = new HashMap();
+        for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
         {
-            if (!mv.equals("2"))
+            // 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++)
             {
-                // R3 bundles cannot have directives on their imports.
-                if (!clause.m_dirs.isEmpty())
-                {
-                    throw new BundleException("R3 imports cannot contain directives.");
-                }
+                Attribute attr = clauses.get(clauseIdx).m_attrs.get(attrIdx);
+                attrMap.put(attr.getName(), attr);
             }
 
-            // Add the resolution directive to indicate that these are
-            // dynamic imports.
-// TODO: OSGi R4.3 - Use real constant value for "dynamic".
-            clause.m_dirs.put(Constants.RESOLUTION_DIRECTIVE, "dynamic");
-
             // Check for "version" and "specification-version" attributes
             // and verify they are the same if both are specified.
-            Object v = clause.m_attrs.get(Constants.VERSION_ATTRIBUTE);
-            Object sv = clause.m_attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
+            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).trim().equals(((String) sv).trim()))
+                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.");
@@ -444,27 +475,40 @@ public class ManifestParser
             // it to the VersionRange type.
             if ((v != null) || (sv != null))
             {
-                clause.m_attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+                attrMap.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
                 v = (v == null) ? sv : v;
-                clause.m_attrs.put(
-                    Constants.VERSION_ATTRIBUTE,
-                    VersionRange.parse(v.toString()));
+                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 = clause.m_attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+            v = attrMap.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
             if (v != null)
             {
-                clause.m_attrs.put(
-                    Constants.BUNDLE_VERSION_ATTRIBUTE,
-                    VersionRange.parse(v.toString()));
+                attrMap.put(Constants.BUNDLE_VERSION_ATTRIBUTE,
+                    new Attribute(
+                        Constants.BUNDLE_VERSION_ATTRIBUTE,
+                        VersionRange.parse(v.getValue().toString()),
+                        v.isMandatory()));
             }
 
-            // Dynamic imports can have duplicates, so verify that java.*
-            // packages are not imported.
-            for (int pathIdx = 0; pathIdx < clause.m_paths.size(); pathIdx++)
+            // 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 = clause.m_paths.get(pathIdx);
+                String pkgName = paths.get(pathIdx);
                 if (pkgName.startsWith("java."))
                 {
                     throw new BundleException(
@@ -478,6 +522,21 @@ public class ManifestParser
             }
         }
 
+        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;
     }
 
@@ -487,33 +546,49 @@ public class ManifestParser
         throws BundleException
     {
         // Verify that "java.*" packages are not exported.
-        for (ParsedHeaderClause clause : clauses)
+        for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
         {
             // Verify that the named package has not already been declared.
-            for (int pathIdx = 0; pathIdx < clause.m_paths.size(); pathIdx++)
+            for (int pathIdx = 0; pathIdx < clauses.get(clauseIdx).m_paths.size(); pathIdx++)
             {
                 // Verify that java.* packages are not exported.
-                if (clause.m_paths.get(pathIdx).startsWith("java."))
+                if (clauses.get(clauseIdx).m_paths.get(pathIdx).startsWith("java."))
                 {
                     throw new BundleException(
                         "Exporting java.* packages not allowed: "
-                        + clause.m_paths.get(pathIdx));
+                        + clauses.get(clauseIdx).m_paths.get(pathIdx));
                 }
-                else if (clause.m_paths.get(pathIdx).length() == 0)
+                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.
-            Object v = clause.m_attrs.get(Constants.VERSION_ATTRIBUTE);
-            Object sv = clause.m_attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
+            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).trim().equals(((String) sv).trim()))
+                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.");
@@ -523,7 +598,8 @@ public class ManifestParser
             // Always add the default version if not specified.
             if ((v == null) && (sv == null))
             {
-                v = Version.emptyVersion;
+                v = new Attribute(
+                    Constants.VERSION_ATTRIBUTE, Version.emptyVersion, false);
             }
 
             // Ensure that only the "version" attribute is used and convert
@@ -531,34 +607,57 @@ public class ManifestParser
             if ((v != null) || (sv != null))
             {
                 // Convert version attribute to type Version.
-                clause.m_attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+                attrMap.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
                 v = (v == null) ? sv : v;
-                clause.m_attrs.put(
-                    Constants.VERSION_ATTRIBUTE,
-                    Version.parseVersion(v.toString()));
+                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"))
-            {
-                // Find symbolic name and version attribute, if present.
-                if (clause.m_attrs.containsKey(Constants.BUNDLE_VERSION_ATTRIBUTE)
-                    || clause.m_attrs.containsKey(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE))
-                {
-                    throw new BundleException(
-                        "Exports must not specify bundle symbolic name or bundle version.");
+        // 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.
-                clause.m_attrs.put(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, bsn);
-                clause.m_attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bv);
+                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"))
+        }
+        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 (!clause.m_dirs.isEmpty())
+                if (clauses.get(clauseIdx).m_dirs.size() != 0)
                 {
                     throw new BundleException("R3 exports cannot contain directives.");
                 }
@@ -568,31 +667,37 @@ public class ManifestParser
                 // because the package class normalizes to "version" to avoid having
                 // future special cases. This could be changed if more strict behavior
                 // is required.
-                if (!clause.m_attrs.isEmpty())
+                if (clauses.get(clauseIdx).m_attrs.size() != 0)
                 {
                     // R3 package capabilities should only have a version attribute.
-                    Object pkgVersion = clause.m_attrs.get(BundleCapabilityImpl.VERSION_ATTR);
-                    pkgVersion = (pkgVersion == null)
-                        ? Version.emptyVersion
-                        : pkgVersion;
-                    for (Entry<String, Object> entry : clause.m_attrs.entrySet())
+                    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 (!entry.getKey().equals(BundleCapabilityImpl.VERSION_ATTR))
+                        if (attrs.get(attrIdx).getName().equals(Capability.VERSION_ATTR))
+                        {
+                            pkgVersion = attrs.get(attrIdx);
+                        }
+                        else
                         {
                             logger.log(
                                 Logger.LOG_WARNING,
                                 "Unknown R3 export attribute: "
-                                + entry.getKey());
+                                + attrs.get(attrIdx).getName());
                         }
                     }
 
-                    // Remove all other attributes except package version.
-                    clause.m_attrs.clear();
-                    clause.m_attrs.put(BundleCapabilityImpl.VERSION_ATTR, pkgVersion);
+                    // 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;
     }
 
@@ -638,16 +743,21 @@ public class ManifestParser
         return m_bundleVersion;
     }
 
-    public List<BundleCapability> getCapabilities()
+    public List<Capability> getCapabilities()
     {
         return m_capabilities;
     }
 
-    public List<BundleRequirement> getRequirements()
+    public List<Requirement> getRequirements()
     {
         return m_requirements;
     }
 
+    public List<Requirement> getDynamicRequirements()
+    {
+        return m_dynamicRequirements;
+    }
+
     public List<R4LibraryClause> getLibraryClauses()
     {
         return m_libraryClauses;
@@ -743,7 +853,7 @@ public class ManifestParser
 
             // Select the matching native clause.
             int selected = 0;
-            if (clauseList.isEmpty())
+            if (clauseList.size() == 0)
             {
                 // If optional clause exists, no error thrown.
                 if (m_libraryHeadersOptional)
@@ -826,7 +936,7 @@ public class ManifestParser
             }
         }
 
-        if (selection.isEmpty())
+        if (selection.size() == 0)
         {
             // Re-init index list.
             selection.clear();
@@ -857,7 +967,7 @@ public class ManifestParser
         }
 
         // Return the first sorted clause
-        if (selection.isEmpty())
+        if (selection.size() == 0)
         {
             return 0;
         }
@@ -868,7 +978,7 @@ public class ManifestParser
     }
 
     private static List<ParsedHeaderClause> calculateImplicitImports(
-        List<BundleCapability> exports, List<ParsedHeaderClause> imports)
+        List<Capability> exports, List<ParsedHeaderClause> imports)
         throws BundleException
     {
         List<ParsedHeaderClause> clauseList = new ArrayList();
@@ -890,32 +1000,34 @@ public class ManifestParser
         // Add import requirement for each export capability.
         for (int i = 0; i < exports.size(); i++)
         {
-            if (map.get(exports.get(i).getAttributes()
-                .get(BundleCapabilityImpl.PACKAGE_ATTR)) == null)
+            if (map.get(exports.get(i).getAttribute(Capability.PACKAGE_ATTR).getValue()) == null)
             {
                 // Convert Version to VersionRange.
-                Map<String, Object> attrs = new HashMap<String, Object>();
-                Object version = exports.get(i).getAttributes().get(Constants.VERSION_ATTRIBUTE);
-                if (version != null)
+                List<Attribute> attrs = new ArrayList<Attribute>(exports.get(i).getAttributes());
+                for (int attrIdx = 0; (attrs != null) && (attrIdx < attrs.size()); attrIdx++)
                 {
-                    attrs.put(
-                        Constants.VERSION_ATTRIBUTE,
-                        VersionRange.parse(version.toString()));
+                    if (attrs.get(attrIdx).getName().equals(Constants.VERSION_ATTRIBUTE))
+                    {
+                        attrs.set(attrIdx, new Attribute(
+                            attrs.get(attrIdx).getName(),
+                            VersionRange.parse(attrs.get(attrIdx).getValue().toString()),
+                            attrs.get(attrIdx).isMandatory()));
+                    }
                 }
 
                 List<String> paths = new ArrayList();
                 paths.add((String)
-                    exports.get(i).getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR));
+                    exports.get(i).getAttribute(Capability.PACKAGE_ATTR).getValue());
                 clauseList.add(
-                    new ParsedHeaderClause(paths, Collections.EMPTY_MAP, attrs));
+                    new ParsedHeaderClause(paths, new ArrayList<Directive>(0), attrs));
             }
         }
 
         return clauseList;
     }
 
-    private static List<BundleCapability> calculateImplicitUses(
-        List<BundleCapability> exports, List<ParsedHeaderClause> imports)
+    private static List<Capability> calculateImplicitUses(
+        List<Capability> exports, List<ParsedHeaderClause> imports)
         throws BundleException
     {
         // Add a "uses" directive onto each export of R3 bundles
@@ -933,14 +1045,16 @@ public class ManifestParser
                     + imports.get(i).m_paths.get(pathIdx);
             }
         }
+        Directive uses = new Directive(
+            Constants.USES_DIRECTIVE, usesValue);
         for (int i = 0; i < exports.size(); i++)
         {
-            Map<String, String> dirs = new HashMap<String, String>(1);
-            dirs.put(Constants.USES_DIRECTIVE, usesValue);
-            exports.set(i, new BundleCapabilityImpl(
-                exports.get(i).getRevision(),
-                BundleCapabilityImpl.PACKAGE_NAMESPACE,
-                dirs,
+            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()));
         }
 
@@ -949,13 +1063,13 @@ public class ManifestParser
 
     private static boolean checkExtensionBundle(Map headerMap) throws BundleException
     {
-        Object extension = parseExtensionBundleHeader(
+        Directive extension = parseExtensionBundleHeader(
             (String) headerMap.get(Constants.FRAGMENT_HOST));
 
         if (extension != null)
         {
-            if (!(Constants.EXTENSION_FRAMEWORK.equals(extension) ||
-                Constants.EXTENSION_BOOTCLASSPATH.equals(extension)))
+            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'");
@@ -973,8 +1087,7 @@ public class ManifestParser
         return false;
     }
 
-    private static BundleCapabilityImpl parseBundleSymbolicName(
-        BundleRevision owner, Map headerMap)
+    private static Capability parseBundleSymbolicName(Module owner, Map headerMap)
         throws BundleException
     {
         List<ParsedHeaderClause> clauses = parseStandardHeader(
@@ -1015,14 +1128,16 @@ public class ManifestParser
                 }
             }
 
-            // Create a require capability and return it.
+            // Create a module capability and return it.
             String symName = (String) clauses.get(0).m_paths.get(0);
-            Map<String, Object> attrs = new HashMap<String, Object>(2);
-            attrs.put(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, symName);
-            attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bundleVersion);
-            return new BundleCapabilityImpl(
+            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,
-                BundleCapabilityImpl.BUNDLE_NAMESPACE,
+                Capability.MODULE_NAMESPACE,
                 clauses.get(0).m_dirs,
                 attrs);
         }
@@ -1030,11 +1145,11 @@ public class ManifestParser
         return null;
     }
 
-    private static List<BundleRequirementImpl> parseFragmentHost(
-        Logger logger, BundleRevision owner, Map headerMap)
+    private static List<Requirement> parseFragmentHost(
+        Logger logger, Module owner, Map headerMap)
         throws BundleException
     {
-        List<BundleRequirementImpl> reqs = new ArrayList();
+        List<Requirement> reqs = new ArrayList();
 
         String mv = getManifestVersion(headerMap);
         if ((mv != null) && mv.equals("2"))
@@ -1058,12 +1173,10 @@ public class ManifestParser
                 }
 
                 // Strip all attributes other than bundle-version.
-                for (Iterator<Entry<String, Object>> it =
-                        clauses.get(0).m_attrs.entrySet().iterator();
-                    it.hasNext(); )
+                for (Iterator<Attribute> it = clauses.get(0).m_attrs.iterator(); it.hasNext(); )
                 {
-                    Entry<String, Object> entry = it.next();
-                    if (!entry.getKey().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
+                    Attribute attr = it.next();
+                    if (!attr.getName().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
                     {
                         it.remove();
                     }
@@ -1071,24 +1184,26 @@ public class ManifestParser
 
                 // If the bundle-version attribute is specified, then convert
                 // it to the proper type.
-                Object value = clauses.get(0).m_attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
-                if (value != null)
+                if (clauses.get(0).m_attrs.size() == 1)
                 {
-                    clauses.get(0).m_attrs.put(
-                        Constants.BUNDLE_VERSION_ATTRIBUTE,
-                        VersionRange.parse(value.toString()));
+                    Attribute attr = clauses.get(0).m_attrs.get(0);
+                    clauses.get(0).m_attrs.set(0,
+                        new Attribute(
+                            Constants.BUNDLE_VERSION_ATTRIBUTE,
+                            VersionRange.parse(attr.getValue().toString()),
+                            attr.isMandatory()));
                 }
 
                 // Prepend the host symbolic name to the array of attributes.
-                Map<String, Object> attrs = clauses.get(0).m_attrs;
-                Map<String, Object> newAttrs = new HashMap<String, Object>(attrs.size() + 1);
-                newAttrs.put(
+                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.get(0).m_paths.get(0));
-                newAttrs.putAll(attrs);
+                    clauses.get(0).m_paths.get(0), false));
+                newAttrs.addAll(attrs);
 
-                reqs.add(new BundleRequirementImpl(
-                    owner, BundleCapabilityImpl.HOST_NAMESPACE,
+                reqs.add(new RequirementImpl(
+                    owner, Capability.HOST_NAMESPACE,
                     clauses.get(0).m_dirs,
                     newAttrs));
             }
@@ -1107,11 +1222,11 @@ public class ManifestParser
         return reqs;
     }
 
-    public static List<BundleCapability> parseExportHeader(
-        Logger logger, BundleRevision owner, String header, String bsn, Version bv)
+    public static List<Capability> parseExportHeader(
+        Logger logger, Module owner, String header, String bsn, Version bv)
     {
 
-        List<BundleCapability> caps = null;
+        List<Capability> caps = null;
         try
         {
             List<ParsedHeaderClause> exportClauses = parseStandardHeader(header);
@@ -1125,10 +1240,10 @@ public class ManifestParser
         return caps;
     }
 
-    private static List<BundleCapability> convertExports(
-        List<ParsedHeaderClause> clauses, BundleRevision owner)
+    private static List<Capability> convertExports(
+        List<ParsedHeaderClause> clauses, Module owner)
     {
-        List<BundleCapability> capList = new ArrayList();
+        List<Capability> capList = new ArrayList();
         for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
         {
             for (int pathIdx = 0;
@@ -1136,18 +1251,18 @@ public class ManifestParser
                 pathIdx++)
             {
                 // Prepend the package name to the array of attributes.
-                Map<String, Object> attrs = clauses.get(clauseIdx).m_attrs;
-                Map<String, Object> newAttrs = new HashMap<String, Object>(attrs.size() + 1);
-                newAttrs.put(
-                    BundleCapabilityImpl.PACKAGE_ATTR,
-                    clauses.get(clauseIdx).m_paths.get(pathIdx));
-                newAttrs.putAll(attrs);
+                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 BundleCapabilityImpl(
+                    new CapabilityImpl(
                         owner,
-                        BundleCapabilityImpl.PACKAGE_NAMESPACE,
+                        Capability.PACKAGE_NAMESPACE,
                         clauses.get(clauseIdx).m_dirs,
                         newAttrs));
             }
@@ -1169,13 +1284,19 @@ public class ManifestParser
             // Convert bundle version attribute to VersionRange type.
             for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
             {
-                Object value = clauses.get(clauseIdx).m_attrs.get(
-                    Constants.BUNDLE_VERSION_ATTRIBUTE);
-                if (value != null)
+                for (int attrIdx = 0;
+                    attrIdx < clauses.get(clauseIdx).m_attrs.size();
+                    attrIdx++)
                 {
-                    clauses.get(clauseIdx).m_attrs.put(
-                        Constants.BUNDLE_VERSION_ATTRIBUTE,
-                        VersionRange.parse(value.toString()));
+                    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()));
+                    }
                 }
             }
         }
@@ -1183,35 +1304,30 @@ public class ManifestParser
         return clauses;
     }
 
-    private static List<BundleRequirementImpl> convertRequires(
-        List<ParsedHeaderClause> clauses, BundleRevision owner)
+    private static List<Requirement> convertRequires(
+        List<ParsedHeaderClause> clauses, Module owner)
     {
-        List<BundleRequirementImpl> reqList = new ArrayList();
+        List<Requirement> reqList = new ArrayList();
         for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
         {
+            List<Attribute> attrs = clauses.get(clauseIdx).m_attrs;
+
             for (int pathIdx = 0;
                 pathIdx < clauses.get(clauseIdx).m_paths.size();
                 pathIdx++)
             {
-                // Prepend the bundle symbolic name to the array of attributes.
-                Map<String, Object> attrs = clauses.get(clauseIdx).m_attrs;
-                // Note that we use a linked hash map here to ensure the
-                // package attribute is first, which will make indexing
-                // more efficient.
-// TODO: OSGi R4.3 - This is a hack...perhaps we should use the standard "key"
-//       notion where namespace is also the name of the key attribute.
                 // Prepend the symbolic name to the array of attributes.
-                Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
-                newAttrs.put(
+                List<Attribute> newAttrs = new ArrayList<Attribute>(attrs.size() + 1);
+                newAttrs.add(new Attribute(
                     Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE,
-                    clauses.get(clauseIdx).m_paths.get(pathIdx));
-                newAttrs.putAll(attrs);
+                    clauses.get(clauseIdx).m_paths.get(pathIdx), false));
+                newAttrs.addAll(attrs);
 
                 // Create package requirement and add to requirement list.
                 reqList.add(
-                    new BundleRequirementImpl(
+                    new RequirementImpl(
                         owner,
-                        BundleCapabilityImpl.BUNDLE_NAMESPACE,
+                        Capability.MODULE_NAMESPACE,
                         clauses.get(clauseIdx).m_dirs,
                         newAttrs));
             }
@@ -1220,26 +1336,27 @@ public class ManifestParser
         return reqList;
     }
 
-    public static String parseExtensionBundleHeader(String header)
+    public static Directive parseExtensionBundleHeader(String header)
         throws BundleException
     {
         List<ParsedHeaderClause> clauses = parseStandardHeader(header);
 
-        String result = null;
+        Directive result = null;
 
         if (clauses.size() == 1)
         {
             // See if there is the "extension" directive.
-            for (Entry<String, String> entry : clauses.get(0).m_dirs.entrySet())
+            List<Directive> dirs = clauses.get(0).m_dirs;
+            for (int dirIdx = 0; (result == null) && (dirIdx < dirs.size()); dirIdx++)
             {
-                if (Constants.EXTENSION_DIRECTIVE.equals(entry.getKey()))
+                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.get(0).m_paths.get(0)) ||
                         Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(clauses.get(0).m_paths.get(0)))
                     {
-                        return entry.getValue();
+                        result = (Directive) dirs.get(dirIdx);
                     }
                     else
                     {
@@ -1255,7 +1372,7 @@ public class ManifestParser
 
     private void parseActivationPolicy(Map headerMap)
     {
-        m_activationPolicy = BundleRevisionImpl.EAGER_ACTIVATION;
+        m_activationPolicy = Module.EAGER_ACTIVATION;
 
         List<ParsedHeaderClause> clauses = parseStandardHeader(
             (String) headerMap.get(Constants.BUNDLE_ACTIVATIONPOLICY));
@@ -1268,16 +1385,17 @@ public class ManifestParser
             {
                 if (clauses.get(0).m_paths.get(clauseIdx).equals(Constants.ACTIVATION_LAZY))
                 {
-                    m_activationPolicy = BundleRevisionImpl.LAZY_ACTIVATION;
-                    for (Entry<String, String> entry : clauses.get(0).m_dirs.entrySet())
+                    m_activationPolicy = Module.LAZY_ACTIVATION;
+                    for (int dirIdx = 0; dirIdx < clauses.get(0).m_dirs.size(); dirIdx++)
                     {
-                        if (entry.getKey().equalsIgnoreCase(Constants.INCLUDE_DIRECTIVE))
+                        Directive dir = clauses.get(0).m_dirs.get(dirIdx);
+                        if (dir.getName().equalsIgnoreCase(Constants.INCLUDE_DIRECTIVE))
                         {
-                            m_activationIncludeDir = entry.getValue();
+                            m_activationIncludeDir = (String) dir.getValue();
                         }
-                        else if (entry.getKey().equalsIgnoreCase(Constants.EXCLUDE_DIRECTIVE))
+                        else if (dir.getName().equalsIgnoreCase(Constants.EXCLUDE_DIRECTIVE))
                         {
-                            m_activationExcludeDir = entry.getValue();
+                            m_activationExcludeDir = (String) dir.getValue();
                         }
                     }
                     break;
@@ -1353,8 +1471,8 @@ public class ManifestParser
         }
 
         // Parse the directives/attributes.
-        Map<String, String> dirs = new HashMap<String, String>();
-        Map<String, Object> attrs = new HashMap<String, Object>();
+        Map<String, Directive> dirsMap = new HashMap();
+        Map<String, Attribute> attrsMap = new HashMap();
         int idx = -1;
         String sep = null;
         for (int pieceIdx = pathCount; pieceIdx < pieces.size(); pieceIdx++)
@@ -1388,25 +1506,36 @@ public class ManifestParser
             if (sep.equals(FelixConstants.DIRECTIVE_SEPARATOR))
             {
                 // Check for duplicates.
-                if (dirs.get(key) != null)
+                if (dirsMap.get(key) != null)
                 {
                     throw new IllegalArgumentException(
                         "Duplicate directive: " + key);
                 }
-                dirs.put(key, value);
+                dirsMap.put(key, new Directive(key, value));
             }
             else
             {
                 // Check for duplicates.
-                if (attrs.get(key) != null)
+                if (attrsMap.get(key) != null)
                 {
                     throw new IllegalArgumentException(
                         "Duplicate attribute: " + key);
                 }
-                attrs.put(key, value);
+                attrsMap.put(key, new Attribute(key, value, false));
             }
         }
 
+        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());
+        }
+
         return new ParsedHeaderClause(paths, dirs, attrs);
     }
 
@@ -1504,4 +1633,4 @@ public class ManifestParser
 
         return libList;
     }
-}
\ No newline at end of file
+}

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ParsedHeaderClause.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ParsedHeaderClause.java?rev=1103918&r1=1103917&r2=1103918&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ParsedHeaderClause.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ParsedHeaderClause.java Mon May 16 21:49:02 2011
@@ -19,16 +19,16 @@
 package org.apache.felix.framework.util.manifestparser;
 
 import java.util.List;
-import java.util.Map;
+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 Map<String, String> m_dirs;
-    public final Map<String, Object> m_attrs;
+    public final List<Directive> m_dirs;
+    public final List<Attribute> m_attrs;
 
-    public ParsedHeaderClause(
-        List<String> paths, Map<String, String> dirs, Map<String, Object> attrs)
+    public ParsedHeaderClause(List<String> paths, List<Directive> dirs, List<Attribute> attrs)
     {
         m_paths = paths;
         m_dirs = dirs;



Mime
View raw message