felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rickh...@apache.org
Subject svn commit: r958004 [2/2] - in /felix/sandbox/rickhall/vb: composite/src/main/java/org/apache/felix/sandbox/composite/ composite/src/main/java/org/apache/felix/sandbox/composite/activator/ composite/src/main/java/org/apache/felix/sandbox/composite/mp/ ...
Date Fri, 25 Jun 2010 15:16:50 GMT
Added: felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/ManifestParser.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/ManifestParser.java?rev=958004&view=auto
==============================================================================
--- felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/ManifestParser.java (added)
+++ felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/ManifestParser.java Fri Jun 25 15:16:48 2010
@@ -0,0 +1,917 @@
+/*
+ * 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.sandbox.composite.mp;
+
+import java.util.*;
+import java.util.ArrayList;
+import java.util.Map.Entry;
+
+import org.osgi.framework.*;
+
+public class ManifestParser
+{
+    private static List<ParsedHeaderClause> normalizeImportClauses(
+        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());
+        }
+
+        // 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 = 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
+                        {
+                            System.out.println(
+                                "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 Requirement(
+                        Capability.PACKAGE_NAMESPACE,
+                        clauses.get(clauseIdx).m_dirs,
+                        newAttrs));
+            }
+        }
+
+        return reqList;
+    }
+
+    private static List<ParsedHeaderClause> normalizeDynamicImportClauses(
+        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(
+        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
+                        {
+                            System.out.println(
+                                "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;
+    }
+
+    private static String getManifestVersion(Map headerMap)
+    {
+        String manifestVersion = (String) headerMap.get(Constants.BUNDLE_MANIFESTVERSION);
+        return (manifestVersion == null) ? null : manifestVersion.trim();
+    }
+
+    private static Capability parseBundleSymbolicName(Map headerMap)
+        throws BundleException
+    {
+        List<ParsedHeaderClause> clauses = parseStandardHeader(
+            (String) headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
+        if (clauses.size() > 0)
+        {
+            if (clauses.size() > 1)
+            {
+                throw new BundleException(
+                    "Cannot have multiple symbolic names: "
+                        + headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
+            }
+            else if (clauses.get(0).m_paths.size() > 1)
+            {
+                throw new BundleException(
+                    "Cannot have multiple symbolic names: "
+                        + headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
+            }
+
+            // Get bundle version.
+            Version bundleVersion = Version.emptyVersion;
+            if (headerMap.get(Constants.BUNDLE_VERSION) != null)
+            {
+                try
+                {
+                    bundleVersion = Version.parseVersion(
+                        (String) headerMap.get(Constants.BUNDLE_VERSION));
+                }
+                catch (RuntimeException ex)
+                {
+                    // R4 bundle versions must parse, R3 bundle version may not.
+                    String mv = getManifestVersion(headerMap);
+                    if (mv != null)
+                    {
+                        throw ex;
+                    }
+                    bundleVersion = Version.emptyVersion;
+                }
+            }
+
+            // Create a module capability and return it.
+            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 Capability(
+                Capability.MODULE_NAMESPACE,
+                clauses.get(0).m_dirs,
+                attrs);
+        }
+
+        return null;
+    }
+
+    private static List<Requirement> parseFragmentHost(Map headerMap)
+        throws BundleException
+    {
+        List<Requirement> reqs = new ArrayList();
+
+        String mv = getManifestVersion(headerMap);
+        if ((mv != null) && mv.equals("2"))
+        {
+            List<ParsedHeaderClause> clauses = parseStandardHeader(
+                (String) headerMap.get(Constants.FRAGMENT_HOST));
+            if (clauses.size() > 0)
+            {
+                // Make sure that only one fragment host symbolic name is specified.
+                if (clauses.size() > 1)
+                {
+                    throw new BundleException(
+                        "Fragments cannot have multiple hosts: "
+                            + headerMap.get(Constants.FRAGMENT_HOST));
+                }
+                else if (clauses.get(0).m_paths.size() > 1)
+                {
+                    throw new BundleException(
+                        "Fragments cannot have multiple hosts: "
+                            + headerMap.get(Constants.FRAGMENT_HOST));
+                }
+
+                // If the bundle version matching attribute is specified, then
+                // convert it to the proper type.
+                for (int attrIdx = 0;
+                    attrIdx < clauses.get(0).m_attrs.size();
+                    attrIdx++)
+                {
+                    Attribute attr = clauses.get(0).m_attrs.get(attrIdx);
+                    if (attr.getName().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
+                    {
+                        clauses.get(0).m_attrs.set(attrIdx,
+                            new Attribute(
+                                Constants.BUNDLE_VERSION_ATTRIBUTE,
+                                VersionRange.parse(attr.getValue().toString()),
+                                attr.isMandatory()));
+                    }
+                }
+
+                // Prepend the host symbolic name to the array of attributes.
+                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), false));
+                newAttrs.addAll(attrs);
+
+                reqs.add(new Requirement(
+                    Capability.HOST_NAMESPACE,
+                    clauses.get(0).m_dirs,
+                    newAttrs));
+            }
+        }
+        else if (headerMap.get(Constants.FRAGMENT_HOST) != null)
+        {
+            String s = (String) headerMap.get(Constants.BUNDLE_SYMBOLICNAME);
+            s = (s == null) ? (String) headerMap.get(Constants.BUNDLE_NAME) : s;
+            s = (s == null) ? headerMap.toString() : s;
+            System.out.println("Only R4 bundles can be fragments: " + s);
+        }
+
+        return reqs;
+    }
+
+    public static List<Capability> parseExportHeader(
+        String header, String bsn, Version bv)
+    {
+
+        List<Capability> caps = null;
+        try
+        {
+            List<ParsedHeaderClause> exportClauses = parseStandardHeader(header);
+            exportClauses = normalizeExportClauses(exportClauses, "2", bsn, bv);
+            caps = convertExports(exportClauses);
+        }
+        catch (BundleException ex)
+        {
+            caps = null;
+        }
+        return caps;
+    }
+
+    private static List<Capability> convertExports(
+        List<ParsedHeaderClause> clauses)
+    {
+        List<Capability> capList = 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 capability and add to capability list.
+                capList.add(
+                    new Capability(
+                        Capability.PACKAGE_NAMESPACE,
+                        clauses.get(clauseIdx).m_dirs,
+                        newAttrs));
+            }
+        }
+
+        return capList;
+    }
+
+    private static List<ParsedHeaderClause> normalizeRequireClauses(
+        List<ParsedHeaderClause> clauses, String mv)
+    {
+        // R3 bundles cannot require other bundles.
+        if (!mv.equals("2"))
+        {
+            clauses.clear();
+        }
+        else
+        {
+            // Convert bundle version attribute to VersionRange type.
+            for (int clauseIdx = 0; clauseIdx < clauses.size(); clauseIdx++)
+            {
+                for (int attrIdx = 0;
+                    attrIdx < clauses.get(clauseIdx).m_attrs.size();
+                    attrIdx++)
+                {
+                    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()));
+                    }
+                }
+            }
+        }
+
+        return clauses;
+    }
+
+    private static List<Requirement> convertRequires(
+        List<ParsedHeaderClause> clauses)
+    {
+        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 symbolic name to the array of attributes.
+                List<Attribute> newAttrs = new ArrayList<Attribute>(attrs.size() + 1);
+                newAttrs.add(new Attribute(
+                    Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE,
+                    clauses.get(clauseIdx).m_paths.get(pathIdx), false));
+                newAttrs.addAll(attrs);
+
+                // Create package requirement and add to requirement list.
+                reqList.add(
+                    new Requirement(
+                        Capability.MODULE_NAMESPACE,
+                        clauses.get(clauseIdx).m_dirs,
+                        newAttrs));
+            }
+        }
+
+        return reqList;
+    }
+
+    public static final int CLAUSE_PATHS_INDEX = 0;
+    public static final int CLAUSE_DIRECTIVES_INDEX = 1;
+    public static final int CLAUSE_ATTRIBUTES_INDEX = 2;
+
+    // Like this: path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2,
+    //            path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
+    public static List<ParsedHeaderClause> parseStandardHeader(String header)
+    {
+        List<ParsedHeaderClause> clauses = new ArrayList();
+
+        if (header != null)
+        {
+            if (header.length() == 0)
+            {
+                throw new IllegalArgumentException(
+                    "A header cannot be an empty string.");
+            }
+
+            List<String> clauseStrings = parseDelimitedString(
+                header, ",");
+
+            for (int i = 0; (clauseStrings != null) && (i < clauseStrings.size()); i++)
+            {
+                clauses.add(parseStandardHeaderClause(clauseStrings.get(i)));
+            }
+        }
+
+        return clauses;
+    }
+
+    // Like this: path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
+    private static ParsedHeaderClause parseStandardHeaderClause(String clauseString)
+        throws IllegalArgumentException
+    {
+        // Break string into semi-colon delimited pieces.
+        List<String> pieces = parseDelimitedString(
+            clauseString, ";");
+
+        // Count the number of different paths; paths
+        // will not have an '=' in their string. This assumes
+        // that paths come first, before directives and
+        // attributes.
+        int pathCount = 0;
+        for (int pieceIdx = 0; pieceIdx < pieces.size(); pieceIdx++)
+        {
+            if (pieces.get(pieceIdx).indexOf('=') >= 0)
+            {
+                break;
+            }
+            pathCount++;
+        }
+
+        // Error if no paths were specified.
+        if (pathCount == 0)
+        {
+            throw new IllegalArgumentException(
+                "No paths specified in header: " + clauseString);
+        }
+
+        // Create an array of paths.
+        List<String> paths = new ArrayList<String>(pathCount);
+        for (int pathIdx = 0; pathIdx < pathCount; pathIdx++)
+        {
+            paths.add(pieces.get(pathIdx));
+        }
+
+        // Parse the directives/attributes.
+        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++)
+        {
+            // Check if it is a directive.
+            if ((idx = pieces.get(pieceIdx).indexOf(":=")) >= 0)
+            {
+                sep = ":=";
+            }
+            // Check if it is an attribute.
+            else if ((idx = pieces.get(pieceIdx).indexOf("=")) >= 0)
+            {
+                sep = "=";
+            }
+            // It is an error.
+            else
+            {
+                throw new IllegalArgumentException("Not a directive/attribute: " + clauseString);
+            }
+
+            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("\""))
+            {
+                value = value.substring(1, value.length() - 1);
+            }
+
+            // Save the directive/attribute in the appropriate array.
+            if (sep.equals(":="))
+            {
+                // Check for duplicates.
+                if (dirsMap.get(key) != null)
+                {
+                    throw new IllegalArgumentException(
+                        "Duplicate directive: " + key);
+                }
+                dirsMap.put(key, new Directive(key, value));
+            }
+            else
+            {
+                // Check for duplicates.
+                if (attrsMap.get(key) != null)
+                {
+                    throw new IllegalArgumentException(
+                        "Duplicate attribute: " + key);
+                }
+                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);
+    }
+
+    /**
+     * Parses delimited string and returns an array containing the tokens. This
+     * parser obeys quotes, so the delimiter character will be ignored if it is
+     * inside of a quote. This method assumes that the quote character is not
+     * included in the set of delimiter characters.
+     * @param value the delimited string to parse.
+     * @param delim the characters delimiting the tokens.
+     * @return an array of string tokens or null if there were no tokens.
+    **/
+    public static List<String> parseDelimitedString(String value, String delim)
+    {
+        if (value == null)
+        {
+           value = "";
+        }
+
+        List<String> list = new ArrayList();
+
+        int CHAR = 1;
+        int DELIMITER = 2;
+        int STARTQUOTE = 4;
+        int ENDQUOTE = 8;
+
+        StringBuffer sb = new StringBuffer();
+
+        int expecting = (CHAR | DELIMITER | STARTQUOTE);
+
+        for (int i = 0; i < value.length(); i++)
+        {
+            char c = value.charAt(i);
+
+            boolean isDelimiter = (delim.indexOf(c) >= 0);
+            boolean isQuote = (c == '"');
+
+            if (isDelimiter && ((expecting & DELIMITER) > 0))
+            {
+                list.add(sb.toString().trim());
+                sb.delete(0, sb.length());
+                expecting = (CHAR | DELIMITER | STARTQUOTE);
+            }
+            else if (isQuote && ((expecting & STARTQUOTE) > 0))
+            {
+                sb.append(c);
+                expecting = CHAR | ENDQUOTE;
+            }
+            else if (isQuote && ((expecting & ENDQUOTE) > 0))
+            {
+                sb.append(c);
+                expecting = (CHAR | STARTQUOTE | DELIMITER);
+            }
+            else if ((expecting & CHAR) > 0)
+            {
+                sb.append(c);
+            }
+            else
+            {
+                throw new IllegalArgumentException("Invalid delimited string: " + value);
+            }
+        }
+
+        if (sb.length() > 0)
+        {
+            list.add(sb.toString().trim());
+        }
+
+        return list;
+    }
+}

