/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.felix.framework.util.manifestparser;

import org.apache.felix.framework.BundleRevisionImpl;
import org.apache.felix.framework.Logger;
import org.apache.felix.framework.capabilityset.SimpleFilter;
import org.apache.felix.framework.util.FelixConstants;
import org.apache.felix.framework.wiring.BundleCapabilityImpl;
import org.apache.felix.framework.wiring.BundleRequirementImpl;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.osgi.framework.VersionRange;
import org.osgi.framework.namespace.BundleNamespace;
import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.namespace.NativeNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class ManifestParser
{
    private static final String BUNDLE_LICENSE_HEADER = "Bundle-License"; // No constant defined by OSGi...

    private final Logger m_logger;
    private final Map<String, Object> m_configMap;
    private final Map<String, Object> m_headerMap;
    private volatile int m_activationPolicy = BundleRevisionImpl.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<NativeLibraryClause> m_libraryClauses;
    private volatile boolean m_libraryHeadersOptional = false;

    public ManifestParser(Logger logger, Map<String, Object> configMap, BundleRevision owner, Map<String, Object> headerMap)
        throws BundleException
    {
        m_logger = logger;
        m_configMap = configMap;
        m_headerMap = headerMap;

        // Verify that only manifest version 2 is specified.
        String manifestVersion = getManifestVersion(m_headerMap);
        if ((manifestVersion != null) && !manifestVersion.equals("2"))
        {
            throw new BundleException(
                "Unknown 'Bundle-ManifestVersion' value: " + manifestVersion);
        }

        // Create lists to hold capabilities and requirements.
        List<BundleCapabilityImpl> capList = new ArrayList<BundleCapabilityImpl>();

        //
        // Parse bundle version.
        //

        m_bundleVersion = Version.emptyVersion;
        if (headerMap.get(Constants.BUNDLE_VERSION) != null)
        {
            try
            {
                m_bundleVersion = Version.parseVersion(
                    (String) headerMap.get(Constants.BUNDLE_VERSION));
            }
            catch (RuntimeException ex)
            {
                // R4 bundle versions must parse, R3 bundle version may not.
                if (getManifestVersion().equals("2"))
                {
                    throw ex;
                }
                m_bundleVersion = Version.emptyVersion;
            }
        }

        //
        // Parse bundle symbolic name.
        //

        BundleCapabilityImpl bundleCap = parseBundleSymbolicName(owner, m_headerMap);
        if (bundleCap != null)
        {
            m_bundleSymbolicName = (String)
                bundleCap.getAttributes().get(BundleRevision.BUNDLE_NAMESPACE);

            // Add a bundle 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
            // dependencies, while host capabilities resolve fragment-host
            // dependencies.
            if (headerMap.get(Constants.FRAGMENT_HOST) == null)
            {
                // All non-fragment bundles have host capabilities.
                capList.add(bundleCap);
                // A non-fragment bundle can choose to not have a host capability.
                String attachment =
                    bundleCap.getDirectives().get(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE);
                attachment = (attachment == null)
                    ? Constants.FRAGMENT_ATTACHMENT_RESOLVETIME
                    : attachment;
                if (!attachment.equalsIgnoreCase(Constants.FRAGMENT_ATTACHMENT_NEVER))
                {
                    Map<String, Object> hostAttrs =
                        new HashMap<String, Object>(bundleCap.getAttributes());
                    Object value = hostAttrs.remove(BundleRevision.BUNDLE_NAMESPACE);
                    hostAttrs.put(BundleRevision.HOST_NAMESPACE, value);
                    capList.add(new BundleCapabilityImpl(
                        owner, BundleRevision.HOST_NAMESPACE,
                        bundleCap.getDirectives(),
                        hostAttrs));
                }
            }

            //
            // Add the osgi.identity capability.
            //
            capList.add(addIdentityCapability(owner, headerMap, bundleCap));
        }

        // Verify that bundle symbolic name is specified.
        if (getManifestVersion().equals("2") && (m_bundleSymbolicName == null))
        {
            throw new BundleException(
                "R4 bundle manifests must include bundle symbolic name.");
        }

        m_isExtension = checkExtensionBundle(headerMap);

        //
        // Parse Fragment-Host.
        //

        List<BundleRequirementImpl> hostReqs = parseFragmentHost(m_logger, owner, m_headerMap);

        //
        // Parse Require-Bundle
        //

        List<ParsedHeaderClause> rbClauses =
            parseStandardHeader((String) headerMap.get(Constants.REQUIRE_BUNDLE));
        rbClauses = normalizeRequireClauses(m_logger, rbClauses, getManifestVersion());
        List<BundleRequirementImpl> rbReqs = convertRequires(rbClauses, owner);

        //
        // Parse Import-Package.
        //

        List<ParsedHeaderClause> importClauses =
            parseStandardHeader((String) headerMap.get(Constants.IMPORT_PACKAGE));
        importClauses = normalizeImportClauses(m_logger, importClauses, getManifestVersion());
        List<BundleRequirement> importReqs = convertImports(importClauses, owner);

        //
        // Parse DynamicImport-Package.
        //

        List<ParsedHeaderClause> dynamicClauses =
            parseStandardHeader((String) headerMap.get(Constants.DYNAMICIMPORT_PACKAGE));
        dynamicClauses = normalizeDynamicImportClauses(m_logger, dynamicClauses, getManifestVersion());
        List<BundleRequirement> dynamicReqs = convertImports(dynamicClauses, owner);

        //
        // Parse Require-Capability.
        //

        List<ParsedHeaderClause> requireClauses =
            parseStandardHeader((String) headerMap.get(Constants.REQUIRE_CAPABILITY));
        importClauses = normalizeCapabilityClauses(
            m_logger, requireClauses, getManifestVersion());
        List<BundleRequirement> requireReqs = convertRequireCapabilities(importClauses, owner);

        //
        // Parse Bundle-RequiredExecutionEnvironment.
        //
        List<BundleRequirement> breeReqs =
            parseBreeHeader((String) headerMap.get(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT), owner);

        //
        // Parse Export-Package.
        //

        List<ParsedHeaderClause> exportClauses =
            parseStandardHeader((String) headerMap.get(Constants.EXPORT_PACKAGE));
        exportClauses = normalizeExportClauses(logger, exportClauses,
            getManifestVersion(), m_bundleSymbolicName, m_bundleVersion);
        List<BundleCapability> exportCaps = convertExports(exportClauses, owner);

        //
        // Parse Provide-Capability.
        //

        List<ParsedHeaderClause> provideClauses =
            parseStandardHeader((String) headerMap.get(Constants.PROVIDE_CAPABILITY));
        provideClauses = normalizeCapabilityClauses(
            logger, provideClauses, getManifestVersion());
        List<BundleCapability> provideCaps = convertProvideCapabilities(provideClauses, owner);

        //
        // Calculate implicit imports.
        //

        if (!getManifestVersion().equals("2"))
        {
            List<ParsedHeaderClause> implicitClauses =
                calculateImplicitImports(exportCaps, importClauses);
            importReqs.addAll(convertImports(implicitClauses, owner));

            List<ParsedHeaderClause> allImportClauses =
                new ArrayList<ParsedHeaderClause>(implicitClauses.size() + importClauses.size());
            allImportClauses.addAll(importClauses);
            allImportClauses.addAll(implicitClauses);

            exportCaps = calculateImplicitUses(exportCaps, allImportClauses);
        }

        //
        // Parse Bundle-NativeCode.
        //

        // Parse native library clauses.
        m_libraryClauses =
            parseLibraryStrings(
                m_logger,
                parseDelimitedString((String) m_headerMap.get(Constants.BUNDLE_NATIVECODE), ","));

        // Check to see if there was an optional native library clause, which is
        // represented by a null library header; if so, record it and remove it.
        if (!m_libraryClauses.isEmpty() &&
            (m_libraryClauses.get(m_libraryClauses.size() - 1).getLibraryEntries() == null))
        {
            m_libraryHeadersOptional = true;
            m_libraryClauses.remove(m_libraryClauses.size() - 1);
        }
        
        List<BundleRequirement> nativeCodeReqs = convertNativeCode(owner, m_libraryClauses, m_libraryHeadersOptional);
        
        // Combine all requirements.
        m_requirements = new ArrayList<BundleRequirement>(
            hostReqs.size() + importReqs.size() + rbReqs.size()
            + requireReqs.size() + dynamicReqs.size() + breeReqs.size());
        m_requirements.addAll(hostReqs);
        m_requirements.addAll(importReqs);
        m_requirements.addAll(rbReqs);
        m_requirements.addAll(requireReqs);
        m_requirements.addAll(dynamicReqs);
        m_requirements.addAll(breeReqs);
        m_requirements.addAll(nativeCodeReqs);
        
        // Combine all capabilities.
        m_capabilities = new ArrayList<BundleCapability>(
             capList.size() + exportCaps.size() + provideCaps.size());
        m_capabilities.addAll(capList);
        m_capabilities.addAll(exportCaps);
        m_capabilities.addAll(provideCaps);

        //
        // Parse activation policy.
        //

        // This sets m_activationPolicy, m_includedPolicyClasses, and
        // m_excludedPolicyClasses.
        parseActivationPolicy(headerMap);
    }

    private static List<ParsedHeaderClause> normalizeImportClauses(
        Logger logger, List<ParsedHeaderClause> clauses, String mv)
        throws BundleException
    {
        // Verify that the values are equals if the package specifies
        // both version and specification-version attributes.
        Set<String> dupeSet = new HashSet<String>();
        for (ParsedHeaderClause clause : clauses)
        {
            // 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);
            if ((v != null) && (sv != null))
            {
                // Verify they are equal.
                if (!((String) v).trim().equals(((String) sv).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))
            {
                clause.m_attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
                v = (v == null) ? sv : v;
                clause.m_attrs.put(
                    Constants.VERSION_ATTRIBUTE,
                    new VersionRange(v.toString()));
            }

            // If bundle version is specified, then convert its type to VersionRange.
            v = clause.m_attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
            if (v != null)
            {
                clause.m_attrs.put(
                    Constants.BUNDLE_VERSION_ATTRIBUTE,
                    new VersionRange(v.toString()));
            }

            // Verify no duplicate imports.
            for (String pkgName : clause.m_paths)
            {
                if (!dupeSet.contains(pkgName))
                {

                    // The character "." has no meaning in the OSGi spec except
                    // when placed on the bundle class path. Some people, however,
                    // mistakenly think it means the default package when imported
                    // or exported. This is not correct. It is invalid.
                    if (pkgName.equals("."))
                    {
                        throw new BundleException("Imporing '.' is invalid.");
                    }
                    // Make sure a package name was specified.
                    else if (pkgName.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"))
            {
                // R3 bundles cannot have directives on their imports.
                if (!clause.m_dirs.isEmpty())
                {
                    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 (!clause.m_attrs.isEmpty())
                {
                    // R3 package requirements should only have version attributes.
                    Object pkgVersion = clause.m_attrs.get(BundleCapabilityImpl.VERSION_ATTR);
                    pkgVersion = (pkgVersion == null)
                        ? new VersionRange(VersionRange.LEFT_CLOSED, Version.emptyVersion, null, VersionRange.RIGHT_CLOSED)
                        : pkgVersion;
                    for (Entry<String, Object> entry : clause.m_attrs.entrySet())
                    {
                        if (!entry.getKey().equals(BundleCapabilityImpl.VERSION_ATTR))
                        {
                            logger.log(Logger.LOG_WARNING,
                                "Unknown R3 import attribute: "
                                    + entry.getKey());
                        }
                    }

                    // Remove all other attributes except package version.
                    clause.m_attrs.clear();
                    clause.m_attrs.put(BundleCapabilityImpl.VERSION_ATTR, pkgVersion);
                }
            }
        }

        return clauses;
    }

    public static List<BundleRequirement> parseDynamicImportHeader(
        Logger logger, BundleRevision owner, String header)
        throws BundleException
    {

        List<ParsedHeaderClause> importClauses = parseStandardHeader(header);
        importClauses = normalizeDynamicImportClauses(logger, importClauses, "2");
        List<BundleRequirement> reqs = convertImports(importClauses, owner);
        return reqs;
    }

    private static List<BundleRequirement> convertImports(
        List<ParsedHeaderClause> clauses, BundleRevision owner)
    {
        // Now convert generic header clauses into requirements.
        List<BundleRequirement> reqList = new ArrayList<BundleRequirement>();
        for (ParsedHeaderClause clause : clauses)
        {
            for (String path : clause.m_paths)
            {
                // Prepend the package name to the array of attributes.
                Map<String, Object> attrs = clause.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 ordering is kind of hacky.
                // Prepend the package name to the array of attributes.
                Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
                // We want this first from an indexing perspective.
                newAttrs.put(
                    BundleRevision.PACKAGE_NAMESPACE,
                    path);
                newAttrs.putAll(attrs);
                // But we need to put it again to make sure it wasn't overwritten.
                newAttrs.put(
                    BundleRevision.PACKAGE_NAMESPACE,
                    path);

                // Create filter now so we can inject filter directive.
                SimpleFilter sf = SimpleFilter.convert(newAttrs);

                // Inject filter directive.
// TODO: OSGi R4.3 - Can we insert this on demand somehow?
                Map<String, String> dirs = clause.m_dirs;
                Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
                newDirs.putAll(dirs);
                newDirs.put(
                    Constants.FILTER_DIRECTIVE,
                    sf.toString());

                // Create package requirement and add to requirement list.
                reqList.add(
                    new BundleRequirementImpl(
                        owner,
                        BundleRevision.PACKAGE_NAMESPACE,
                        newDirs,
                        Collections.EMPTY_MAP,
                        sf));
            }
        }

        return reqList;
    }

    private static List<ParsedHeaderClause> normalizeDynamicImportClauses(
        Logger logger, List<ParsedHeaderClause> clauses, String mv)
        throws BundleException
    {
        // Verify that the values are equals if the package specifies
        // both version and specification-version attributes.
        for (ParsedHeaderClause clause : clauses)
        {
            if (!mv.equals("2"))
            {
                // R3 bundles cannot have directives on their imports.
                if (!clause.m_dirs.isEmpty())
                {
                    throw new BundleException("R3 imports cannot contain directives.");
                }
            }

            // Add the resolution directive to indicate that these are
            // dynamic imports.
            clause.m_dirs.put(Constants.RESOLUTION_DIRECTIVE,
                FelixConstants.RESOLUTION_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);
            if ((v != null) && (sv != null))
            {
                // Verify they are equal.
                if (!((String) v).trim().equals(((String) sv).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))
            {
                clause.m_attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
                v = (v == null) ? sv : v;
                clause.m_attrs.put(
                    Constants.VERSION_ATTRIBUTE,
                    new VersionRange(v.toString()));
            }

            // If bundle version is specified, then convert its type to VersionRange.
            v = clause.m_attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
            if (v != null)
            {
                clause.m_attrs.put(
                    Constants.BUNDLE_VERSION_ATTRIBUTE,
                    new VersionRange(v.toString()));
            }

            // Dynamic imports can have duplicates, verify that no partial package name wild carding is used
            for (String pkgName : clause.m_paths)
            {
                if (!pkgName.equals("*") && pkgName.endsWith("*") && !pkgName.endsWith(".*"))
                {
                    throw new BundleException(
                        "Partial package name wild carding is not allowed: " + pkgName);
                }
            }
        }

        return clauses;
    }

    private static List<BundleRequirement> convertRequireCapabilities(
        List<ParsedHeaderClause> clauses, BundleRevision owner)
        throws BundleException
    {
        // Now convert generic header clauses into requirements.
        List<BundleRequirement> reqList = new ArrayList<BundleRequirement>();
        for (ParsedHeaderClause clause : clauses)
        {
            try
            {
                String filterStr = clause.m_dirs.get(Constants.FILTER_DIRECTIVE);
                SimpleFilter sf = (filterStr != null)
                    ? SimpleFilter.parse(filterStr)
                    : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
                for (String path : clause.m_paths)
                {
                    if (path.startsWith("osgi.wiring."))
                    {
                        throw new BundleException("Manifest cannot use Require-Capability for '"
                            + path
                            + "' namespace.");
                    }

                    // Create requirement and add to requirement list.
                    reqList.add(
                        new BundleRequirementImpl(
                            owner,
                            path,
                            clause.m_dirs,
                            clause.m_attrs,
                            sf));
                }
            }
            catch (Exception ex)
            {
                throw new BundleException("Error creating requirement: " + ex);
            }
        }

        return reqList;
    }
    
    static List<BundleRequirement> convertNativeCode(BundleRevision owner, List<NativeLibraryClause> nativeLibraryClauses, boolean hasOptionalLibraryDirective)
    {
        List<BundleRequirement> result = new ArrayList<BundleRequirement>();
        
        List<SimpleFilter> nativeFilterClauseList = new ArrayList<SimpleFilter>();
        
        if(nativeLibraryClauses != null && !nativeLibraryClauses.isEmpty())
        {
            for(NativeLibraryClause clause: nativeLibraryClauses)
            {
                String[] osNameArray = clause.getOSNames();
                String[] osVersionArray = clause.getOSVersions();
                String[] processorArray = clause.getProcessors();
                String[] languageArray = clause.getLanguages();
                
                String currentSelectionFilter = clause.getSelectionFilter();
                
                List<SimpleFilter> nativeFilterList = new ArrayList<SimpleFilter>();
                if(osNameArray != null && osNameArray.length > 0)
                {
                    nativeFilterList.add(buildFilterFromArray(NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE, osNameArray, SimpleFilter.APPROX));
                }
                
                if(osVersionArray != null && osVersionArray.length > 0)
                {
                    nativeFilterList.add(buildFilterFromArray(NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE, osVersionArray, SimpleFilter.EQ));
                }
                
                if(processorArray != null && processorArray.length > 0)
                {
                    nativeFilterList.add(buildFilterFromArray(NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE, processorArray, SimpleFilter.APPROX));
                }

                if(languageArray != null && languageArray.length > 0)
                {
                    nativeFilterList.add(buildFilterFromArray(NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE, languageArray, SimpleFilter.APPROX));
                }
                
                if(currentSelectionFilter != null)
                {
                    nativeFilterList.add(SimpleFilter.parse(currentSelectionFilter));
                }
                
                if(!nativeFilterList.isEmpty())
                {
                    SimpleFilter nativeClauseFilter = new SimpleFilter(null, nativeFilterList, SimpleFilter.AND);
                    nativeFilterClauseList.add(nativeClauseFilter);
                }
            }
            
            Map<String, String> requirementDirectives = new HashMap<String, String>();
            
            SimpleFilter consolidatedNativeFilter = null;
            
            if(hasOptionalLibraryDirective)
            {
                requirementDirectives.put(NativeNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE, NativeNamespace.RESOLUTION_OPTIONAL);
            }
            
            if(nativeFilterClauseList.size() > 1)
            {
                consolidatedNativeFilter = new SimpleFilter(null, nativeFilterClauseList, SimpleFilter.OR);
                
                requirementDirectives.put(NativeNamespace.REQUIREMENT_FILTER_DIRECTIVE, consolidatedNativeFilter.toString());
            }
            else if(nativeFilterClauseList.size() == 1)
            {
                consolidatedNativeFilter = nativeFilterClauseList.get(0);
                
                requirementDirectives.put(NativeNamespace.REQUIREMENT_FILTER_DIRECTIVE, consolidatedNativeFilter.toString());
            }
            
            if(requirementDirectives.size() > 0)
            {
                result.add(new BundleRequirementImpl(owner, NativeNamespace.NATIVE_NAMESPACE, requirementDirectives,
                        Collections.<String, Object>emptyMap(),
                        consolidatedNativeFilter));
            }
            
        }
        
        return result;
    }
    
    private static SimpleFilter buildFilterFromArray(String attributeName, String[] stringArray, int operation)
    {
        SimpleFilter result = null;
        List<SimpleFilter> filterSet = new ArrayList<SimpleFilter>();
        
        if(stringArray != null)
        {
            for(String currentValue : stringArray)
            {
                filterSet.add(new SimpleFilter(attributeName, currentValue.toLowerCase(), operation));
            }
            
            if(filterSet.size() == 1)
            {
                result = filterSet.get(0);
            }
            else
            {
                result = new SimpleFilter(null, filterSet, SimpleFilter.OR);
            }
        }
        
        return result;
    }
    
    private static List<ParsedHeaderClause> normalizeCapabilityClauses(
        Logger logger, List<ParsedHeaderClause> clauses, String mv)
        throws BundleException
    {

        if (!mv.equals("2") && !clauses.isEmpty())
        {
            // Should we error here if we are not an R4 bundle?
        }

        // Convert attributes into specified types.
        for (ParsedHeaderClause clause : clauses)
        {
            for (Entry<String, String> entry : clause.m_types.entrySet())
            {
                String type = entry.getValue();
                if (!type.equals("String"))
                {
                    if (type.equals("Double"))
                    {
                        clause.m_attrs.put(
                            entry.getKey(),
                            new Double(clause.m_attrs.get(entry.getKey()).toString().trim()));
                    }
                    else if (type.equals("Version"))
                    {
                        clause.m_attrs.put(
                            entry.getKey(),
                            new Version(clause.m_attrs.get(entry.getKey()).toString().trim()));
                    }
                    else if (type.equals("Long"))
                    {
                        clause.m_attrs.put(
                            entry.getKey(),
                            new Long(clause.m_attrs.get(entry.getKey()).toString().trim()));
                    }
                    else if (type.startsWith("List"))
                    {
                        int startIdx = type.indexOf('<');
                        int endIdx = type.indexOf('>');
                        if (((startIdx > 0) && (endIdx <= startIdx))
                            || ((startIdx < 0) && (endIdx > 0)))
                        {
                            throw new BundleException(
                                "Invalid Provide-Capability attribute list type for '"
                                + entry.getKey()
                                + "' : "
                                + type);
                        }

                        String listType = "String";
                        if (endIdx > startIdx)
                        {
                            listType = type.substring(startIdx + 1, endIdx).trim();
                        }

                        List<String> tokens = parseDelimitedString(
                            clause.m_attrs.get(entry.getKey()).toString(), ",", false);
                        List<Object> values = new ArrayList<Object>(tokens.size());
                        for (String token : tokens)
                        {
                            if (listType.equals("String"))
                            {
                                values.add(token);
                            }
                            else if (listType.equals("Double"))
                            {
                                values.add(new Double(token.trim()));
                            }
                            else if (listType.equals("Version"))
                            {
                                values.add(new Version(token.trim()));
                            }
                            else if (listType.equals("Long"))
                            {
                                values.add(new Long(token.trim()));
                            }
                            else
                            {
                                throw new BundleException(
                                    "Unknown Provide-Capability attribute list type for '"
                                    + entry.getKey()
                                    + "' : "
                                    + type);
                            }
                        }
                        clause.m_attrs.put(
                            entry.getKey(),
                            values);
                    }
                    else
                    {
                        throw new BundleException(
                            "Unknown Provide-Capability attribute type for '"
                            + entry.getKey()
                            + "' : "
                            + type);
                    }
                }
            }
        }

        return clauses;
    }

    private static List<BundleCapability> convertProvideCapabilities(
        List<ParsedHeaderClause> clauses, BundleRevision owner)
        throws BundleException
    {
        List<BundleCapability> capList = new ArrayList<BundleCapability>();
        for (ParsedHeaderClause clause : clauses)
        {
            for (String path : clause.m_paths)
            {
                if (path.startsWith("osgi.wiring."))
                {
                    throw new BundleException("Manifest cannot use Provide-Capability for '"
                        + path
                        + "' namespace.");
                }
                
                if((path.startsWith(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE) ||
                    path.startsWith(NativeNamespace.NATIVE_NAMESPACE)) && (owner == null ||
                    !FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(owner.getSymbolicName())))
                {
                    throw new BundleException("Only System Bundle can use Provide-Capability for '"
                            + path
                            + "' namespace.", BundleException.MANIFEST_ERROR);
                }

                // Create package capability and add to capability list.
                capList.add(
                    new BundleCapabilityImpl(
                        owner,
                        path,
                        clause.m_dirs,
                        clause.m_attrs));
            }
        }

        return capList;
    }

    private static List<ParsedHeaderClause> normalizeExportClauses(
        Logger logger, List<ParsedHeaderClause> clauses,
        String mv, String bsn, Version bv)
        throws BundleException
    {
        for (ParsedHeaderClause clause : clauses)
        {
            // Verify that the named package has not already been declared.
            for (String pkgName : clause.m_paths)
            {
                // Verify that java.* packages are not exported (except from the system bundle).
                if (!FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(bsn) && pkgName.startsWith("java."))
                {
                    throw new BundleException(
                        "Exporting java.* packages not allowed: "
                        + pkgName, BundleException.MANIFEST_ERROR);
                }
                // The character "." has no meaning in the OSGi spec except
                // when placed on the bundle class path. Some people, however,
                // mistakenly think it means the default package when imported
                // or exported. This is not correct. It is invalid.
                else if (pkgName.equals("."))
                {
                    throw new BundleException("Exporing '.' is invalid.");
                }
                // Make sure a package name was specified.
                else if (pkgName.length() == 0)
                {
                    throw new BundleException(
                        "Exported package names cannot be zero length.");
                }
            }

            // 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);
            if ((v != null) && (sv != null))
            {
                // Verify they are equal.
                if (!((String) v).trim().equals(((String) sv).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 = Version.emptyVersion;
            }

            // 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.
                clause.m_attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
                v = (v == null) ? sv : v;
                clause.m_attrs.put(
                    Constants.VERSION_ATTRIBUTE,
                    Version.parseVersion(v.toString()));
            }

            // 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.");
                }

                // 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);
            }
            else if (!mv.equals("2"))
            {
                // R3 bundles cannot have directives on their exports.
                if (!clause.m_dirs.isEmpty())
                {
                    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 (!clause.m_attrs.isEmpty())
                {
                    // 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())
                    {
                        if (!entry.getKey().equals(BundleCapabilityImpl.VERSION_ATTR))
                        {
                            logger.log(
                                Logger.LOG_WARNING,
                                "Unknown R3 export attribute: "
                                + entry.getKey());
                        }
                    }

                    // Remove all other attributes except package version.
                    clause.m_attrs.clear();
                    clause.m_attrs.put(BundleCapabilityImpl.VERSION_ATTR, pkgVersion);
                }
            }
        }

        return clauses;
    }

    private static List<BundleCapability> convertExports(
        List<ParsedHeaderClause> clauses, BundleRevision owner)
    {
        List<BundleCapability> capList = new ArrayList<BundleCapability>();
        for (ParsedHeaderClause clause : clauses)
        {
            for (String pkgName : clause.m_paths)
            {
                // Prepend the package name to the array of attributes.
                Map<String, Object> attrs = clause.m_attrs;
                Map<String, Object> newAttrs = new HashMap<String, Object>(attrs.size() + 1);
                newAttrs.putAll(attrs);
                newAttrs.put(
                    BundleRevision.PACKAGE_NAMESPACE,
                    pkgName);

                // Create package capability and add to capability list.
                capList.add(
                    new BundleCapabilityImpl(
                        owner,
                        BundleRevision.PACKAGE_NAMESPACE,
                        clause.m_dirs,
                        newAttrs));
            }
        }

        return capList;
    }

    public String getManifestVersion()
    {
        String manifestVersion = getManifestVersion(m_headerMap);
        return (manifestVersion == null) ? "1" : manifestVersion;
    }

    private static String getManifestVersion(Map<String, Object> headerMap)
    {
        String manifestVersion = (String) headerMap.get(Constants.BUNDLE_MANIFESTVERSION);
        return (manifestVersion == null) ? null : manifestVersion.trim();
    }

    public int getActivationPolicy()
    {
        return m_activationPolicy;
    }

    public String getActivationIncludeDirective()
    {
        return m_activationIncludeDir;
    }

    public String getActivationExcludeDirective()
    {
        return m_activationExcludeDir;
    }

    public boolean isExtension()
    {
        return m_isExtension;
    }

    public String getSymbolicName()
    {
        return m_bundleSymbolicName;
    }

    public Version getBundleVersion()
    {
        return m_bundleVersion;
    }

    public List<BundleCapability> getCapabilities()
    {
        return m_capabilities;
    }

    public List<BundleRequirement> getRequirements()
    {
        return m_requirements;
    }

    /**
     * <p>
     * This method returns the selected native library metadata from
     * the manifest. The information is not the raw metadata from the
     * manifest, but is the native library clause selected according
     * to the OSGi native library clause selection policy. The metadata
     * returned by this method will be attached directly to a module and
     * used for finding its native libraries at run time. To inspect the
     * raw native library metadata refer to <tt>getLibraryClauses()</tt>.
     * </p>
     * <p>
     * This method returns one of three values:
     * </p>
     * <ul>
     * <li><tt>null</tt> - if the are no native libraries for this module;
     *     this may also indicate the native libraries are optional and
     *     did not match the current platform.</li>
     * <li>Zero-length <tt>NativeLibrary</tt> array - if no matching native library
     *     clause was found; this bundle should not resolve.</li>
     * <li>Nonzero-length <tt>NativeLibrary</tt> array - the native libraries
     *     associated with the matching native library clause.</li>
     * </ul>
     *
     * @return <tt>null</tt> if there are no native libraries, a zero-length
     *         array if no libraries matched, or an array of selected libraries.
    **/
    public List<NativeLibrary> getLibraries()
    {
        ArrayList<NativeLibrary> libs = null;
        try
        {
            NativeLibraryClause clause = getSelectedLibraryClause();
            if (clause != null)
            {
                String[] entries = clause.getLibraryEntries();
                libs = new ArrayList<NativeLibrary>(entries.length);
                int current = 0;
                for (int i = 0; i < entries.length; i++)
                {
                    String name = getName(entries[i]);
                    boolean found = false;
                    for (int j = 0; !found && (j < current); j++)
                    {
                        found = getName(entries[j]).equals(name);
                    }
                    if (!found)
                    {
                        libs.add(new NativeLibrary(
                            clause.getLibraryEntries()[i],
                            clause.getOSNames(), clause.getProcessors(), clause.getOSVersions(),
                            clause.getLanguages(), clause.getSelectionFilter()));
                    }
                }
                libs.trimToSize();
            }
        }
        catch (Exception ex)
        {
            libs = new ArrayList<NativeLibrary>(0);
        }
        return libs;
    }

    private String getName(String path)
    {
        int idx = path.lastIndexOf('/');
        if (idx > -1)
        {
            return path.substring(idx);
        }
        return path;
    }

    private NativeLibraryClause getSelectedLibraryClause() throws BundleException
    {
        if ((m_libraryClauses != null) && (m_libraryClauses.size() > 0))
        {
            List<NativeLibraryClause> clauseList = new ArrayList<NativeLibraryClause>();

            // Search for matching native clauses.
            for (NativeLibraryClause libraryClause : m_libraryClauses)
            {
                if (libraryClause.match(m_configMap))
                {
                    clauseList.add(libraryClause);
                }
            }

            // Select the matching native clause.
            int selected = 0;
            if (clauseList.isEmpty())
            {
                // If optional clause exists, no error thrown.
                if (m_libraryHeadersOptional)
                {
                    return null;
                }
                else
                {
                    throw new BundleException("Unable to select a native library clause.");
                }
            }
            else if (clauseList.size() == 1)
            {
                selected = 0;
            }
            else if (clauseList.size() > 1)
            {
                selected = firstSortedClause(clauseList);
            }
            return ((NativeLibraryClause) clauseList.get(selected));
        }

        return null;
    }

    private int firstSortedClause(List<NativeLibraryClause> clauseList)
    {
        ArrayList<String> indexList = new ArrayList<String>();
        ArrayList<String> selection = new ArrayList<String>();

        // Init index list
        for (int i = 0; i < clauseList.size(); i++)
        {
            indexList.add("" + i);
        }

        // Select clause with 'osversion' range declared
        // and get back the max floor of 'osversion' ranges.
        Version osVersionRangeMaxFloor = new Version(0, 0, 0);
        for (int i = 0; i < indexList.size(); i++)
        {
            int index = Integer.parseInt(indexList.get(i).toString());
            String[] osversions = ((NativeLibraryClause) clauseList.get(index)).getOSVersions();
            if (osversions != null)
            {
                selection.add("" + indexList.get(i));
            }
            for (int k = 0; (osversions != null) && (k < osversions.length); k++)
            {
                VersionRange range = new VersionRange(osversions[k]);
                if ((range.getLeft()).compareTo(osVersionRangeMaxFloor) >= 0)
                {
                    osVersionRangeMaxFloor = range.getLeft();
                }
            }
        }

        if (selection.size() == 1)
        {
            return Integer.parseInt(selection.get(0).toString());
        }
        else if (selection.size() > 1)
        {
            // Keep only selected clauses with an 'osversion'
            // equal to the max floor of 'osversion' ranges.
            indexList = selection;
            selection = new ArrayList<String>();
            for (int i = 0; i < indexList.size(); i++)
            {
                int index = Integer.parseInt(indexList.get(i).toString());
                String[] osversions = ((NativeLibraryClause) clauseList.get(index)).getOSVersions();
                for (int k = 0; k < osversions.length; k++)
                {
                    VersionRange range = new VersionRange(osversions[k]);
                    if ((range.getLeft()).compareTo(osVersionRangeMaxFloor) >= 0)
                    {
                        selection.add("" + indexList.get(i));
                    }
                }
            }
        }

        if (selection.isEmpty())
        {
            // Re-init index list.
            selection.clear();
            indexList.clear();
            for (int i = 0; i < clauseList.size(); i++)
            {
                indexList.add("" + i);
            }
        }
        else if (selection.size() == 1)
        {
            return Integer.parseInt(selection.get(0).toString());
        }
        else
        {
            indexList = selection;
            selection.clear();
        }

        // Keep only clauses with 'language' declared.
        for (int i = 0; i < indexList.size(); i++)
        {
            int index = Integer.parseInt(indexList.get(i).toString());
            if (((NativeLibraryClause) clauseList.get(index)).getLanguages() != null)
            {
                selection.add("" + indexList.get(i));
            }
        }

        // Return the first sorted clause
        if (selection.isEmpty())
        {
            return 0;
        }
        else
        {
            return Integer.parseInt(selection.get(0).toString());
        }
    }

    private static List<ParsedHeaderClause> calculateImplicitImports(
        List<BundleCapability> exports, List<ParsedHeaderClause> imports)
        throws BundleException
    {
        List<ParsedHeaderClause> clauseList = new ArrayList<ParsedHeaderClause>();

        // Since all R3 exports imply an import, add a corresponding
        // requirement for each existing export capability. Do not
        // duplicate imports.
        Map<String, String> map =  new HashMap<String, String>();
        // Add existing imports.
        for (int impIdx = 0; impIdx < imports.size(); impIdx++)
        {
            for (int pathIdx = 0; pathIdx < imports.get(impIdx).m_paths.size(); pathIdx++)
            {
                map.put(
                    imports.get(impIdx).m_paths.get(pathIdx),
                    imports.get(impIdx).m_paths.get(pathIdx));
            }
        }
        // Add import requirement for each export capability.
        for (int i = 0; i < exports.size(); i++)
        {
            if (map.get(exports.get(i).getAttributes()
                .get(BundleRevision.PACKAGE_NAMESPACE)) == 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)
                {
                    attrs.put(
                        Constants.VERSION_ATTRIBUTE,
                        new VersionRange(version.toString()));
                }

                List<String> paths = new ArrayList<String>();
                paths.add((String)
                    exports.get(i).getAttributes().get(BundleRevision.PACKAGE_NAMESPACE));
                clauseList.add(
                    new ParsedHeaderClause(
                        paths, Collections.EMPTY_MAP, attrs, Collections.EMPTY_MAP));
            }
        }

        return clauseList;
    }

    private static List<BundleCapability> calculateImplicitUses(
        List<BundleCapability> exports, List<ParsedHeaderClause> imports)
        throws BundleException
    {
        // Add a "uses" directive onto each export of R3 bundles
        // that references every other import (which will include
        // exports, since export implies import); this is
        // necessary since R3 bundles assumed a single class space,
        // but R4 allows for multiple class spaces.
        String usesValue = "";
        for (int i = 0; i < imports.size(); i++)
        {
            for (int pathIdx = 0; pathIdx < imports.get(i).m_paths.size(); pathIdx++)
            {
                usesValue = usesValue
                    + ((usesValue.length() > 0) ? "," : "")
                    + imports.get(i).m_paths.get(pathIdx);
            }
        }
        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(),
                BundleRevision.PACKAGE_NAMESPACE,
                dirs,
                exports.get(i).getAttributes()));
        }

        return exports;
    }

    private static boolean checkExtensionBundle(Map<String, Object> headerMap) throws BundleException
    {
        Object extension = parseExtensionBundleHeader(
            (String) headerMap.get(Constants.FRAGMENT_HOST));

        if (extension != null)
        {
            if (!(Constants.EXTENSION_FRAMEWORK.equals(extension) ||
                Constants.EXTENSION_BOOTCLASSPATH.equals(extension)))
            {
                throw new BundleException(
                    "Extension bundle must have either 'extension:=framework' or 'extension:=bootclasspath'");
            }
            if (headerMap.containsKey(Constants.REQUIRE_BUNDLE) ||
                headerMap.containsKey(Constants.BUNDLE_NATIVECODE) ||
                headerMap.containsKey(Constants.DYNAMICIMPORT_PACKAGE) ||
                headerMap.containsKey(Constants.BUNDLE_ACTIVATOR))
            {
                throw new BundleException("Invalid extension bundle manifest");
            }
            return true;
        }
        return false;
    }

    private static BundleCapabilityImpl parseBundleSymbolicName(
        BundleRevision owner, Map<String, Object> 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 require capability and return it.
            String symName = (String) clauses.get(0).m_paths.get(0);
            clauses.get(0).m_attrs.put(BundleRevision.BUNDLE_NAMESPACE, symName);
            clauses.get(0).m_attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bundleVersion);
            return new BundleCapabilityImpl(
                owner,
                BundleRevision.BUNDLE_NAMESPACE,
                clauses.get(0).m_dirs,
                clauses.get(0).m_attrs);
        }

        return null;
    }

    private static BundleCapabilityImpl addIdentityCapability(BundleRevision owner,
        Map<String, Object> headerMap, BundleCapabilityImpl bundleCap)
    {
        Map<String, Object> attrs = new HashMap<String, Object>();

        attrs.put(IdentityNamespace.IDENTITY_NAMESPACE,
            bundleCap.getAttributes().get(BundleNamespace.BUNDLE_NAMESPACE));
        attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE,
            headerMap.get(Constants.FRAGMENT_HOST) == null
            ? IdentityNamespace.TYPE_BUNDLE
            : IdentityNamespace.TYPE_FRAGMENT);
        attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE,
            bundleCap.getAttributes().get(Constants.BUNDLE_VERSION_ATTRIBUTE));

        if (headerMap.get(Constants.BUNDLE_COPYRIGHT) != null)
        {
            attrs.put(IdentityNamespace.CAPABILITY_COPYRIGHT_ATTRIBUTE,
                headerMap.get(Constants.BUNDLE_COPYRIGHT));
        }

        if (headerMap.get(Constants.BUNDLE_DESCRIPTION) != null)
        {
            attrs.put(IdentityNamespace.CAPABILITY_DESCRIPTION_ATTRIBUTE,
                headerMap.get(Constants.BUNDLE_DESCRIPTION));
        }
        if (headerMap.get(Constants.BUNDLE_DOCURL) != null)
        {
            attrs.put(IdentityNamespace.CAPABILITY_DOCUMENTATION_ATTRIBUTE,
                headerMap.get(Constants.BUNDLE_DOCURL));
        }
        if (headerMap.get(BUNDLE_LICENSE_HEADER) != null)
        {
            attrs.put(IdentityNamespace.CAPABILITY_LICENSE_ATTRIBUTE,
                headerMap.get(BUNDLE_LICENSE_HEADER));
        }

        Map<String, String> dirs;
        if (bundleCap.getDirectives().get(Constants.SINGLETON_DIRECTIVE) != null)
        {
            dirs = Collections.singletonMap(IdentityNamespace.CAPABILITY_SINGLETON_DIRECTIVE,
                    bundleCap.getDirectives().get(Constants.SINGLETON_DIRECTIVE));
        }
        else
        {
            dirs = Collections.emptyMap();
        }
        return new BundleCapabilityImpl(owner, IdentityNamespace.IDENTITY_NAMESPACE, dirs, attrs);
    }

    private static List<BundleRequirementImpl> parseFragmentHost(
        Logger logger, BundleRevision owner, Map<String, Object> headerMap)
        throws BundleException
    {
        List<BundleRequirementImpl> reqs = new ArrayList<BundleRequirementImpl>();

        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 attribute is specified, then convert
                // it to the proper type.
                Object value = clauses.get(0).m_attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
                value = (value == null) ? "0.0.0" : value;
                if (value != null)
                {
                    clauses.get(0).m_attrs.put(
                        Constants.BUNDLE_VERSION_ATTRIBUTE,
                        new VersionRange(value.toString()));
                }

                // Note that we use a linked hash map here to ensure the
                // host symbolic name is first, which will make indexing
                // more efficient.
// TODO: OSGi R4.3 - This is ordering is kind of hacky.
                // Prepend the host symbolic name to the map of attributes.
                Map<String, Object> attrs = clauses.get(0).m_attrs;
                Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
                // We want this first from an indexing perspective.
                newAttrs.put(
                    BundleRevision.HOST_NAMESPACE,
                    clauses.get(0).m_paths.get(0));
                newAttrs.putAll(attrs);
                // But we need to put it again to make sure it wasn't overwritten.
                newAttrs.put(
                    BundleRevision.HOST_NAMESPACE,
                    clauses.get(0).m_paths.get(0));

                // Create filter now so we can inject filter directive.
                SimpleFilter sf = SimpleFilter.convert(newAttrs);

                // Inject filter directive.
// TODO: OSGi R4.3 - Can we insert this on demand somehow?
                Map<String, String> dirs = clauses.get(0).m_dirs;
                Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
                newDirs.putAll(dirs);
                newDirs.put(
                    Constants.FILTER_DIRECTIVE,
                    sf.toString());

                reqs.add(new BundleRequirementImpl(
                    owner, BundleRevision.HOST_NAMESPACE,
                    newDirs,
                    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;
            logger.log(
                Logger.LOG_WARNING,
                "Only R4 bundles can be fragments: " + s);
        }

        return reqs;
    }

    private static List<BundleRequirement> parseBreeHeader(String header, BundleRevision owner)
    {
        List<String> filters = new ArrayList<String>();
        for (String entry : parseDelimitedString(header, ","))
        {
            List<String> names = parseDelimitedString(entry, "/");
            List<String> left = parseDelimitedString(names.get(0), "-");

            String lName = left.get(0);
            Version lVer;
            try
            {
                lVer = Version.parseVersion(left.get(1));
            }
            catch (Exception ex)
            {
                // Version doesn't parse. Make it part of the name.
                lName = names.get(0);
                lVer = null;
            }

            String rName = null;
            Version rVer = null;
            if (names.size() > 1)
            {
                List<String> right = parseDelimitedString(names.get(1), "-");
                rName = right.get(0);
                try
                {
                    rVer = Version.parseVersion(right.get(1));
                }
                catch (Exception ex)
                {
                    rName = names.get(1);
                    rVer = null;
                }
            }

            String versionClause;
            if (lVer != null)
            {
                if ((rVer != null) && (!rVer.equals(lVer)))
                {
                    // Both versions are defined, but different. Make each of them part of the name
                    lName = names.get(0);
                    rName = names.get(1);
                    versionClause = null;
                }
                else
                {
                    versionClause = getBreeVersionClause(lVer);
                }
            }
            else
            {
                versionClause = getBreeVersionClause(rVer);
            }

            if ("J2SE".equals(lName))
            {
                // J2SE is not used in the Capability variant of BREE, use JavaSE here
                // This can only happen with the lName part...
                lName = "JavaSE";
            }

            String nameClause;
            if (rName != null)
                nameClause = "(" + ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE + "=" + lName + "/" + rName + ")";
            else
                nameClause = "(" + ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE + "=" + lName + ")";

            String filter;
            if (versionClause != null)
                filter = "(&" + nameClause + versionClause + ")";
            else
                filter = nameClause;

            filters.add(filter);
        }

        if (filters.size() == 0)
        {
            return Collections.emptyList();
        }
        else
        {
            String reqFilter;
            if (filters.size() == 1)
            {
                reqFilter = filters.get(0);
            }
            else
            {
                // If there are more BREE filters, we need to or them together
                StringBuilder sb = new StringBuilder("(|");
                for (String f : filters)
                {
                    sb.append(f);
                }
                sb.append(")");
                reqFilter = sb.toString();
            }

            SimpleFilter sf = SimpleFilter.parse(reqFilter);
            return Collections.<BundleRequirement>singletonList(new BundleRequirementImpl(
                owner,
                ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE,
                Collections.singletonMap(ExecutionEnvironmentNamespace.REQUIREMENT_FILTER_DIRECTIVE, reqFilter),
                Collections.<String, Object>emptyMap(),
                sf));
        }
    }

    private static String getBreeVersionClause(Version ver)
    {
        if (ver == null)
            return null;

        return "(" + ExecutionEnvironmentNamespace.CAPABILITY_VERSION_ATTRIBUTE + "=" + ver + ")";
    }

    private static List<ParsedHeaderClause> normalizeRequireClauses(
        Logger logger, 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 (ParsedHeaderClause clause : clauses)
            {
                Object value = clause.m_attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
                if (value != null)
                {
                    clause.m_attrs.put(
                        Constants.BUNDLE_VERSION_ATTRIBUTE,
                        new VersionRange(value.toString()));
                }
            }
        }

        return clauses;
    }

    private static List<BundleRequirementImpl> convertRequires(
        List<ParsedHeaderClause> clauses, BundleRevision owner)
    {
        List<BundleRequirementImpl> reqList = new ArrayList<BundleRequirementImpl>();
        for (ParsedHeaderClause clause : clauses)
        {
            for (String path : clause.m_paths)
            {
                // Prepend the bundle symbolic name to the array of attributes.
                Map<String, Object> attrs = clause.m_attrs;
                // Note that we use a linked hash map here to ensure the
                // symbolic name attribute is first, which will make indexing
                // more efficient.
// TODO: OSGi R4.3 - This is ordering is kind of hacky.
                // Prepend the symbolic name to the array of attributes.
                Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
                // We want this first from an indexing perspective.
                newAttrs.put(
                    BundleRevision.BUNDLE_NAMESPACE,
                    path);
                newAttrs.putAll(attrs);
                // But we need to put it again to make sure it wasn't overwritten.
                newAttrs.put(
                    BundleRevision.BUNDLE_NAMESPACE,
                    path);

                // Create filter now so we can inject filter directive.
                SimpleFilter sf = SimpleFilter.convert(newAttrs);

                // Inject filter directive.
// TODO: OSGi R4.3 - Can we insert this on demand somehow?
                Map<String, String> dirs = clause.m_dirs;
                Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
                newDirs.putAll(dirs);
                newDirs.put(
                    Constants.FILTER_DIRECTIVE,
                    sf.toString());

                // Create package requirement and add to requirement list.
                reqList.add(
                    new BundleRequirementImpl(
                        owner,
                        BundleRevision.BUNDLE_NAMESPACE,
                        newDirs,
                        newAttrs));
            }
        }

        return reqList;
    }

    public static String parseExtensionBundleHeader(String header)
        throws BundleException
    {
        List<ParsedHeaderClause> clauses = parseStandardHeader(header);

        String result = null;

        if (clauses.size() == 1)
        {
            for (Entry<String, String> entry : clauses.get(0).m_dirs.entrySet())
            {
                if (Constants.EXTENSION_DIRECTIVE.equals(entry.getKey()))
                {
                    result = entry.getValue();
                }
            }

            if (FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(clauses.get(0).m_paths.get(0)) ||
                Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(clauses.get(0).m_paths.get(0)))
            {
                result = (result == null) ? Constants.EXTENSION_FRAMEWORK : result;
            }
            else if (result != null)
            {
                throw new BundleException(
                    "Only the system bundle can have extension bundles.");
            }
        }

        return result;
    }

    private void parseActivationPolicy(Map<String, Object> headerMap)
    {
        m_activationPolicy = BundleRevisionImpl.EAGER_ACTIVATION;

        List<ParsedHeaderClause> clauses = parseStandardHeader(
            (String) headerMap.get(Constants.BUNDLE_ACTIVATIONPOLICY));

        if (clauses.size() > 0)
        {
            // Just look for a "path" matching the lazy policy, ignore
            // everything else.
            for (String path : clauses.get(0).m_paths)
            {
                if (path.equals(Constants.ACTIVATION_LAZY))
                {
                    m_activationPolicy = BundleRevisionImpl.LAZY_ACTIVATION;
                    for (Entry<String, String> entry : clauses.get(0).m_dirs.entrySet())
                    {
                        if (entry.getKey().equalsIgnoreCase(Constants.INCLUDE_DIRECTIVE))
                        {
                            m_activationIncludeDir = entry.getValue();
                        }
                        else if (entry.getKey().equalsIgnoreCase(Constants.EXCLUDE_DIRECTIVE))
                        {
                            m_activationExcludeDir = entry.getValue();
                        }
                    }
                    break;
                }
            }
        }
    }

    // Like this: path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2,
    //            path; path; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
    public static void main(String[] headers)
    {
        String header = headers[0];
        if (header != null)
        {
            if (header.length() == 0)
            {
                throw new IllegalArgumentException(
                    "A header cannot be an empty string.");
            }
            List<ParsedHeaderClause> clauses = parseStandardHeader(header);

            for (ParsedHeaderClause clause : clauses)
            {
                System.out.println("PATHS " + clause.m_paths);
                System.out.println("    DIRS  " + clause.m_dirs);
                System.out.println("    ATTRS " + clause.m_attrs);
                System.out.println("    TYPES " + clause.m_types);
            }

        }
    }

    private static final char EOF = (char) -1;

    private static char charAt(int pos, String headers, int length)
    {
        if (pos >= length)
        {
            return EOF;
        }
        return headers.charAt(pos);
    }

    private static final int CLAUSE_START = 0;
    private static final int PARAMETER_START = 1;
    private static final int KEY = 2;
    private static final int DIRECTIVE_OR_TYPEDATTRIBUTE = 4;
    private static final int ARGUMENT = 8;
    private static final int VALUE = 16;

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static List<ParsedHeaderClause> parseStandardHeader(String header)
    {
        List<ParsedHeaderClause> clauses = new ArrayList<ParsedHeaderClause>();
        if (header == null)
        {
            return clauses;
        }
        ParsedHeaderClause clause = null;
        String key = null;
        Map targetMap = null;
        int state = CLAUSE_START;
        int currentPosition = 0;
        int startPosition = 0;
        int length = header.length();
        boolean quoted = false;
        boolean escaped = false;

        char currentChar = EOF;
        do
        {
            currentChar = charAt(currentPosition, header, length);
            switch (state)
            {
                case CLAUSE_START:
                    clause = new ParsedHeaderClause(
                            new ArrayList<String>(),
                            new HashMap<String, String>(),
                            new HashMap<String, Object>(),
                            new HashMap<String, String>());
                    clauses.add(clause);
                    state = PARAMETER_START;
                case PARAMETER_START:
                    startPosition = currentPosition;
                    state = KEY;
                case KEY:
                    switch (currentChar)
                    {
                        case ':':
                        case '=':
                            key = header.substring(startPosition, currentPosition).trim();
                            startPosition = currentPosition + 1;
                            targetMap = clause.m_attrs;
                            state = currentChar == ':' ? DIRECTIVE_OR_TYPEDATTRIBUTE : ARGUMENT;
                            break;
                        case EOF:
                        case ',':
                        case ';':
                            clause.m_paths.add(header.substring(startPosition, currentPosition).trim());
                            state = currentChar == ',' ? CLAUSE_START : PARAMETER_START;
                            break;
                        default:
                            break;
                    }
                    currentPosition++;
                    break;
                case DIRECTIVE_OR_TYPEDATTRIBUTE:
                    switch(currentChar)
                    {
                        case '=':
                            if (startPosition != currentPosition)
                            {
                                clause.m_types.put(key, header.substring(startPosition, currentPosition).trim());
                            }
                            else
                            {
                                targetMap = clause.m_dirs;
                            }
                            state = ARGUMENT;
                            startPosition = currentPosition + 1;
                            break;
                        default:
                            break;
                    }
                    currentPosition++;
                    break;
                case ARGUMENT:
                    if (currentChar == '\"')
                    {
                        quoted = true;
                        currentPosition++;
                    }
                    else
                    {
                        quoted = false;
                    }
                    if (!Character.isWhitespace(currentChar)) {
                    	state = VALUE;
                    }
                    else {
                    	currentPosition++;
                    }
                    break;
                case VALUE:
                    if (escaped)
                    {
                        escaped = false;
                    }
                    else
                    {
                        if (currentChar == '\\' )
                        {
                            escaped = true;
                        }
                        else if (quoted && currentChar == '\"')
                        {
                            quoted = false;
                        }
                        else if (!quoted)
                        {
                            String value = null;
                            switch(currentChar)
                            {
                                case EOF:
                                case ';':
                                case ',':
                                    value = header.substring(startPosition, currentPosition).trim();
                                    if (value.startsWith("\"") && value.endsWith("\""))
                                    {
                                        value = value.substring(1, value.length() - 1);
                                    }
                                    if (targetMap.put(key, value) != null)
                                    {
                                        throw new IllegalArgumentException(
                                                "Duplicate '" + key + "' in: " + header);
                                    }
                                    state = currentChar == ';' ? PARAMETER_START : CLAUSE_START;
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    currentPosition++;
                    break;
                default:
                    break;
            }
        } while ( currentChar != EOF);

        if (state > PARAMETER_START)
        {
            throw new IllegalArgumentException("Unable to parse header: " + header);
        }
        return clauses;
    }

    public static List<String> parseDelimitedString(String value, String delim)
    {
        return parseDelimitedString(value, delim, true);
    }

    /**
     * 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 a list of string or an empty list if there are none.
    **/
    public static List<String> parseDelimitedString(String value, String delim, boolean trim)
    {
        if (value == null)
        {
           value = "";
        }

        List<String> list = new ArrayList<String>();

        int CHAR = 1;
        int DELIMITER = 2;
        int STARTQUOTE = 4;
        int ENDQUOTE = 8;

        StringBuilder sb = new StringBuilder();

        int expecting = (CHAR | DELIMITER | STARTQUOTE);

        boolean isEscaped = false;
        for (int i = 0; i < value.length(); i++)
        {
            char c = value.charAt(i);

            boolean isDelimiter = (delim.indexOf(c) >= 0);

            if (!isEscaped && (c == '\\'))
            {
                isEscaped = true;
                continue;
            }

            if (isEscaped)
            {
                sb.append(c);
            }
            else if (isDelimiter && ((expecting & DELIMITER) > 0))
            {
                if (trim)
                {
                    list.add(sb.toString().trim());
                }
                else
                {
                    list.add(sb.toString());
                }
                sb.delete(0, sb.length());
                expecting = (CHAR | DELIMITER | STARTQUOTE);
            }
            else if ((c == '"') && ((expecting & STARTQUOTE) > 0))
            {
                sb.append(c);
                expecting = CHAR | ENDQUOTE;
            }
            else if ((c == '"') && ((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);
            }

            isEscaped = false;
        }

        if (sb.length() > 0)
        {
            if (trim)
            {
                list.add(sb.toString().trim());
            }
            else
            {
                list.add(sb.toString());
            }
        }

        return list;
    }

    /**
     * Parses native code manifest headers.
     * @param libStrs an array of native library manifest header
     *        strings from the bundle manifest.
     * @return an array of <tt>LibraryInfo</tt> objects for the
     *         passed in strings.
    **/
    private static List<NativeLibraryClause> parseLibraryStrings(
        Logger logger, List<String> libStrs)
        throws IllegalArgumentException
    {
        if (libStrs == null)
        {
            return new ArrayList<NativeLibraryClause>(0);
        }

        List<NativeLibraryClause> libList = new ArrayList<NativeLibraryClause>(libStrs.size());

        for (int i = 0; i < libStrs.size(); i++)
        {
            NativeLibraryClause clause = NativeLibraryClause.parse(logger, libStrs.get(i));
            libList.add(clause);
        }

        return libList;
    }

    public static List<BundleCapability> aliasSymbolicName(List<BundleCapability> caps, BundleRevision owner)
    {
        if (caps == null)
        {
            return new ArrayList<BundleCapability>(0);
        }

        List<BundleCapability> aliasCaps = new ArrayList<BundleCapability>(caps);

        String[] aliases = {
                FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME,
                Constants.SYSTEM_BUNDLE_SYMBOLICNAME };

        for (int capIdx = 0; capIdx < aliasCaps.size(); capIdx++)
        {
            BundleCapability cap = aliasCaps.get(capIdx);

            // Need to alias bundle and host capabilities.
            if (cap.getNamespace().equals(BundleRevision.BUNDLE_NAMESPACE)
                    || cap.getNamespace().equals(BundleRevision.HOST_NAMESPACE))
            {
                // Make a copy of the attribute array.
                Map<String, Object> aliasAttrs =
                        new HashMap<String, Object>(cap.getAttributes());
                // Add the aliased value.
                aliasAttrs.put(cap.getNamespace(), aliases);
                // Create the aliased capability to replace the old capability.
                cap = new BundleCapabilityImpl(
                        owner,
                        cap.getNamespace(),
                        cap.getDirectives(),
                        aliasAttrs);
                aliasCaps.set(capIdx, cap);
            }

            // Further, search attributes for bundle symbolic name and alias it too.
            for (Entry<String, Object> entry : cap.getAttributes().entrySet())
            {
                // If there is a bundle symbolic name attribute, add the
                // standard alias as a value.
                if (entry.getKey().equalsIgnoreCase(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE))
                {
                    // Make a copy of the attribute array.
                    Map<String, Object> aliasAttrs =
                            new HashMap<String, Object>(cap.getAttributes());
                    // Add the aliased value.
                    aliasAttrs.put(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, aliases);
                    // Create the aliased capability to replace the old capability.
                    aliasCaps.set(capIdx, new BundleCapabilityImpl(
                            owner,
                            cap.getNamespace(),
                            cap.getDirectives(),
                            aliasAttrs));
                    // Continue with the next capability.
                    break;
                }
            }
        }

        return aliasCaps;
    }
}
