diff --git a/bundleplugin/NOTICE b/bundleplugin/NOTICE
index b12ce4c..5ecb6de 100644
--- a/bundleplugin/NOTICE
+++ b/bundleplugin/NOTICE
@@ -13,6 +13,11 @@
 Copyright 2006-2008 The OSGi Alliance.
 Licensed under the Apache License 2.0.
 
+This product includes software developed by Peter Kriens
+(http://www.aqute.biz/Code/Bnd)
+Copyright 2006-2008 aQute, All rights reserved
+Licensed under the Apache License 2.0.
+
 
 II. Used Software
 
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java b/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
new file mode 100644
index 0000000..1b0f0ad
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
@@ -0,0 +1,769 @@
+/* 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;
+
+    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);
+                    } 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);
+    }
+
+    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() {
+        super.close();
+    }
+}
