/*
 * 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.bundlerepository.impl;

import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.felix.bundlerepository.Capability;
import org.apache.felix.bundlerepository.DataModelHelper;
import org.apache.felix.bundlerepository.Property;
import org.apache.felix.bundlerepository.Repository;
import org.apache.felix.bundlerepository.Requirement;
import org.apache.felix.bundlerepository.Resource;
import org.apache.felix.utils.filter.FilterImpl;
import org.apache.felix.utils.manifest.Attribute;
import org.apache.felix.utils.manifest.Clause;
import org.apache.felix.utils.manifest.Directive;
import org.apache.felix.utils.manifest.Parser;
import org.apache.felix.utils.version.VersionCleaner;
import org.apache.felix.utils.version.VersionRange;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.Version;

public class DataModelHelperImpl implements DataModelHelper
{

    public static final String BUNDLE_LICENSE = "Bundle-License";
    public static final String BUNDLE_SOURCE = "Bundle-Source";

    public Requirement requirement(String name, String filter)
    {
        RequirementImpl req = new RequirementImpl();
        req.setName(name);
        if (filter != null)
        {
            req.setFilter(filter);
        }
        return req;
    }

    public Filter filter(String filter)
    {
        try
        {
            return FilterImpl.newInstance(filter);
        }
        catch (InvalidSyntaxException e)
        {
            IllegalArgumentException ex = new IllegalArgumentException();
            ex.initCause(e);
            throw ex;
        }
    }

    public Repository repository(final URL url) throws Exception
    {
        InputStream is = null;

        try
        {
            if (url.getPath().endsWith(".zip"))
            {
                ZipInputStream zin = new ZipInputStream(FileUtil.openURL(url));
                ZipEntry entry = zin.getNextEntry();
                while (entry != null)
                {
                    if (entry.getName().equals("repository.xml") || entry.getName().equals("index.xml"))
                    {
                        is = zin;
                        break;
                    }
                    entry = zin.getNextEntry();
                }
                // as the ZipInputStream is not used further it would not be closed.
                if (is == null)
                {
                    try
                    {
                        zin.close();
                    }
                    catch (IOException ex)
                    {
                        // Not much we can do.
                    }
                }
            }
            else if (url.getPath().endsWith(".gz"))
            {
                is = new GZIPInputStream(FileUtil.openURL(url));
            }
            else
            {
                is = FileUtil.openURL(url);
            }

            if (is != null)
            {
                String repositoryUri = url.toExternalForm();
                String baseUri;
                if (repositoryUri.endsWith(".zip")) {
                    baseUri = new StringBuilder("jar:").append(repositoryUri).append("!/").toString();
                } else if (repositoryUri.endsWith(".xml")) {
                    baseUri = repositoryUri.substring(0, repositoryUri.lastIndexOf('/') + 1);
                } else {
                    baseUri = repositoryUri;
                }
                RepositoryImpl repository = repository(is, URI.create(baseUri));
                repository.setURI(repositoryUri);

                return repository;
            }
            else
            {
                // This should not happen.
                throw new Exception("Unable to get input stream for repository.");
            }
        }
        finally
        {
            try
            {
                if (is != null)
                {
                    is.close();
                }
            }
            catch (IOException ex)
            {
                // Not much we can do.
            }
        }
    }

    public RepositoryImpl repository(InputStream is, URI baseURI) throws Exception
    {
        RepositoryParser parser = RepositoryParser.getParser();
        RepositoryImpl repository = parser.parseRepository(is, baseURI);
        
        return repository;
    }

    public Repository repository(Resource[] resources)
    {
        return new RepositoryImpl(resources);
    }

    public Capability capability(String name, Map properties)
    {
        CapabilityImpl cap = new CapabilityImpl(name);
        for (Iterator it = properties.entrySet().iterator(); it.hasNext();)
        {
            Map.Entry e = (Map.Entry) it.next();
            cap.addProperty((String) e.getKey(), (String) e.getValue());
        }
        return cap;
    }

    public String writeRepository(Repository repository)
    {
        try
        {
            StringWriter sw = new StringWriter();
            writeRepository(repository, sw);
            return sw.toString();
        }
        catch (IOException e)
        {
            IllegalStateException ex = new IllegalStateException(e);
            ex.initCause(e);
            throw ex;
        }
    }

    public void writeRepository(Repository repository, Writer writer) throws IOException
    {
        XmlWriter w = new XmlWriter(writer);
        toXml(w, repository);
    }

    public String writeResource(Resource resource)
    {
        try
        {
            StringWriter sw = new StringWriter();
            writeResource(resource, sw);
            return sw.toString();
        }
        catch (IOException e)
        {
            IllegalStateException ex = new IllegalStateException(e);
            ex.initCause(e);
            throw ex;
        }
    }

    public void writeResource(Resource resource, Writer writer) throws IOException
    {
        XmlWriter w = new XmlWriter(writer);
        toXml(w, resource);
    }

    public String writeCapability(Capability capability)
    {
        try
        {
            StringWriter sw = new StringWriter();
            writeCapability(capability, sw);
            return sw.toString();
        }
        catch (IOException e)
        {
            IllegalStateException ex = new IllegalStateException(e);
            ex.initCause(e);
            throw ex;
        }
    }

    public void writeCapability(Capability capability, Writer writer) throws IOException
    {
        XmlWriter w = new XmlWriter(writer);
        toXml(w, capability);
    }

    public String writeRequirement(Requirement requirement)
    {
        try
        {
            StringWriter sw = new StringWriter();
            writeRequirement(requirement, sw);
            return sw.toString();
        }
        catch (IOException e)
        {
            IllegalStateException ex = new IllegalStateException(e);
            ex.initCause(e);
            throw ex;
        }
    }

    public void writeRequirement(Requirement requirement, Writer writer) throws IOException
    {
        XmlWriter w = new XmlWriter(writer);
        toXml(w, requirement);
    }

    public String writeProperty(Property property)
    {
        try
        {
            StringWriter sw = new StringWriter();
            writeProperty(property, sw);
            return sw.toString();
        }
        catch (IOException e)
        {
            IllegalStateException ex = new IllegalStateException(e);
            ex.initCause(e);
            throw ex;
        }
    }

    public void writeProperty(Property property, Writer writer) throws IOException
    {
        XmlWriter w = new XmlWriter(writer);
        toXml(w, property);
    }

    private static void toXml(XmlWriter w, Repository repository) throws IOException
    {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss.SSS");
        w.element(RepositoryParser.REPOSITORY)
            .attribute(RepositoryParser.NAME, repository.getName())
            .attribute(RepositoryParser.LASTMODIFIED, format.format(new Date(repository.getLastModified())));

        if (repository instanceof RepositoryImpl)
        {
            Referral[] referrals = ((RepositoryImpl) repository).getReferrals();
            for (int i = 0; referrals != null && i < referrals.length; i++)
            {
                w.element(RepositoryParser.REFERRAL)
                    .attribute(RepositoryParser.DEPTH, new Integer(referrals[i].getDepth()))
                    .attribute(RepositoryParser.URL, referrals[i].getUrl())
                    .end();
            }
        }

        Resource[] resources = repository.getResources();
        for (int i = 0; resources != null && i < resources.length; i++)
        {
            toXml(w, resources[i]);
        }

        w.end();
    }

    private static void toXml(XmlWriter w, Resource resource) throws IOException
    {
        w.element(RepositoryParser.RESOURCE)
            .attribute(Resource.ID, resource.getId())
            .attribute(Resource.SYMBOLIC_NAME, resource.getSymbolicName())
            .attribute(Resource.PRESENTATION_NAME, resource.getPresentationName())
            .attribute(Resource.URI, getRelativeUri(resource, Resource.URI))
            .attribute(Resource.VERSION, resource.getVersion().toString());

        w.textElement(Resource.DESCRIPTION, resource.getProperties().get(Resource.DESCRIPTION))
            .textElement(Resource.SIZE, resource.getProperties().get(Resource.SIZE))
            .textElement(Resource.DOCUMENTATION_URI, getRelativeUri(resource, Resource.DOCUMENTATION_URI))
            .textElement(Resource.SOURCE_URI, getRelativeUri(resource, Resource.SOURCE_URI))
            .textElement(Resource.JAVADOC_URI, getRelativeUri(resource, Resource.JAVADOC_URI))
            .textElement(Resource.LICENSE_URI, getRelativeUri(resource, Resource.LICENSE_URI));

        String[] categories = resource.getCategories();
        for (int i = 0; categories != null && i < categories.length; i++)
        {
            w.element(RepositoryParser.CATEGORY)
                .attribute(RepositoryParser.ID, categories[i])
                .end();
        }
        Capability[] capabilities = resource.getCapabilities();
        for (int i = 0; capabilities != null && i < capabilities.length; i++)
        {
            toXml(w, capabilities[i]);
        }
        Requirement[] requirements = resource.getRequirements();
        for (int i = 0; requirements != null && i < requirements.length; i++)
        {
            toXml(w, requirements[i]);
        }
        w.end();
    }

    private static String getRelativeUri(Resource resource, String name) 
    {
        String uri = (String) resource.getProperties().get(name);
        if (resource instanceof ResourceImpl)
        {
            try
            {
                uri = URI.create(((ResourceImpl) resource).getRepository().getURI()).relativize(URI.create(uri)).toASCIIString();
            }
            catch (Throwable t)
            {
            }
        }
        return uri;
    }

    private static void toXml(XmlWriter w, Capability capability) throws IOException
    {
        w.element(RepositoryParser.CAPABILITY)
            .attribute(RepositoryParser.NAME, capability.getName());
        Property[] props = capability.getProperties();
        for (int j = 0; props != null && j < props.length; j++)
        {
            toXml(w, props[j]);
        }
        w.end();
    }

    private static void toXml(XmlWriter w, Property property) throws IOException
    {
        w.element(RepositoryParser.P)
            .attribute(RepositoryParser.N, property.getName())
            .attribute(RepositoryParser.T, property.getType())
            .attribute(RepositoryParser.V, property.getValue())
            .end();
    }

    private static void toXml(XmlWriter w, Requirement requirement) throws IOException
    {
        w.element(RepositoryParser.REQUIRE)
            .attribute(RepositoryParser.NAME, requirement.getName())
            .attribute(RepositoryParser.FILTER, requirement.getFilter())
            .attribute(RepositoryParser.EXTEND, Boolean.toString(requirement.isExtend()))
            .attribute(RepositoryParser.MULTIPLE, Boolean.toString(requirement.isMultiple()))
            .attribute(RepositoryParser.OPTIONAL, Boolean.toString(requirement.isOptional()))
            .text(requirement.getComment().trim())
            .end();
    }

    public Resource createResource(final Bundle bundle)
    {
        final Dictionary dict = bundle.getHeaders();
        return createResource(new Headers()
        {
            public String getHeader(String name)
            {
                return (String) dict.get(name);
            }
        });
    }

    public Resource createResource(final URL bundleUrl) throws IOException
    {
        ResourceImpl resource = createResource(new Headers()
        {
            private final Manifest manifest;
            private Properties localization;
            {
                // Do not use a JarInputStream so that we can read the manifest even if it's not
                // the first entry in the JAR.
                byte[] man = loadEntry(JarFile.MANIFEST_NAME);
                if (man == null)
                {
                    throw new IllegalArgumentException("The specified url is not a valid jar (can't read manifest): " + bundleUrl);
                }
                manifest = new Manifest(new ByteArrayInputStream(man));
            }
            public String getHeader(String name)
            {
                String value = manifest.getMainAttributes().getValue(name);
                if (value != null && value.startsWith("%"))
                {
                    if (localization == null)
                    {
                        try
                        {
                            localization = new Properties();
                            String path = manifest.getMainAttributes().getValue(Constants.BUNDLE_LOCALIZATION);
                            if (path == null)
                            {
                                path = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
                            }
                            path += ".properties";
                            byte[] loc = loadEntry(path);
                            if (loc != null)
                            {
                                localization.load(new ByteArrayInputStream(loc));
                            }
                        }
                        catch (IOException e)
                        {
                            // TODO: ?
                        }
                    }
                    value = value.substring(1);
                    value = localization.getProperty(value, value);
                }
                return value;
            }
            private byte[] loadEntry(String name) throws IOException
            {
                ZipInputStream zis = new ZipInputStream(FileUtil.openURL(bundleUrl));
                try
                {
                    for (ZipEntry e = zis.getNextEntry(); e != null; e = zis.getNextEntry())
                    {
                        if (name.equalsIgnoreCase(e.getName()))
                        {
                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
                            byte[] buf = new byte[1024];
                            int n;
                            while ((n = zis.read(buf, 0, buf.length)) > 0)
                            {
                                baos.write(buf, 0, n);
                            }
                            return baos.toByteArray();
                        }
                    }
                }
                finally
                {
                    zis.close();
                }
                return null;
            }
        });
        if (resource != null)
        {
            if ("file".equals(bundleUrl.getProtocol()))
            {
                try {
                    File f = new File(bundleUrl.toURI());
                    resource.put(Resource.SIZE, Long.toString(f.length()), null);
                } catch (URISyntaxException e) {
                    throw new RuntimeException(e);
                }
            }
            resource.put(Resource.URI, bundleUrl.toExternalForm(), null);
        }
        return resource;
    }

    public Resource createResource(final Attributes attributes)
    {
        return createResource(new Headers()
        {
            public String getHeader(String name)
            {
                return attributes.getValue(name);
            }
        });
    }

    public ResourceImpl createResource(Headers headers)
    {
        String bsn = headers.getHeader(Constants.BUNDLE_SYMBOLICNAME);
        if (bsn == null)
        {
            return null;
        }
        ResourceImpl resource = new ResourceImpl();
        populate(headers, resource);
        return resource;
    }

    static void populate(Headers headers, ResourceImpl resource)
    {
        String bsn = getSymbolicName(headers);
        String v = getVersion(headers);

        resource.put(Resource.ID, bsn + "/" + v);
        resource.put(Resource.SYMBOLIC_NAME, bsn);
        resource.put(Resource.VERSION, v);
        if (headers.getHeader(Constants.BUNDLE_NAME) != null)
        {
            resource.put(Resource.PRESENTATION_NAME, headers.getHeader(Constants.BUNDLE_NAME));
        }
        if (headers.getHeader(Constants.BUNDLE_DESCRIPTION) != null)
        {
            resource.put(Resource.DESCRIPTION, headers.getHeader(Constants.BUNDLE_DESCRIPTION));
        }
        if (headers.getHeader(BUNDLE_LICENSE) != null)
        {
            resource.put(Resource.LICENSE_URI, headers.getHeader(BUNDLE_LICENSE));
        }
        if (headers.getHeader(Constants.BUNDLE_COPYRIGHT) != null)
        {
            resource.put(Resource.COPYRIGHT, headers.getHeader(Constants.BUNDLE_COPYRIGHT));
        }
        if (headers.getHeader(Constants.BUNDLE_DOCURL) != null)
        {
            resource.put(Resource.DOCUMENTATION_URI, headers.getHeader(Constants.BUNDLE_DOCURL));
        }
        if (headers.getHeader(BUNDLE_SOURCE) != null)
        {
            resource.put(Resource.SOURCE_URI, headers.getHeader(BUNDLE_SOURCE));
        }

        doCategories(resource, headers);
        doBundle(resource, headers);
        doImportExportServices(resource, headers);
        doFragment(resource, headers);
        doRequires(resource, headers);
        doExports(resource, headers);
        doImports(resource, headers);
        doExecutionEnvironment(resource, headers);
        doProvides(resource, headers);
    }

    private static void doCategories(ResourceImpl resource, Headers headers)
    {
        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.BUNDLE_CATEGORY));
        for (int i = 0; clauses != null && i < clauses.length; i++)
        {
            resource.addCategory(clauses[i].getName());
        }
    }

    private static void doImportExportServices(ResourceImpl resource, Headers headers)
    {
        Clause[] imports = Parser.parseHeader(headers.getHeader(Constants.IMPORT_SERVICE));
        for (int i = 0; imports != null && i < imports.length; i++) {
            RequirementImpl ri = new RequirementImpl(Capability.SERVICE);
            ri.setFilter(createServiceFilter(imports[i]));
            ri.addText("Import Service " + imports[i].getName());

            String avail = imports[i].getDirective("availability");
            String mult = imports[i].getDirective("multiple");
            ri.setOptional("optional".equalsIgnoreCase(avail));
            ri.setMultiple(!"false".equalsIgnoreCase(mult));
            resource.addRequire(ri);
        }

        Clause[] exports = Parser.parseHeader(headers.getHeader(Constants.EXPORT_SERVICE));
        for (int i = 0; exports != null && i < exports.length; i++) {
            CapabilityImpl cap = createServiceCapability(exports[i]);
            resource.addCapability(cap);
        }
    }

    private static String createServiceFilter(Clause clause) {
        String f = clause.getAttribute("filter");
		StringBuffer filter = new StringBuffer();
        if (f != null) {
            filter.append("(&");
        }
        filter.append("(");
        filter.append(Capability.SERVICE);
        filter.append("=");
		filter.append(clause.getName());
		filter.append(")");
        if (f != null) {
            if (!f.startsWith("("))
            {
                filter.append("(").append(f).append(")");
            }
            else
            {
                filter.append(f);
            }
            filter.append(")");
        }
		return filter.toString();
    }

    private static CapabilityImpl createServiceCapability(Clause clause) {
        CapabilityImpl capability = new CapabilityImpl(Capability.SERVICE);
        capability.addProperty(Capability.SERVICE, clause.getName());
        Attribute[] attributes = clause.getAttributes();
        for (int i = 0; attributes != null && i < attributes.length; i++)
        {
            capability.addProperty(attributes[i].getName(), attributes[i].getValue());
        }
        return capability;
    }

    private static void doFragment(ResourceImpl resource, Headers headers)
    {
        // Check if we are a fragment
        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.FRAGMENT_HOST));
        if (clauses != null && clauses.length == 1)
        {
            // We are a fragment, create a requirement
            // to our host.
            RequirementImpl r = new RequirementImpl(Capability.BUNDLE);
            StringBuffer sb = new StringBuffer();
            sb.append("(&(symbolicname=");
            sb.append(clauses[0].getName());
            sb.append(")");
            appendVersion(sb, VersionRange.parseVersionRange(clauses[0].getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE)));
            sb.append(")");
            r.setFilter(sb.toString());
            r.addText("Required Host " + clauses[0].getName());
            r.setExtend(true);
            r.setOptional(false);
            r.setMultiple(false);
            resource.addRequire(r);

            // And insert a capability that we are available
            // as a fragment. ### Do we need that with extend?
            CapabilityImpl capability = new CapabilityImpl(Capability.FRAGMENT);
            capability.addProperty("host", clauses[0].getName());
            capability.addProperty("version", Property.VERSION, getVersion(clauses[0]));
            resource.addCapability(capability);
        }
    }

    private static void doRequires(ResourceImpl resource, Headers headers)
    {
        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.REQUIRE_BUNDLE));
        for (int i = 0; clauses != null && i < clauses.length; i++) {
            RequirementImpl r = new RequirementImpl(Capability.BUNDLE);

            VersionRange v = VersionRange.parseVersionRange(clauses[i].getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE));

            StringBuffer sb = new StringBuffer();
            sb.append("(&(symbolicname=");
            sb.append(clauses[i].getName());
            sb.append(")");
            appendVersion(sb, v);
            sb.append(")");
            r.setFilter(sb.toString());

            r.addText("Require Bundle " + clauses[i].getName() + "; " + v);
            r.setOptional(Constants.RESOLUTION_OPTIONAL.equalsIgnoreCase(clauses[i].getDirective(Constants.RESOLUTION_DIRECTIVE)));
            resource.addRequire(r);
        }
    }

    private static void doBundle(ResourceImpl resource, Headers headers) {
        CapabilityImpl capability = new CapabilityImpl(Capability.BUNDLE);
        capability.addProperty(Resource.SYMBOLIC_NAME, getSymbolicName(headers));
        if (headers.getHeader(Constants.BUNDLE_NAME) != null)
        {
            capability.addProperty(Resource.PRESENTATION_NAME, headers.getHeader(Constants.BUNDLE_NAME));
        }
        capability.addProperty(Resource.VERSION, Property.VERSION, getVersion(headers));
        capability.addProperty(Resource.MANIFEST_VERSION, getManifestVersion(headers));
        resource.addCapability(capability);
    }

    private static void doExports(ResourceImpl resource, Headers headers)
    {
        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.EXPORT_PACKAGE));
        for (int i = 0; clauses != null && i < clauses.length; i++)
        {
            CapabilityImpl capability = createCapability(Capability.PACKAGE, clauses[i]);
            resource.addCapability(capability);
        }
    }

    private static void doProvides(ResourceImpl resource, Headers headers) {
        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.PROVIDE_CAPABILITY));

        if (clauses != null) {
            for (Clause clause : clauses) {
                CapabilityImpl capability = createCapability(clause.getName(), clause);
                resource.addCapability(capability);
            }
        }
    }

    private static CapabilityImpl createCapability(String name, Clause clause)
    {
        CapabilityImpl capability = new CapabilityImpl(NamespaceTranslator.getFelixNamespace(name));
        capability.addProperty(name, clause.getName());
        capability.addProperty(Resource.VERSION, Property.VERSION, getVersion(clause));
        Attribute[] attributes = clause.getAttributes();
        for (int i = 0; attributes != null && i < attributes.length; i++)
        {
            String key = attributes[i].getName();
            if (key.equalsIgnoreCase(Constants.PACKAGE_SPECIFICATION_VERSION) || key.equalsIgnoreCase(Constants.VERSION_ATTRIBUTE) || key.equalsIgnoreCase("version:Version"))
            {
                continue;
            }
            else
            {
                String value = attributes[i].getValue();
                capability.addProperty(key, value);
            }
        }
        Directive[] directives = clause.getDirectives();
        for (int i = 0; directives != null && i < directives.length; i++)
        {
            String key = directives[i].getName();
            String value = directives[i].getValue();
            capability.addProperty(key + ":", value);
        }
        return capability;
    }

    private static void doImports(ResourceImpl resource, Headers headers)
    {
        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.IMPORT_PACKAGE));
        for (int i = 0; clauses != null && i < clauses.length; i++)
        {
            RequirementImpl requirement = new RequirementImpl(Capability.PACKAGE);

            createImportFilter(requirement, Capability.PACKAGE, clauses[i]);
            requirement.addText("Import package " + clauses[i]);
            requirement.setOptional(Constants.RESOLUTION_OPTIONAL.equalsIgnoreCase(clauses[i].getDirective(Constants.RESOLUTION_DIRECTIVE)));
            resource.addRequire(requirement);
        }
    }

    private static void createImportFilter(RequirementImpl requirement, String name, Clause clause)
    {
        StringBuffer filter = new StringBuffer();
        filter.append("(&(");
        filter.append(name);
        filter.append("=");
        filter.append(clause.getName());
        filter.append(")");
        appendVersion(filter, getVersionRange(clause));
        Attribute[] attributes = clause.getAttributes();
        Set attrs = doImportPackageAttributes(requirement, filter, attributes);

        // The next code is using the subset operator
        // to check mandatory attributes, it seems to be
        // impossible to rewrite. It must assert that whateber
        // is in mandatory: must be in any of the attributes.
        // This is a fundamental shortcoming of the filter language.
        if (attrs.size() > 0)
        {
            String del = "";
            filter.append("(mandatory:<*");
            for (Iterator i = attrs.iterator(); i.hasNext();)
            {
                filter.append(del);
                filter.append(i.next());
                del = ", ";
            }
            filter.append(")");
        }
        filter.append(")");
        requirement.setFilter(filter.toString());
    }

    private static Set doImportPackageAttributes(RequirementImpl requirement, StringBuffer filter, Attribute[] attributes)
    {
        HashSet set = new HashSet();
        for (int i = 0; attributes != null && i < attributes.length; i++)
        {
            String name = attributes[i].getName();
            String value = attributes[i].getValue();
            if (name.equalsIgnoreCase(Constants.PACKAGE_SPECIFICATION_VERSION) || name.equalsIgnoreCase(Constants.VERSION_ATTRIBUTE))
            {
                continue;
            }
            else if (name.equalsIgnoreCase(Constants.RESOLUTION_DIRECTIVE + ":"))
            {
                requirement.setOptional(Constants.RESOLUTION_OPTIONAL.equalsIgnoreCase(value));
            }
            if (name.endsWith(":"))
            {
                // Ignore
            }
            else
            {
                filter.append("(");
                filter.append(name);
                filter.append("=");
                filter.append(value);
                filter.append(")");
                set.add(name);
            }
        }
        return set;
    }

    private static void doExecutionEnvironment(ResourceImpl resource, Headers headers)
    {
        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT));
        if (clauses != null && clauses.length > 0)
        {
            StringBuffer sb = new StringBuffer();
            sb.append("(|");
            for (int i = 0; i < clauses.length; i++)
            {
                sb.append("(");
                sb.append(Capability.EXECUTIONENVIRONMENT);
                sb.append("=");
                sb.append(clauses[i].getName());
                sb.append(")");
            }
            sb.append(")");
            RequirementImpl req = new RequirementImpl(Capability.EXECUTIONENVIRONMENT);
            req.setFilter(sb.toString());
            req.addText("Execution Environment " + sb.toString());
            resource.addRequire(req);
        }
    }

    private static String getVersion(Clause clause)
    {
        String v = clause.getAttribute(Constants.VERSION_ATTRIBUTE);
        if (v == null)
        {
            v = clause.getAttribute(Constants.PACKAGE_SPECIFICATION_VERSION);
        }
        if (v == null)
        {
            v = clause.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE);
        }
        if (v == null)
        {
            v = clause.getAttribute("version:Version");
        }

        return VersionCleaner.clean(v);
    }

    private static VersionRange getVersionRange(Clause clause)
    {
        String v = clause.getAttribute(Constants.VERSION_ATTRIBUTE);
        if (v == null)
        {
            v = clause.getAttribute(Constants.PACKAGE_SPECIFICATION_VERSION);
        }
        if (v == null)
        {
            v = clause.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE);
        }
        return VersionRange.parseVersionRange(v);
    }

    private static String getSymbolicName(Headers headers)
    {
        String bsn = headers.getHeader(Constants.BUNDLE_SYMBOLICNAME);
        if (bsn == null)
        {
            bsn = headers.getHeader(Constants.BUNDLE_NAME);
            if (bsn == null)
            {
                bsn = "Untitled-" + headers.hashCode();
            }
        }
        Clause[] clauses = Parser.parseHeader(bsn);
        return clauses[0].getName();
    }

    private static String getVersion(Headers headers)
    {
        String v = headers.getHeader(Constants.BUNDLE_VERSION);
        return VersionCleaner.clean(v);
    }

    private static String getManifestVersion(Headers headers)
    {
        String v = headers.getHeader(Constants.BUNDLE_MANIFESTVERSION);
        if (v == null)
        {
            v = "1";
        }
        return v;
    }

    private static void appendVersion(StringBuffer filter, VersionRange version)
    {
        if (version != null)
        {
            if ( !version.isOpenFloor() )
            {
                if ( !Version.emptyVersion.equals(version.getFloor()) )
                {
                    filter.append("(");
                    filter.append(Constants.VERSION_ATTRIBUTE);
                    filter.append(">=");
                    filter.append(version.getFloor());
                    filter.append(")");
                }
            }
            else
            {
                filter.append("(!(");
                filter.append(Constants.VERSION_ATTRIBUTE);
                filter.append("<=");
                filter.append(version.getFloor());
                filter.append("))");
            }

            if (!VersionRange.INFINITE_VERSION.equals(version.getCeiling()))
            {
                if ( !version.isOpenCeiling() )
                {
                    filter.append("(");
                    filter.append(Constants.VERSION_ATTRIBUTE);
                    filter.append("<=");
                    filter.append(version.getCeiling());
                    filter.append(")");
                }
                else
                {
                    filter.append("(!(");
                    filter.append(Constants.VERSION_ATTRIBUTE);
                    filter.append(">=");
                    filter.append(version.getCeiling());
                    filter.append("))");
                }
            }
        }
    }

    interface Headers
    {
        String getHeader(String name);
    }

    public Repository readRepository(String xml) throws Exception
    {
        try
        {
            return readRepository(new StringReader(xml));
        }
        catch (IOException e)
        {
            IllegalStateException ex = new IllegalStateException(e);
            ex.initCause(e);
            throw ex;
        }
    }

    public Repository readRepository(Reader reader) throws Exception
    {
        return RepositoryParser.getParser().parseRepository(reader);
    }

    public Resource readResource(String xml) throws Exception
    {
        try
        {
            return readResource(new StringReader(xml));
        }
        catch (IOException e)
        {
            IllegalStateException ex = new IllegalStateException(e);
            ex.initCause(e);
            throw ex;
        }
    }

    public Resource readResource(Reader reader) throws Exception
    {
        return RepositoryParser.getParser().parseResource(reader);
    }

    public Capability readCapability(String xml) throws Exception
    {
        try
        {
            return readCapability(new StringReader(xml));
        }
        catch (IOException e)
        {
            IllegalStateException ex = new IllegalStateException(e);
            ex.initCause(e);
            throw ex;
        }
    }

    public Capability readCapability(Reader reader) throws Exception
    {
        return RepositoryParser.getParser().parseCapability(reader);
    }

    public Requirement readRequirement(String xml) throws Exception
    {
        try
        {
            return readRequirement(new StringReader(xml));
        }
        catch (IOException e)
        {
            IllegalStateException ex = new IllegalStateException(e);
            ex.initCause(e);
            throw ex;
        }
    }

    public Requirement readRequirement(Reader reader) throws Exception
    {
        return RepositoryParser.getParser().parseRequirement(reader);
    }

    public Property readProperty(String xml) throws Exception
    {
        try
        {
            return readProperty(new StringReader(xml));
        }
        catch (IOException e)
        {
            IllegalStateException ex = new IllegalStateException(e);
            ex.initCause(e);
            throw ex;
        }
    }

    public Property readProperty(Reader reader) throws Exception
    {
        return RepositoryParser.getParser().parseProperty(reader);
    }
}
