/* Copyright 2006 aQute SARL 
 * Licensed under the Apache License, Version 2.0, see http://www.apache.org/licenses/LICENSE-2.0 */
package aQute.lib.osgi;

import java.io.*;
import java.security.*;
import java.security.cert.*;
import java.security.spec.*;
import java.util.*;
import java.util.jar.*;
import java.util.regex.*;
import java.util.zip.*;

import aQute.bnd.make.*;
import aQute.lib.signing.*;

/**
 * Include-Resource: ( [name '=' ] file )+
 * 
 * Private-Package: package-decl ( ',' package-decl )*
 * 
 * Export-Package: package-decl ( ',' package-decl )*
 * 
 * Import-Package: package-decl ( ',' package-decl )*
 * 
 * @version $Revision: 1.4 $
 */
public class Builder extends Analyzer {
    private static final int SPLIT_MERGE_LAST  = 1;
    private static final int SPLIT_MERGE_FIRST = 2;
    private static final int SPLIT_ERROR       = 3;
    private static final int SPLIT_FIRST       = 4;
    private static final int SPLIT_DEFAULT     = 0;

    List<File>               sourcePath        = new ArrayList<File>();
    Pattern                  NAME_URL          = Pattern
                                                       .compile("(.*)(http://.*)");

    Make                     make              = new Make(this);
    private KeyStore         keystore;

    public Builder(Processor parent) {
        super(parent);
    }

    public Builder() {
    }

    public Jar build() throws Exception {
        if (getProperty(NOPE) != null)
            return null;

        String sub = getProperty(SUB);
        if (sub != null && sub.trim().length() > 0)
            error("Specified "
                    + SUB
                    + " but calls build() instead of builds() (might be a programmer error)");

        if (getProperty(CONDUIT) != null)
            error("Specified "
                    + CONDUIT
                    + " but calls build() instead of builds() (might be a programmer error");

        dot = new Jar("dot");
        addClose(dot);
        try {
            long modified = Long.parseLong(getProperty("base.modified"));
            dot.updateModified(modified, "Base modified");
        } catch (Exception e) {
        }

        doExpand(dot);
        doIncludeResources(dot);

        doConditional(dot);

        // NEW!
        // Check if we override the calculation of the
        // manifest. We still need to calculated it because
        // we need to have analyzed the classpath.

        Manifest manifest = calcManifest();

        String mf = getProperty(MANIFEST);
        if (mf != null) {
            File mff = getFile(mf);
            if (mff.isFile()) {
                try {
                    InputStream in = new FileInputStream(mff);
                    manifest = new Manifest(in);
                    in.close();
                } catch (Exception e) {
                    error(MANIFEST + " while reading manifest file", e);
                }
            } else {
                error(MANIFEST + ", no such file " + mf);
            }
        }

        dot.setManifest(manifest);

        // This must happen after we analyzed so
        // we know what it is on the classpath
        addSources(dot);
        if (getProperty(POM) != null)
            doPom(dot);

        doVerify(dot);

        if (dot.getResources().isEmpty())
            error("The JAR is empty");

        dot.updateModified(lastModified(), "Last Modified Processor");
        dot.setName(getBsn());

        sign(dot);
        return dot;
    }

    /**
     * Sign the jar file.
     * 
     * -sign : <alias> [ ';' 'password:=' <password> ] [ ';' 'keystore:='
     * <keystore> ] [ ';' 'sign-password:=' <pw> ] ( ',' ... )*
     * 
     * @return
     */

