/* 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.util.*;
import java.util.jar.*;
import java.util.regex.*;
import java.util.zip.*;

/**
 * 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                     tempJars          = new ArrayList();
    boolean                  sources           = false;
    File[]                   sourcePath;
    Pattern                  NAME_URL          = Pattern
                                                       .compile("(.*)(http://.*)");

    public Jar build() throws Exception {
        begin();

        dot = new Jar("dot");
        doPrebuild(dot, parseHeader(getProperty("-prebuild")));
        doExpand(dot);
        doIncludeResources(dot);

        doConditional(dot);

        dot.setManifest(calcManifest());
        // 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());
        return dot;
    }

    void begin() {
        super.begin();
        if (getProperty(IMPORT_PACKAGE) == null)
            setProperty(IMPORT_PACKAGE, "*");

        sources = getProperty(SOURCES) != null;
    }

    private void doConditional(Jar dot) throws IOException {
        Map conditionals = getHeader(CONDITIONAL_PACKAGE);
        if (conditionals != null && conditionals.size() > 0) {
            int size;
            do {
                size = dot.getDirectories().size();
                analyze();
                analyzed = false;
                Map imports = getImports();

                Map filtered = merge(CONDITIONAL_PACKAGE, conditionals,
                        imports, new HashSet());

                // remove existing packages to prevent merge errors
                filtered.keySet().removeAll(dot.getPackages());
                filtered = replaceWithPattern(filtered);
                doExpand(dot, CONDITIONAL_PACKAGE, filtered);
            } while (dot.getDirectories().size() > size);
        }
    }

    /**
     * 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 mapOfMap) {
        for (Iterator e = mapOfMap.entrySet().iterator(); e.hasNext();) {
            Map.Entry entry = (Map.Entry) e.next();
            Map attributes = (Map) entry.getValue();
            if (attributes.containsKey("version")) {
                attributes.put("version", cleanupVersion((String) attributes
                        .get("version")));
            }
        }
    }

    /**
     * Clean up version parameters. Other builders use more fuzzy definitions of
     * the version syntax. This method cleans up such a version to match an OSGi
     * version.
     * 
     * @param version
     * @return
     */
    static Pattern fuzzyVersion  = Pattern
                                         .compile(
                                                 "(\\d+)(\\.(\\d+)(\\.(\\d+))?)?([^a-zA-Z0-9](.*))?",
                                                 Pattern.DOTALL);
    static Pattern fuzzyModifier = Pattern.compile("(\\d+[.-])*(.*)",
                                         Pattern.DOTALL);

    static Pattern nummeric      = Pattern.compile("\\d*");

    static public String cleanupVersion(String version) {
        Matcher m = fuzzyVersion.matcher(version);
        if (m.matches()) {
            StringBuffer result = new StringBuffer();
            String d1 = m.group(1);
            String d2 = m.group(3);
            String d3 = m.group(5);
            String qualifier = m.group(7);

            if (d1 != null) {
                result.append(d1);
                if (d2 != null) {
                    result.append(".");
                    result.append(d2);
                    if (d3 != null) {
                        result.append(".");
                        result.append(d3);
                        if (qualifier != null) {
                            result.append(".");
                            cleanupModifier(result, qualifier);
                        }
                    } else if (qualifier != null) {
                        result.append(".0.");
                        cleanupModifier(result, qualifier);
                    }
                } else if (qualifier != null) {
                    result.append(".0.0.");
                    cleanupModifier(result, qualifier);
                }
                return result.toString();
            }
        }
        return version;
    }

    static void cleanupModifier(StringBuffer result, String modifier) {
        Matcher m = fuzzyModifier.matcher(modifier);
        if (m.matches())
            modifier = m.group(2);

        for (int i = 0; i < modifier.length(); i++) {
            char c = modifier.charAt(i);
            if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')
                    || (c >= 'A' && c <= 'Z') || c == '_' || c == '-')
                result.append(c);
        }
    }

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

        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 cpe = classspace.keySet().iterator(); cpe.hasNext();) {
            String path = (String) cpe.next();
            path = path.substring(0, path.length() - ".class".length())
                    + ".java";

            for (int i = 0; i < sourcePath.length; i++) {
                File root = sourcePath[i];
                File f = getFile(root, path);
                if (f.exists()) {
                    dot
                            .putResource("OSGI-OPT/src/" + path,
                                    new FileResource(f));
                }
            }
        }
    }

    private void doVerify(Jar dot) throws Exception {
        Verifier verifier = new Verifier(dot, getProperties());
        verifier.setPedantic(isPedantic());
        verifier.verify();
        errors.addAll(verifier.getErrors());
        warnings.addAll(verifier.getWarnings());
    }

    private void doExpand(Jar jar) throws IOException {
        if (classpath.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 prive = replaceWithPattern(getHeader(Analyzer.PRIVATE_PACKAGE));
        Map export = replaceWithPattern(getHeader(Analyzer.EXPORT_PACKAGE));
        if (prive.isEmpty() && export.isEmpty()) {
            warnings
                    .add("Neither Export-Package nor Private-Package is set, therefore no packages will be included");
        }
        doExpand(jar, EXPORT_PACKAGE, export);
        doExpand(jar, PRIVATE_PACKAGE, prive);
    }

    private void doExpand(Jar jar, String name, Map instructions) {
        Set superfluous = new HashSet(instructions.keySet());
        for (Iterator c = classpath.iterator(); c.hasNext();) {
            Jar now = (Jar) c.next();
            doExpand(jar, instructions, now, superfluous);
        }
        if (superfluous.size() > 0) {
            StringBuffer sb = new StringBuffer();
            String del = "Instructions for " + name + " that are never used: ";
            for (Iterator i = superfluous.iterator(); i.hasNext();) {
                Instruction p = (Instruction) 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 included, Jar classpathEntry,
            Set superfluous) {

        loop: for (Iterator p = classpathEntry.getDirectories().entrySet()
                .iterator(); p.hasNext();) {
            Map.Entry directory = (Map.Entry) p.next();
            String path = (String) 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 contents = (Map) 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 directives = (Map) 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("Split package generates error: " + pack);
                            continue loop;

                        case SPLIT_FIRST:
                            continue loop;

                        default:
                            // Default is like merge-first, but with a warning
                            warning("There are split packages, use directive -split-package:=(merge-first|merge-last) on instruction to get rid of this warning: "
                                    + pack
                                    + ", classpath: "
                                    + classpath
                                    + " from: " + classpathEntry.source);
                            overwriteResource = false;
                            break;
                        }
                    }
                    jar.addDirectory(contents, overwriteResource);
                }
            }
        }
    }

    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 replaceWithPattern(Map header) {
        Map map = new LinkedHashMap();
        for (Iterator e = header.entrySet().iterator(); e.hasNext();) {
            Map.Entry entry = (Map.Entry) e.next();
            String pattern = (String) entry.getKey();
            Instruction instr = Instruction.getPattern(pattern);
            map.put(instr, entry.getValue());
        }
        return map;
    }

    private Instruction matches(Map instructions, String pack,
            Set superfluousPatterns) {
        for (Iterator i = instructions.keySet().iterator(); i.hasNext();) {
            Instruction pattern = (Instruction) i.next();
            if (pattern.matches(pack)) {
                superfluousPatterns.remove(pattern);
                return pattern;
            }
        }
        return null;
    }

    private Map getHeader(String string) {
        if (string == null)
            return new LinkedHashMap();
        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 {
        Macro macro = new Macro(getProperties(), this);

        String includes = getProperty("Bundle-Includes");
        if (includes == null)
            includes = getProperty("Include-Resource");
        else
            warnings
                    .add("Please use Include-Resource instead of Bundle-Includes");

        if (includes == null)
            return;

        for (Iterator i = getClauses(includes).iterator(); i.hasNext();) {
            boolean preprocess = false;
            String clause = (String) i.next();
            if (clause.startsWith("{") && clause.endsWith("}")) {
                preprocess = true;
                clause = clause.substring(1, clause.length() - 1).trim();
            }

            Map extra = new HashMap();
            int n = clause.indexOf(';');
            if (n > 0) {
                String attributes = clause.substring(n + 1);
                String parts[] = attributes.split("\\s*;\\s*");
                for (int j = 0; j < parts.length; j++) {
                    String assignment[] = parts[j].split("\\s*=\\s*");
                    if (assignment.length == 2)
                        extra.put(assignment[0], assignment[1]);
                    else
                        error("Invalid attribute on Include-Resource: "
                                + clause);
                }
                clause = clause.substring(0, n);
            }

            if (clause.startsWith("@")) {
                extractFromJar(jar, clause.substring(1));
            } else {
                String parts[] = clause.split("\\s*=\\s*");

                String source;
                File sourceFile;
                String destinationPath;

                if (parts.length == 1) {
                    // Just a copy, destination path defined by
                    // source path.
                    source = parts[0];
                    sourceFile = getFile(base, 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(base, 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()) {
                    Jar src = getJarFromName(source, "Include-Resource "
                            + source);
                    if (src != null) {
                        JarResource jarResource = new JarResource(src);
                        jar.putResource(destinationPath, jarResource);
                        tempJars.add(src);
                    } else {
                        error("Input file does not exist: " + source);
                    }
                } else
                    copy(jar, destinationPath, sourceFile, preprocess ? macro
                            : null, extra);
            }
        }
    }

    /**
     * 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);
            tempJars.add(sub);
        }
    }

    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, Macro macro, Map 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], macro, extra);
            }
        } else {
            if (from.exists()) {
                if (macro != null) {
                    String content = read(from);
                    content = macro.process(content);
                    Resource resource = new EmbeddedResource(content
                            .getBytes("UTF-8"), from.lastModified());

                    String x = (String) extra.get("extra");
                    if (x != null)
                        resource.setExtra(x);
                    jar.putResource(path, resource);
                } else
                    jar.putResource(path, new FileResource(from));
            } else {
                error("Input file does not exist: " + from);
            }
        }
    }

    private String read(File from) throws Exception {
        long size = from.length();
        byte[] buffer = new byte[(int) size];
        FileInputStream in = new FileInputStream(from);
        in.read(buffer);
        in.close();
        return new String(buffer, "UTF-8");
    }

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

        return where.substring(n + 1);
    }

    public void setSourcepath(File[] files) {
        sourcePath = files;
    }

    /**
     * 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) {
                errors
                        .add("Can not create POM unless Bundle-SymbolicName is set");
                return;
            }

            bsn = bsn.trim();
            int n = bsn.lastIndexOf('.');
            if (n <= 0) {
                errors
                        .add("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 map = parseHeader(licenses);
                for (Iterator e = map.entrySet().iterator(); e.hasNext();) {
                    Map.Entry entry = (Map.Entry) e.next();
                    ps.println("    <license>");
                    Map values = (Map) 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));
        }
    }

    /**
     * NEW
     * 
     */
    void doPrebuild(Jar dot, Map clauses) {
        for (Iterator i = clauses.entrySet().iterator(); i.hasNext();) {
            Map.Entry entry = (Map.Entry) i.next();
            String name = (String) entry.getKey();
            Map args = (Map) entry.getValue();
            File file = getFile(base, name);
            File dir = file.getParentFile();
            if (!dir.exists())
                error("No directory for prebuild: " + file.getAbsolutePath());
            else {
                Instruction instr = Instruction.getPattern(file.getName());
                File[] children = dir.listFiles();
                for (int c = 0; c < children.length; c++) {
                    File child = children[c];
                    if (instr.matches(child.getName()) && !instr.isNegated()) {
                        try {
                            progress("Prebuilding "+child);
                            doPrebuild(dot, child, args);
                        } catch (Exception e) {
                            error("Can not build: "+child);
                        }
                    }
                }
            }
        }
    }

    void doPrebuild(Jar dot, File f, Map args) throws Exception {
        Builder builder = new Builder();
        builder.setBase(base);
        builder.setProperties(f);

        Properties p = new Properties();
        p.putAll(getProperties());
        p.keySet().removeAll(builder.getProperties().keySet());
        builder.getProperties().putAll(p);

        Jar jar = builder.build();
        String path = (String) args.get("path");
        if (path != null)
            path = f.getName();

        dot.putResource(path, new JarResource(jar));
    }

    /**
     * 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 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() {
        for (Iterator j = tempJars.iterator(); j.hasNext();) {
            Jar jar = (Jar) j.next();
            jar.close();
        }
        super.close();
    }
}