Copied: felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/ParsedHeaderClause.java (from r956641, felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/Install.java)
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/ParsedHeaderClause.java?p2=felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/ParsedHeaderClause.java&p1=felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/Install.java&r1=956641&r2=958004&rev=958004&view=diff
==============================================================================
--- felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/Install.java (original)
+++ felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/ParsedHeaderClause.java Fri Jun 25 15:16:48 2010
@@ -6,9 +6,9 @@
  * 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
@@ -16,27 +16,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.sandbox.composite;
+package org.apache.felix.sandbox.composite.mp;
 
-import org.apache.felix.service.command.Descriptor;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
+import java.util.List;
 
-public class Install
+public class ParsedHeaderClause
 {
-    private final Manager m_manager;
+    public final List<String> m_paths;
+    public final List<Directive> m_dirs;
+    public final List<Attribute> m_attrs;
 
-    public Install(Manager manager)
+    public ParsedHeaderClause(List<String> paths, List<Directive> dirs, List<Attribute> attrs)
     {
-        m_manager = manager;
-    }
-
-    @Descriptor("Install a composite bundle")
-    public Bundle ci(
-        @Descriptor("URL to a composite description")
-        String url)
-        throws BundleException
-    {
-        return m_manager.install(url);
+        m_paths = paths;
+        m_dirs = dirs;
+        m_attrs = attrs;
     }
 }