    void sign(Jar jar) throws Exception {
        String signing = getProperty("-sign");
        if (signing == null)
            return;

        trace("Signing %s, with %s", getBsn(), signing);

        Map<String, Map<String, String>> infos = parseHeader(signing);
        for (Map.Entry<String, Map<String, String>> entry : infos.entrySet()) {
            String alias = entry.getKey();
            String keystoreLocation = entry.getValue().get(
                    KEYSTORE_LOCATION_DIRECTIVE);
            String keystoreProvider = entry.getValue().get(
                    KEYSTORE_PROVIDER_DIRECTIVE);
            String password = entry.getValue().get(KEYSTORE_PASSWORD_DIRECTIVE);
            String signpassword = entry.getValue().get(SIGN_PASSWORD_DIRECTIVE);
            KeyStore keystore = getKeystore(keystoreLocation, keystoreProvider,
                    password);
            if (keystore == null) {
                error(
                        "Cannot find keystore to sign bundle: location=%s,  provider=%s",
                        keystoreLocation, keystoreProvider);
            } else {
                if (signpassword == null && !"-none".equals(signpassword))
                    signpassword = password;

                X509Certificate chain[] = getChain(keystore, alias);
                if (chain == null) {
                    error(
                            "Trying to sign bundle but no signing certificate found: %s",
                            alias);
                    continue;
                }

                try {
                    Key key = keystore.getKey(alias,
                            (signpassword == null ? null : signpassword
                                    .toCharArray()));
                    KeyFactory keyFactory = KeyFactory.getInstance(key
                            .getAlgorithm());
                    KeySpec keySpec = keyFactory.getKeySpec(key,
                            RSAPrivateKeySpec.class);
                    PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

                    JarSigner signer = new JarSigner(alias, privateKey, chain);
                    signer.signJar(jar);

                } catch (UnrecoverableKeyException uke) {
                    error(
                            "Cannot get key to sign, likely invalid password: %s, for %s : %s",
                            signpassword, alias, uke);
                }
            }
        }
    }

    X509Certificate[] getChain(KeyStore keystore, String alias)
            throws Exception {
        java.security.cert.Certificate[] chain = keystore
                .getCertificateChain(alias);
        X509Certificate certChain[] = new X509Certificate[chain.length];

        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        for (int count = 0; count < chain.length; count++) {
            ByteArrayInputStream certIn = new ByteArrayInputStream(chain[count]
                    .getEncoded());
            X509Certificate cert = (X509Certificate) cf
                    .generateCertificate(certIn);
            certChain[count] = cert;
        }
        return certChain;
    }

    KeyStore getKeystore(String keystoreLocation, String keystoreProvider,
            String password) throws Exception {
        if (keystoreLocation == null) {
            return getKeystore();
        }
        if (keystoreProvider == null)
            keystoreProvider = "JKS";

        KeyStore keystore = KeyStore.getInstance(keystoreProvider);
        FileInputStream in = new FileInputStream(keystoreLocation);
        try {
            keystore.load(in, password == null ? null : password.toCharArray());
        } finally {
            in.close();
        }
        return keystore;
    }

    KeyStore getKeystore() throws Exception {
        if (keystore != null) {
            return keystore;
        }

        Map<String, Map<String, String>> header = parseHeader(getProperty(
                "-keystore", "../cnf/keystore"));
        if (header.size() == 0) {
            error("Keystore needed but no -keystore specified");
            return null;
        }

        if (header.size() > 1) {
            warning("Multiple keystores specified, can only specify one: %s",
                    header);
        }
        for (Map.Entry<String, Map<String, String>> entry : header.entrySet()) {
            return keystore = getKeystore(entry.getKey(), entry.getValue().get(
                    "provider:"), entry.getValue().get("password:"));
        }
        return null;
    }

    public boolean hasSources() {
        return isTrue(getProperty(SOURCES));
    }

    protected String getImportPackages() {
        String ip = super.getImportPackages();
        if (ip != null)
            return ip;

        return "*";
    }

    private void doConditional(Jar dot) throws IOException {
        Map<String, Map<String, String>> conditionals = getHeader(CONDITIONAL_PACKAGE);
        int size;
        do {
            size = dot.getDirectories().size();
            analyze();
            analyzed = false;
            Map<String, Map<String, String>> imports = getImports();

            // Match the packages specified in conditionals
            // against the imports. Any match must become a
            // Private-Package
            Map<String, Map<String, String>> filtered = merge(
                    CONDITIONAL_PACKAGE, conditionals, imports,
                    new HashSet<String>(), null);

            // Imports can also specify a private import. These
            // packages must also be copied to the bundle
            for (Map.Entry<String, Map<String, String>> entry : getImports()
                    .entrySet()) {
                String type = entry.getValue().get("import:");
                if (type != null && type.equals("private"))
                    filtered.put(entry.getKey(), entry.getValue());
            }

            // remove existing packages to prevent merge errors
            filtered.keySet().removeAll(dot.getPackages());
            doExpand(dot, CONDITIONAL_PACKAGE + " Private imports",
                    replaceWitInstruction(filtered, CONDITIONAL_PACKAGE), false);
        } while (dot.getDirectories().size() > size);
        analyzed = true;
    }

    /**
     * Intercept the call to analyze and cleanup versions after we have analyzed
     * the setup. We do not want to cleanup if we are going to verify.
     */

    public void analyze() throws IOException {
        super.analyze();
        cleanupVersion(imports);
        cleanupVersion(exports);
        String version = getProperty(BUNDLE_VERSION);
        if (version != null)
            setProperty(BUNDLE_VERSION, cleanupVersion(version));
    }

    public void cleanupVersion(Map<String, Map<String, String>> mapOfMap) {
        for (Iterator<Map.Entry<String, Map<String, String>>> e = mapOfMap
                .entrySet().iterator(); e.hasNext();) {
            Map.Entry<String, Map<String, String>> entry = e.next();
            Map<String, String> attributes = entry.getValue();
            if (attributes.containsKey("version")) {
                attributes.put("version", cleanupVersion(attributes
                        .get("version")));
            }
        }
    }

    /**
     * 
     */
    private void addSources(Jar dot) {
        if (!hasSources())
            return;

        Set<String> packages = new HashSet<String>();

        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            getProperties().store(out, "Generated by BND, at " + new Date());
            dot.putResource("OSGI-OPT/bnd.bnd", new EmbeddedResource(out
                    .toByteArray(), 0));
            out.close();
        } catch (Exception e) {
            error("Can not embed bnd file in JAR: " + e);
        }