\ No newline at end of file

Added: felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/Requirement.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/Requirement.java?rev=958004&view=auto
==============================================================================
--- felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/Requirement.java (added)
+++ felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/Requirement.java Fri Jun 25 15:16:48 2010
@@ -0,0 +1,82 @@
+/*
+ * 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.sandbox.composite.mp;
+
+import java.util.Collections;
+import java.util.List;
+import org.osgi.framework.Constants;
+
+public class Requirement
+{
+    private final String m_namespace;
+    private final boolean m_optional;
+    private final List<Directive> m_dirs;
+    private final List<Directive> m_dirsConst;
+
+    public Requirement(
+        String namespace, List<Directive> dirs, List<Attribute> attrs)
+    {
+        m_namespace = namespace;
+        m_dirs = dirs;
+        m_dirsConst = Collections.unmodifiableList(m_dirs);
+
+        // 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 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;
+    }
+}
\ No newline at end of file

Added: felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/VersionRange.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/VersionRange.java?rev=958004&view=auto
==============================================================================
--- felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/VersionRange.java (added)
+++ felix/sandbox/rickhall/vb/composite/src/main/java/org/apache/felix/sandbox/composite/mp/VersionRange.java Fri Jun 25 15:16:48 2010
@@ -0,0 +1,159 @@
+/* 
+ * 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.sandbox.composite.mp;
+
+import org.osgi.framework.Version;
+
+public class VersionRange
+{
+    private final Version m_floor;
+    private final boolean m_isFloorInclusive;
+    private final Version m_ceiling;
+    private final boolean m_isCeilingInclusive;
+    public static final VersionRange infiniteRange
+        = new VersionRange(Version.emptyVersion, true, null, true);
+
+    public VersionRange(
+        Version low, boolean isLowInclusive,
+        Version high, boolean isHighInclusive)
+    {
+        m_floor = low;
+        m_isFloorInclusive = isLowInclusive;
+        m_ceiling = high;
+        m_isCeilingInclusive = isHighInclusive;
+    }
+
+    public Version getFloor()
+    {
+        return m_floor;
+    }
+
+    public boolean isFloorInclusive()
+    {
+        return m_isFloorInclusive;
+    }
+
+    public Version getCeiling()
+    {
+        return m_ceiling;
+    }
+
+    public boolean isCeilingInclusive()
+    {
+        return m_isCeilingInclusive;
+    }
+
+    public boolean isInRange(Version version)
+    {
+        // We might not have an upper end to the range.
+        if (m_ceiling == null)
+        {
+            return (version.compareTo(m_floor) >= 0);
+        }
+        else if (isFloorInclusive() && isCeilingInclusive())
+        {
+            return (version.compareTo(m_floor) >= 0) && (version.compareTo(m_ceiling) <= 0);
+        }
+        else if (isCeilingInclusive())
+        {
+            return (version.compareTo(m_floor) > 0) && (version.compareTo(m_ceiling) <= 0);
+        }
+        else if (isFloorInclusive())
+        {
+            return (version.compareTo(m_floor) >= 0) && (version.compareTo(m_ceiling) < 0);
+        }
+        return (version.compareTo(m_floor) > 0) && (version.compareTo(m_ceiling) < 0);
+    }
+
+    public static VersionRange parse(String range)
+    {
+        // Check if the version is an interval.
+        if (range.indexOf(',') >= 0)
+        {
+            String s = range.substring(1, range.length() - 1);
+            String vlo = s.substring(0, s.indexOf(',')).trim();
+            String vhi = s.substring(s.indexOf(',') + 1, s.length()).trim();
+            return new VersionRange (
+                new Version(vlo), (range.charAt(0) == '['),
+                new Version(vhi), (range.charAt(range.length() - 1) == ']'));
+        }
+        else
+        {
+            return new VersionRange(new Version(range), true, null, false);
+        }
+    }
+
+    public boolean equals(Object obj)
+    {
+        if (obj == null)
+        {
+            return false;
+        }
+        if (getClass() != obj.getClass())
+        {
+            return false;
+        }
+        final VersionRange other = (VersionRange) obj;
+        if (m_floor != other.m_floor && (m_floor == null || !m_floor.equals(other.m_floor)))
+        {
+            return false;
+        }
+        if (m_isFloorInclusive != other.m_isFloorInclusive)
+        {
+            return false;
+        }
+        if (m_ceiling != other.m_ceiling && (m_ceiling == null || !m_ceiling.equals(other.m_ceiling)))
+        {
+            return false;
+        }
+        if (m_isCeilingInclusive != other.m_isCeilingInclusive)
+        {
+            return false;
+        }
+        return true;
+    }
+
+    public int hashCode()
+    {
+        int hash = 5;
+        hash = 97 * hash + (m_floor != null ? m_floor.hashCode() : 0);
+        hash = 97 * hash + (m_isFloorInclusive ? 1 : 0);
+        hash = 97 * hash + (m_ceiling != null ? m_ceiling.hashCode() : 0);
+        hash = 97 * hash + (m_isCeilingInclusive ? 1 : 0);
+        return hash;
+    }
+
+    public String toString()
+    {
+        if (m_ceiling != null)
+        {
+            StringBuffer sb = new StringBuffer();
+            sb.append(m_isFloorInclusive ? '[' : '(');
+            sb.append(m_floor.toString());
+            sb.append(',');
+            sb.append(m_ceiling.toString());
+            sb.append(m_isCeilingInclusive ? ']' : ')');
+            return sb.toString();
+        }
+        else
+        {
+            return m_floor.toString();
+        }
+    }
+}
\ No newline at end of file

Modified: felix/sandbox/rickhall/vb/framework-vb/src/main/java/org/apache/felix/framework/capabilityset/Capability.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/vb/framework-vb/src/main/java/org/apache/felix/framework/capabilityset/Capability.java?rev=958004&r1=958003&r2=958004&view=diff
==============================================================================
--- felix/sandbox/rickhall/vb/framework-vb/src/main/java/org/apache/felix/framework/capabilityset/Capability.java (original)
+++ felix/sandbox/rickhall/vb/framework-vb/src/main/java/org/apache/felix/framework/capabilityset/Capability.java Fri Jun 25 15:16:48 2010
@@ -27,8 +27,8 @@ public interface Capability
     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";
+    static final String PACKAGE_ATTR = "package";
+    static final String VERSION_ATTR = "version";
 
     Module getModule();
     String getNamespace();

Modified: felix/sandbox/rickhall/vb/main-vb/src/main/resources/config.properties
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/vb/main-vb/src/main/resources/config.properties?rev=958004&r1=958003&r2=958004&view=diff
==============================================================================
--- felix/sandbox/rickhall/vb/main-vb/src/main/resources/config.properties (original)
+++ felix/sandbox/rickhall/vb/main-vb/src/main/resources/config.properties Fri Jun 25 15:16:48 2010
@@ -25,7 +25,7 @@
 
 # To append packages to the default set of exported system packages,
 # set this value.
-#org.osgi.framework.system.packages.extra=
+org.osgi.framework.system.packages.extra=org.apache.felix.framework
 
 # The following property makes specified packages from the class path
 # available to all bundles. You should avoid using this property.



Mime
View raw message