        for (Iterator<String> cpe = classspace.keySet().iterator(); cpe
                .hasNext();) {
            String path = cpe.next();
            path = path.substring(0, path.length() - ".class".length())
                    + ".java";
            String pack = getPackage(path).replace('.', '/');
            if (pack.length() > 1)
                pack = pack + "/";
            boolean found = false;
            String[] fixed = { "packageinfo", "package.html",
                    "module-info.java", "package-info.java" };
            for (Iterator<File> i = getSourcePath().iterator(); i.hasNext();) {
                File root = i.next();
                File f = getFile(root, path);
                if (f.exists()) {
                    found = true;
                    if (!packages.contains(pack)) {
                        packages.add(pack);
                        File bdir = getFile(root, pack);
                        for (int j = 0; j < fixed.length; j++) {
                            File ff = getFile(bdir, fixed[j]);
                            if (ff.isFile()) {
                                dot.putResource("OSGI-OPT/src/" + pack
                                        + fixed[j], new FileResource(ff));
                            }
                        }
                    }
                    dot
                            .putResource("OSGI-OPT/src/" + path,
                                    new FileResource(f));
                }
            }
            if (!found) {
                for (Jar jar : classpath) {
                    Resource resource = jar.getResource(path);
                    if (resource != null) {
                        dot.putResource("OSGI-OPT/src", resource);
                    } else {
                        resource = jar.getResource("OSGI-OPT/src/" + path);
                        if (resource != null) {
                            dot.putResource("OSGI-OPT/src", resource);
                        }
                    }
                }
            }
            if (getSourcePath().isEmpty())
                warning("Including sources but " + SOURCEPATH
                        + " does not contain any source directories ");
            // TODO copy from the jars where they came from
        }
    }

    boolean firstUse = true;

    public Collection<File> getSourcePath() {
        if (firstUse) {
            firstUse = false;
            String sp = getProperty(SOURCEPATH);
            if (sp != null) {
                Map<String, Map<String, String>> map = parseHeader(sp);
                for (Iterator<String> i = map.keySet().iterator(); i.hasNext();) {
                    String file = i.next();
                    if (!isDuplicate(file)) {
                        File f = getFile(file);
                        if (!f.isDirectory()) {
                            error("Adding a sourcepath that is not a directory: "
                                    + f);
                        } else {
                            sourcePath.add(f);
                        }
                    }
                }
            }
        }
        return sourcePath;
    }

    private void doVerify(Jar dot) throws Exception {
        Verifier verifier = new Verifier(dot, getProperties());
        verifier.setPedantic(isPedantic());

        // Give the verifier the benefit of our analysis
        // prevents parsing the files twice
        verifier.setClassSpace(classspace, contained, referred, uses);
        verifier.verify();
        getInfo(verifier);
    }

    private void doExpand(Jar jar) throws IOException {
        if (getClasspath().size() == 0
                && (getProperty(EXPORT_PACKAGE) != null || getProperty(PRIVATE_PACKAGE) != null))
            warning("Classpath is empty. Private-Package and Export-Package can only expand from the classpath when there is one");

        Map<Instruction, Map<String, String>> all = newMap();

        all.putAll(replaceWitInstruction(getHeader(PRIVATE_PACKAGE),
                PRIVATE_PACKAGE));

        all.putAll(replaceWitInstruction(getHeader(EXPORT_PACKAGE),
                EXPORT_PACKAGE));

        if (isTrue(getProperty(Constants.UNDERTEST))) {
            all.putAll(replaceWitInstruction(parseHeader(getProperty(
                    Constants.TESTPACKAGES, "test;presence:=optional")),
                    TESTPACKAGES));
        }

        if (all.isEmpty() && !isResourceOnly()) {
            warning("Neither Export-Package, Private-Package, -testpackages is set, therefore no packages will be included");
        }

        doExpand(jar, "Export-Package, Private-Package, or -testpackages", all,
                true);
    }

    /**
     * 
     * @param jar
     * @param name
     * @param instructions
     */
    private void doExpand(Jar jar, String name,
            Map<Instruction, Map<String, String>> instructions,
            boolean mandatory) {
        Set<Instruction> superfluous = removeMarkedDuplicates(instructions
                .keySet());

        for (Iterator<Jar> c = getClasspath().iterator(); c.hasNext();) {
            Jar now = c.next();
            doExpand(jar, instructions, now, superfluous);
        }

        if (mandatory && superfluous.size() > 0) {
            StringBuffer sb = new StringBuffer();
            String del = "Instructions in " + name + " that are never used: ";
            for (Iterator<Instruction> i = superfluous.iterator(); i.hasNext();) {
                Instruction p = i.next();
                sb.append(del);
                sb.append(p.getPattern());
                del = ", ";
            }
            warning(sb.toString());
        }
    }

    /**
     * Iterate over each directory in the class path entry and check if that
     * directory is a desired package.
     * 
     * @param included
     * @param classpathEntry
     */
    private void doExpand(Jar jar,
            Map<Instruction, Map<String, String>> included, Jar classpathEntry,
            Set<Instruction> superfluous) {

        loop: for (Map.Entry<String, Map<String, Resource>> directory : classpathEntry
                .getDirectories().entrySet()) {
            String path = directory.getKey();

            if (doNotCopy.matcher(getName(path)).matches())
                continue;

            if (directory.getValue() == null)
                continue;

            String pack = path.replace('/', '.');
            Instruction instr = matches(included, pack, superfluous);
            if (instr != null) {
                // System.out.println("Pattern match: " + pack + " " +
                // instr.getPattern() + " " + instr.isNegated());
                if (!instr.isNegated()) {
                    Map<String, Resource> contents = directory.getValue();

                    // What to do with split packages? Well if this
                    // directory already exists, we will check the strategy
                    // and react accordingly.
                    boolean overwriteResource = true;
                    if (jar.hasDirectory(path)) {
                        Map<String, String> directives = included.get(instr);

                        switch (getSplitStrategy((String) directives
                                .get(SPLIT_PACKAGE_DIRECTIVE))) {
                        case SPLIT_MERGE_LAST:
                            overwriteResource = true;
                            break;

                        case SPLIT_MERGE_FIRST:
                            overwriteResource = false;
                            break;

                        case SPLIT_ERROR:
                            error(diagnostic(pack, getClasspath(),
                                    classpathEntry.source));
                            continue loop;

                        case SPLIT_FIRST:
                            continue loop;

                        default:
                            warning(diagnostic(pack, getClasspath(),
                                    classpathEntry.source));
                            overwriteResource = false;
                            break;
                        }
                    }

                    jar.addDirectory(contents, overwriteResource);

                    String key = path + "/bnd.info";
                    Resource r = jar.getResource(key);
                    if (r != null)
                        jar.putResource(key, new PreprocessResource(this, r));

                    if (hasSources()) {
                        String srcPath = "OSGI-INF/src/" + path;
                        Map<String, Resource> srcContents = classpathEntry
                                .getDirectories().get(srcPath);
                        if (srcContents != null) {
                            jar.addDirectory(srcContents, overwriteResource);
                        }
                    }
                }
            }
        }
    }

    /**
     * Analyze the classpath for a split package
     * 
     * @param pack
     * @param classpath
     * @param source
     * @return
     */
    private String diagnostic(String pack, List<Jar> classpath, File source) {
        // Default is like merge-first, but with a warning
        // Find the culprits
        pack = pack.replace('.', '/');
        List<Jar> culprits = new ArrayList<Jar>();
        for (Iterator<Jar> i = classpath.iterator(); i.hasNext();) {
            Jar culprit = (Jar) i.next();
            if (culprit.getDirectories().containsKey(pack)) {
                culprits.add(culprit);
            }
        }
        return "Split package "
                + pack
                + "\nUse directive -split-package:=(merge-first|merge-last|error|first) on Export/Private Package instruction to get rid of this warning\n"
                + "Package found in   " + culprits + "\n"
                + "Reference from     " + source + "\n" + "Classpath          "
                + classpath;
    }

    private int getSplitStrategy(String type) {
        if (type == null)
            return SPLIT_DEFAULT;

        if (type.equals("merge-last"))
            return SPLIT_MERGE_LAST;

        if (type.equals("merge-first"))
            return SPLIT_MERGE_FIRST;

        if (type.equals("error"))
            return SPLIT_ERROR;

        if (type.equals("first"))
            return SPLIT_FIRST;

        error("Invalid strategy for split-package: " + type);
        return SPLIT_DEFAULT;
    }

    private Map<Instruction, Map<String, String>> replaceWitInstruction(
            Map<String, Map<String, String>> header, String type) {
        Map<Instruction, Map<String, String>> map = newMap();
        for (Iterator<Map.Entry<String, Map<String, String>>> e = header
                .entrySet().iterator(); e.hasNext();) {
            Map.Entry<String, Map<String, String>> entry = e.next();
            String pattern = entry.getKey();
            Instruction instr = Instruction.getPattern(pattern);
            String presence = entry.getValue().get(PRESENCE_DIRECTIVE);
            if ("optional".equals(presence))
                instr.setOptional();
            map.put(instr, entry.getValue());
        }
        return map;
    }

    private Instruction matches(
            Map<Instruction, Map<String, String>> instructions, String pack,
            Set<Instruction> superfluousPatterns) {
        for (Instruction pattern : instructions.keySet()) {
            if (pattern.matches(pack)) {
                superfluousPatterns.remove(pattern);
                return pattern;
            }
        }
        return null;
    }

    private Map<String, Map<String, String>> getHeader(String string) {
        if (string == null)
            return Collections.emptyMap();
        return parseHeader(getProperty(string));
    }

    /**
     * Parse the Bundle-Includes header. Files in the bundles Include header are
     * included in the jar. The source can be a directory or a file.
     * 
     * @throws IOException
     * @throws FileNotFoundException
     */
    private void doIncludeResources(Jar jar) throws Exception {
        String includes = getProperty("Bundle-Includes");
        if (includes == null) {
            includes = getProperty(INCLUDERESOURCE);
            if ( includes == null )
                includes = getProperty("Include-Resource");
        }
        else
            warning("Please use -includeresource instead of Bundle-Includes");

        if (includes == null)
            return;

        Map<String, Map<String, String>> clauses = parseHeader(includes);

        for (Iterator<Map.Entry<String, Map<String, String>>> i = clauses
                .entrySet().iterator(); i.hasNext();) {
            Map.Entry<String, Map<String, String>> entry = i.next();
            doIncludeResource(jar, entry.getKey(), entry.getValue());
        }
    }

    private void doIncludeResource(Jar jar, String name,
            Map<String, String> extra) throws ZipException, IOException,
            Exception {
        boolean preprocess = false;
        if (name.startsWith("{") && name.endsWith("}")) {
            preprocess = true;
            name = name.substring(1, name.length() - 1).trim();
        }

        if (name.startsWith("@")) {
            extractFromJar(jar, name.substring(1));
        } else
        /*
         * NEW
         */
        if (extra.containsKey("literal")) {
            String literal = (String) extra.get("literal");
            Resource r = new EmbeddedResource(literal.getBytes("UTF-8"), 0);
            String x = (String) extra.get("extra");
            if (x != null)
                r.setExtra(x);
            jar.putResource(name, r);
        } else {
            String source;
            File sourceFile;
            String destinationPath;

            String parts[] = name.split("\\s*=\\s*");
            if (parts.length == 1) {
                // Just a copy, destination path defined by
                // source path.
                source = parts[0];
                sourceFile = getFile(source);
                // Directories should be copied to the root
                // but files to their file name ...
                if (sourceFile.isDirectory())
                    destinationPath = "";
                else
                    destinationPath = sourceFile.getName();
            } else {
                source = parts[1];
                sourceFile = getFile(source);
                destinationPath = parts[0];
            }

            // Some people insist on ending a directory with
            // a slash ... it now also works if you do /=dir
            if (destinationPath.endsWith("/"))
                destinationPath = destinationPath.substring(0, destinationPath
                        .length() - 1);

            if (!sourceFile.exists()) {
                noSuchFile(jar, name, extra, source, destinationPath);
            } else
                copy(jar, destinationPath, sourceFile, preprocess, extra);
        }
    }

    private void noSuchFile(Jar jar, String clause, Map<String, String> extra,
            String source, String destinationPath) throws Exception {
        Jar src = getJarFromName(source, "Include-Resource " + source);
        if (src != null) {
            JarResource jarResource = new JarResource(src);
            jar.putResource(destinationPath, jarResource);
        } else {
            Resource lastChance = make.process(source);
            if (lastChance != null) {
                jar.putResource(destinationPath, lastChance);
            } else
                error("Input file does not exist: " + source);
        }
    }

    /**
     * Extra resources from a Jar and add them to the given jar. The clause is
     * the
     * 
     * @param jar
     * @param clauses
     * @param i
     * @throws ZipException
     * @throws IOException
     */
    private void extractFromJar(Jar jar, String name) throws ZipException,
            IOException {
        // Inline all resources and classes from another jar
        // optionally appended with a modified regular expression
        // like @zip.jar!/META-INF/MANIFEST.MF
        int n = name.lastIndexOf("!/");
        Pattern filter = null;
        if (n > 0) {
            String fstring = name.substring(n + 2);
            name = name.substring(0, n);
            filter = wildcard(fstring);
        }
        Jar sub = getJarFromName(name, "extract from jar");
        if (sub == null)
            error("Can not find JAR file " + name);
        else
            jar.addAll(sub, filter);
    }

    private Pattern wildcard(String spec) {
        StringBuffer sb = new StringBuffer();
        for (int j = 0; j < spec.length(); j++) {
            char c = spec.charAt(j);
            switch (c) {
            case '.':
                sb.append("\\.");
                break;

            case '*':
                // test for ** (all directories)
                if (j < spec.length() - 1 && spec.charAt(j + 1) == '*') {
                    sb.append(".*");
                    j++;
                } else
                    sb.append("[^/]*");
                break;
            default:
                sb.append(c);
                break;
            }
        }
        String s = sb.toString();
        try {
            return Pattern.compile(s);
        } catch (Exception e) {
            error("Invalid regular expression on wildcarding: " + spec
                    + " used *");
        }
        return null;
    }

    private void copy(Jar jar, String path, File from, boolean preprocess,
            Map<String, String> extra) throws Exception {
        if (doNotCopy.matcher(from.getName()).matches())
            return;

        if (from.isDirectory()) {
            String next = path;
            if (next.length() != 0)
                next += '/';

            File files[] = from.listFiles();
            for (int i = 0; i < files.length; i++) {
                copy(jar, next + files[i].getName(), files[i], preprocess,
                        extra);
            }
        } else {
            if (from.exists()) {
                Resource resource = new FileResource(from);
                if (preprocess) {
                    resource = new PreprocessResource(this, resource);
                }
                jar.putResource(path, resource);
            } else {
                error("Input file does not exist: " + from);
            }
        }
    }

    private String getName(String where) {
        int n = where.lastIndexOf('/');
        if (n < 0)
            return where;

        return where.substring(n + 1);
    }

    public void setSourcepath(File[] files) {
        for (int i = 0; i < files.length; i++)
            addSourcepath(files[i]);
    }

    public void addSourcepath(File cp) {
        if (!cp.exists())
            warning("File on sourcepath that does not exist: " + cp);

        sourcePath.add(cp);
    }

    /**
     * Create a POM reseource for Maven containing as much information as
     * possible from the manifest.
     * 
     * @param output
     * @param builder
     * @throws FileNotFoundException
     * @throws IOException
     */
    public void doPom(Jar dot) throws FileNotFoundException, IOException {
        {
            Manifest manifest = dot.getManifest();
            String name = manifest.getMainAttributes().getValue(
                    Analyzer.BUNDLE_NAME);
            String description = manifest.getMainAttributes().getValue(
                    Analyzer.BUNDLE_DESCRIPTION);
            String docUrl = manifest.getMainAttributes().getValue(
                    Analyzer.BUNDLE_DOCURL);
            String version = manifest.getMainAttributes().getValue(
                    Analyzer.BUNDLE_VERSION);
            String bundleVendor = manifest.getMainAttributes().getValue(
                    Analyzer.BUNDLE_VENDOR);
            ByteArrayOutputStream s = new ByteArrayOutputStream();
            PrintStream ps = new PrintStream(s);
            String bsn = manifest.getMainAttributes().getValue(
                    Analyzer.BUNDLE_SYMBOLICNAME);
            String licenses = manifest.getMainAttributes().getValue(
                    BUNDLE_LICENSE);

            if (bsn == null) {
                error("Can not create POM unless Bundle-SymbolicName is set");
                return;
            }

            bsn = bsn.trim();
            int n = bsn.lastIndexOf('.');
            if (n <= 0) {
                error("Can not create POM unless Bundle-SymbolicName contains a .");
                ps.close();
                s.close();
                return;
            }
            String groupId = bsn.substring(0, n);
            String artifactId = bsn.substring(n + 1);
            ps
                    .println("<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'>");
            ps.println("  <modelVersion>4.0.0</modelVersion>");
            ps.println("  <groupId>" + groupId + "</groupId>");

            n = artifactId.indexOf(';');
            if (n > 0)
                artifactId = artifactId.substring(0, n).trim();

            ps.println("  <artifactId>" + artifactId + "</artifactId>");
            ps.println("  <version>" + version + "</version>");
            if (description != null) {
                ps.println("  <description>");
                ps.print("    ");
                ps.println(description);
                ps.println("  </description>");
            }
            if (name != null) {
                ps.print("  <name>");
                ps.print(name);
                ps.println("</name>");
            }
            if (docUrl != null) {
                ps.print("  <url>");
                ps.print(docUrl);
                ps.println("</url>");
            }

            if (bundleVendor != null) {
                Matcher m = NAME_URL.matcher(bundleVendor);
                String namePart = bundleVendor;
                String urlPart = null;
                if (m.matches()) {
                    namePart = m.group(1);
                    urlPart = m.group(2);
                }
                ps.println("  <organization>");
                ps.print("    <name>");
                ps.print(namePart.trim());
                ps.println("</name>");
                if (urlPart != null) {
                    ps.print("    <url>");
                    ps.print(urlPart.trim());
                    ps.println("</url>");
                }
                ps.println("  </organization>");
            }
            if (licenses != null) {
                ps.println("  <licenses>");
                Map<String, Map<String, String>> map = parseHeader(licenses);
                for (Iterator<Map.Entry<String, Map<String, String>>> e = map
                        .entrySet().iterator(); e.hasNext();) {
                    Map.Entry<String, Map<String, String>> entry = e.next();
                    ps.println("    <license>");
                    Map<String, String> values = entry.getValue();
                    print(ps, values, "name", "name", (String) values
                            .get("url"));
                    print(ps, values, "url", "url", null);
                    print(ps, values, "distribution", "distribution", "repo");
                    ps.println("    </license>");
                }
                ps.println("  </licenses>");
            }
            ps.println("</project>");
            ps.close();
            s.close();
            dot
                    .putResource("pom.xml", new EmbeddedResource(s
                            .toByteArray(), 0));
        }
    }

    /**
     * Utility function to print a tag from a map
     * 
     * @param ps
     * @param values
     * @param string
     * @param tag
     * @param object
     */
    private void print(PrintStream ps, Map<String, String> values,
            String string, String tag, String object) {
        String value = (String) values.get(string);
        if (value == null)
            value = object;
        if (value == null)
            return;
        ps.println("    <" + tag + ">" + value.trim() + "</" + tag + ">");
    }

    public void close() {
        super.close();
    }

    /**
     * Build Multiple jars. If the -sub command is set, we filter the file with
     * the given patterns.
     * 
     * @return
     * @throws Exception
     */
    public Jar[] builds() throws Exception {
        begin();

        // Are we acting as a conduit for another JAR?
        String conduit = getProperty(CONDUIT);
        if (conduit != null) {
            Map<String, Map<String, String>> map = parseHeader(conduit);
            Jar[] result = new Jar[map.size()];
            int n = 0;
            for (String file : map.keySet()) {
                Jar c = new Jar(getFile(file));
                addClose(c);
                String name = map.get(file).get("name");
                if (name != null)
                    c.setName(name);

                result[n++] = c;
            }
            return result;
        }

        // If no -sub property, then reuse this builder object
        // other wise, build all the sub parts.
        String sub = getProperty(SUB);
        if (sub == null) {
            Jar jar = build();
            if (jar == null)
                return new Jar[0];

            return new Jar[] { jar };
        }

        List<Jar> result = new ArrayList<Jar>();

        // Get the Instruction objects that match the sub header
        Set<Instruction> subs = replaceWitInstruction(parseHeader(sub), SUB)
                .keySet();

        // Get the member files of this directory
        List<File> members = new ArrayList<File>(Arrays.asList(getBase()
                .listFiles()));

        getProperties().remove(SUB);
        // For each member file
        nextFile: while (members.size() > 0) {

            File file = members.remove(0);
            if (file.equals(getPropertiesFile()))
                continue nextFile;

            for (Iterator<Instruction> i = subs.iterator(); i.hasNext();) {

                Instruction instruction = i.next();
                if (instruction.matches(file.getName())) {

                    if (!instruction.isNegated()) {

                        Builder builder = null;
                        try {
                            builder = getSubBuilder();
                            addClose(builder);
                            builder.setProperties(file);
                            builder.setProperty(SUB, "");
                            // Recursively build
                            // TODO
                            Jar jar = builder.build();
                            jar.setName(builder.getBsn());
                            result.add(jar);
                        } catch (Exception e) {
                            e.printStackTrace();
                            error("Sub Building " + file, e);
                        }
                        if (builder != null)
                            getInfo(builder, file.getName() + ": ");
                    }

                    // Because we matched (even though we could be negated)
                    // we skip any remaining searches
                    continue nextFile;
                }
            }
        }
        setProperty(SUB, sub);
        return result.toArray(new Jar[result.size()]);
    }

    protected Builder getSubBuilder() throws Exception {
        return new Builder(this);
    }

    /**
     * A macro to convert a maven version to an OSGi version
     */

    public String _maven_version(String args[]) {
        if (args.length > 2)
            error("${maven_version} macro receives too many arguments "
                    + Arrays.toString(args));
        else if (args.length < 2)
            error("${maven_version} macro has no arguments, use ${maven_version;1.2.3-SNAPSHOT}");
        else {
            return cleanupVersion(args[1]);
        }
        return null;
    }

    public String _permissions(String args[]) throws IOException {
        StringBuilder sb = new StringBuilder();

        for (String arg : args) {
            if ("packages".equals(arg) || "all".equals(arg)) {
                for (String imp : getImports().keySet()) {
                    if (!imp.startsWith("java.")) {
                        sb.append("(org.osgi.framework.PackagePermission \"");
                        sb.append(imp);
                        sb.append("\" \"import\")\r\n");
                    }
                }
                for (String exp : getExports().keySet()) {
                    sb.append("(org.osgi.framework.PackagePermission \"");
                    sb.append(exp);
                    sb.append("\" \"export\")\r\n");
                }
            } else if ("admin".equals(arg) || "all".equals(arg)) {
                sb.append("(org.osgi.framework.AdminPermission)");
            } else if ("permissions".equals(arg))
                ;
            else
                error("Invalid option in ${permissions}: %s", arg);
        }
        return sb.toString();
    }

}
