diff --git a/bundleplugin/pom.xml b/bundleplugin/pom.xml
index 5181806..20c4c5d 100644
--- a/bundleplugin/pom.xml
+++ b/bundleplugin/pom.xml
@@ -56,7 +56,7 @@
   <dependency>
     <groupId>biz.aQute</groupId>
     <artifactId>bndlib</artifactId>
-    <version>0.0.357</version>
+    <version>1.10.0</version>
   </dependency>
   <dependency>
     <groupId>net.sf.kxml</groupId>
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java b/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
index cb990a1..11c8863 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
@@ -3,1132 +3,1113 @@
 import java.io.*;
 import java.util.*;
 import java.util.jar.*;
-import java.util.regex.*;
 import java.util.zip.*;
 
 import aQute.bnd.make.*;
+import aQute.bnd.maven.*;
 import aQute.bnd.service.*;
 
 /**
  * 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.20 $
+ *
+ * @version $Revision: 1.27 $
  */
 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;
+	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;
 
-    private static final File[] EMPTY_FILE        = new File[0];
+	List<File>					sourcePath			= new ArrayList<File>();
 
-    List<File>                  sourcePath        = new ArrayList<File>();
-    Pattern                     NAME_URL          = Pattern
-                                                          .compile("(.*)(http://.*)");
+	Make						make				= new Make(this);
 
-    Make                        make              = new Make(this);
+	public Builder(Processor parent) {
+		super(parent);
+	}
 
-    public Builder(Processor parent) {
-        super(parent);
-    }
+	public Builder() {
+	}
 
-    public Builder() {
+    public Map<String, Clazz> analyzeBundleClasspath(Jar dot,
+			Map<String, Map<String, String>> bundleClasspath,
+			Map<String, Map<String, String>> contained,
+			Map<String, Map<String, String>> referred,
+			Map<String, Set<String>> uses) throws IOException {
+        return super.analyzeBundleClasspath(dot, bundleClasspath, contained, referred, uses);
     }
 
     public Jar build() throws Exception {
-        if (getProperty(NOPE) != null)
-            return null;
+		init();
+		if (isTrue(getProperty(NOBUNDLES)))
+			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");
 
-        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) {
+		}
 
-        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);
+		dot = doWab(dot);
 
-        doExpand(dot);
-        doIncludeResources(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.
 
-        doConditional(dot);
+		Manifest manifest = calcManifest();
 
-        // NEW!
-        // Check if we override the calculation of the
-        // manifest. We still need to calculated it because
-        // we need to have analyzed the classpath.
+		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);
+			}
+		}
 
-        Manifest manifest = calcManifest();
+		if (getProperty(NOMANIFEST) == null)
+			dot.setManifest(manifest);
+		else
+			dot.setDoNotTouchManifest();
 
-        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);
-            }
-        }
+		// This must happen after we analyzed so
+		// we know what it is on the classpath
+		addSources(dot);
 
-        if (getProperty(NOMANIFEST) == null)
-            dot.setManifest(manifest);
-        else
-            dot.setNoManifest(true);
+		if (getProperty(POM) != null)
+			dot.putResource("pom.xml", new PomResource(dot.getManifest()));
 
-        // This must happen after we analyzed so
-        // we know what it is on the classpath
-        addSources(dot);
-        if (getProperty(POM) != null)
-            doPom(dot);
+		if (!isNoBundle())
+			doVerify(dot);
 
-        doVerify(dot);
+		if (dot.getResources().isEmpty())
+			error("The JAR is empty: " + dot.getName());
 
-        if (dot.getResources().isEmpty())
-            error("The JAR is empty");
+		dot.updateModified(lastModified(), "Last Modified Processor");
+		dot.setName(getBsn());
 
-        dot.updateModified(lastModified(), "Last Modified Processor");
-        dot.setName(getBsn());
+		sign(dot);
 
-        sign(dot);
-        return dot;
-    }
+		doSaveManifest(dot);
+		return dot;
+	}
 
-    /**
-     * Sign the jar file.
-     * 
-     * -sign : <alias> [ ';' 'password:=' <password> ] [ ';' 'keystore:='
-     * <keystore> ] [ ';' 'sign-password:=' <pw> ] ( ',' ... )*
-     * 
-     * @return
+	/**
+	 * Allow any local initialization by subclasses before we build. Default is
+	 * do nothing.
+	 */
+	public void init() throws Exception {
+
+	}
+
+	/**
+	 * Turn this normal bundle in a web and add any resources.
+	 *
+	 * @throws Exception
+	 */
+	private Jar doWab(Jar dot) throws Exception {
+		String wab = getProperty(WAB);
+		String wablib = getProperty(WABLIB);
+		if (wab == null && wablib == null)
+			return dot;
+
+		setProperty(BUNDLE_CLASSPATH, append("WEB-INF/classes", getProperty(BUNDLE_CLASSPATH)));
+
+		Jar next = new Jar(dot.getName());
+		addClose(next);
+
+		for (Map.Entry<String, Resource> entry : dot.getResources().entrySet()) {
+			String path = entry.getKey();
+			if (path.indexOf('/') > 0 && !Character.isUpperCase(path.charAt(0))) {
+				trace("wab: moving: %s", path);
+				next.putResource("WEB-INF/classes/" + path, entry.getValue());
+			} else {
+				trace("wab: not moving: %s", path);
+				next.putResource(path, entry.getValue());
+			}
+		}
+
+		Map<String, Map<String, String>> clauses = parseHeader(getProperty(WABLIB));
+		for (String key : clauses.keySet()) {
+			File f = getFile(key);
+			addWabLib(next, f);
+		}
+		doIncludeResource(next, wab);
+		return next;
+	}
+
+	/**
+	 * Add a wab lib to the jar.
+	 *
+	 * @param f
+	 */
+	private void addWabLib(Jar dot, File f) throws Exception {
+		if (f.exists()) {
+			Jar jar = new Jar(f);
+			jar.setDoNotTouchManifest();
+			addClose(jar);
+			String path = "WEB-INF/lib/" + f.getName();
+			dot.putResource(path, new JarResource(jar));
+			setProperty(BUNDLE_CLASSPATH, append(getProperty(BUNDLE_CLASSPATH), path));
+
+			Manifest m = jar.getManifest();
+			String cp = m.getMainAttributes().getValue("Class-Path");
+			if (cp != null) {
+				Collection<String> parts = split(cp, ",");
+				for (String part : parts) {
+					File sub = getFile(f.getParentFile(), part);
+					if (!sub.exists() || !sub.getParentFile().equals(f.getParentFile())) {
+						warning(
+								"Invalid Class-Path entry %s in %s, must exist and must reside in same directory",
+								sub, f);
+					} else {
+						addWabLib(dot, sub);
+					}
+				}
+			}
+		} else {
+			error("WAB lib does not exist %s", f);
+		}
+	}
+
+	/**
+	 * Get the manifest and write it out separately if -savemanifest is set
+	 *
+	 * @param dot
+	 */
+	private void doSaveManifest(Jar dot) throws IOException {
+		String output = getProperty(SAVEMANIFEST);
+		if (output == null)
+			return;
+
+		File f = getFile(output);
+		if (f.isDirectory()) {
+			f = new File(f, "MANIFEST.MF");
+		}
+		f.delete();
+		f.getParentFile().mkdirs();
+		OutputStream out = new FileOutputStream(f);
+		try {
+			Jar.writeManifest(dot.getManifest(), out);
+		} finally {
+			out.close();
+		}
+		changedFile(f);
+	}
+
+	protected void changedFile(File f) {
+	}
+
+	/**
+	 * 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);
+		List<SignerPlugin> signers = getPlugins(SignerPlugin.class);
+
+		Map<String, Map<String, String>> infos = parseHeader(signing);
+		for (Map.Entry<String, Map<String, String>> entry : infos.entrySet()) {
+			for (SignerPlugin signer : signers) {
+				signer.sign(this, entry.getKey());
+			}
+		}
+	}
+
+	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 Exception {
+		Map<String, Map<String, String>> conditionals = getHeader(CONDITIONAL_PACKAGE);
+		if (conditionals.isEmpty())
+			return;
+
+		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_DIRECTIVE);
+				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", Instruction
+					.replaceWithInstruction(filtered), 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 Exception {
+		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;
 
-    void sign(Jar jar) throws Exception {
-        String signing = getProperty("-sign");
-        if (signing == null)
-            return;
+		Set<String> packages = new HashSet<String>();
 
-        trace("Signing %s, with %s", getBsn(), signing);
-        List<SignerPlugin> signers = getPlugins(SignerPlugin.class);
+		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);
+		}
 
-        Map<String, Map<String, String>> infos = parseHeader(signing);
-        for (Map.Entry<String, Map<String, String>> entry : infos.entrySet()) {
-            for (SignerPlugin signer : signers) {
-                signer.sign(this, entry.getKey());
-            }
-        }
-    }
+		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
+		}
+	}
 
-    public boolean hasSources() {
-        return isTrue(getProperty(SOURCES));
-    }
+	boolean	firstUse	= true;
 
-    protected String getImportPackages() {
-        String ip = super.getImportPackages();
-        if (ip != null)
-            return ip;
+	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;
+	}
 
-        return "*";
-    }
+	private void doVerify(Jar dot) throws Exception {
+		Verifier verifier = new Verifier(dot, getProperties());
+		verifier.setPedantic(isPedantic());
 
-    private void doConditional(Jar dot) throws IOException {
-        Map<String, Map<String, String>> conditionals = getHeader(CONDITIONAL_PACKAGE);
-        if ( conditionals.isEmpty() )
-            return;
-        
-        int size;
-        do {
-            size = dot.getDirectories().size();
-            analyze();
-            analyzed = false;
-            Map<String, Map<String, String>> imports = getImports();
+		// Give the verifier the benefit of our analysis
+		// prevents parsing the files twice
+		verifier.setClassSpace(classspace, contained, referred, uses);
+		verifier.verify();
+		getInfo(verifier);
+	}
 
-            // 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);
+	private void doExpand(Jar jar) throws IOException {
+		if (getClasspath().size() == 0
+				&& (getProperty(EXPORT_PACKAGE) != null || 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");
 
-            // 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_DIRECTIVE);
-                if (type != null && type.equals("private"))
-                    filtered.put(entry.getKey(), entry.getValue());
-            }
+		Map<Instruction, Map<String, String>> privateMap = Instruction
+				.replaceWithInstruction(getHeader(PRIVATE_PACKAGE));
+		Map<Instruction, Map<String, String>> exportMap = Instruction
+				.replaceWithInstruction(getHeader(EXPORT_PACKAGE));
 
-            // 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;
-    }
+		if (isTrue(getProperty(Constants.UNDERTEST))) {
+			privateMap.putAll(Instruction.replaceWithInstruction(parseHeader(getProperty(
+					Constants.TESTPACKAGES, "test;presence:=optional"))));
+		}
+		if (!privateMap.isEmpty())
+			doExpand(jar, "Private-Package, or -testpackages", privateMap, 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.
+		if (!exportMap.isEmpty() ) {
+			Jar exports = new Jar("exports");
+			doExpand(exports, EXPORT_PACKAGE, exportMap, true);
+			jar.addAll(exports);
+			exports.close();
+		}
+
+		if (!isNoBundle()) {
+			if (privateMap.isEmpty() && exportMap.isEmpty() && !isResourceOnly()
+					&& getProperty(EXPORT_CONTENTS) == null) {
+				warning("None of Export-Package, Provide-Package, Private-Package, -testpackages, or -exportcontents is set, therefore no packages will be included");
+			}
+		}
+	}
+
+	/**
+	 *
+	 * @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) {
+			StringBuilder sb = new StringBuilder();
+			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.toString());
+				del = "\n                ";
+			}
+			sb.append("\nClasspath: ");
+			sb.append(Processor.join(getClasspath()));
+			sb.append("\n");
+
+			warning(sb.toString());
+			if (isPedantic())
+				diagnostics = true;
+		}
+	}
+
+	/**
+	 * 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.keySet(), 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-OPT/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 Instruction matches(Collection<Instruction> instructions, String pack,
+			Set<Instruction> superfluousPatterns) {
+		for (Instruction pattern : instructions) {
+			if (pattern.matches(pack)) {
+				if (superfluousPatterns != null)
+					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.length() == 0)
+				includes = getProperty("Include-Resource");
+		} else
+			warning("Please use -includeresource instead of Bundle-Includes");
+
+		doIncludeResource(jar, includes);
+
+	}
+
+	private void doIncludeResource(Jar jar, String includes) throws Exception {
+		Map<String, Map<String, String>> clauses = parseHeader(includes);
+		doIncludeResource(jar, clauses);
+	}
+
+	private void doIncludeResource(Jar jar, Map<String, Map<String, String>> clauses)
+			throws ZipException, IOException, Exception {
+		for (Map.Entry<String, Map<String, String>> entry : clauses.entrySet()) {
+			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();
+		}
+
+		String parts[] = name.split("\\s*=\\s*");
+		String source = parts[0];
+		String destination = parts[0];
+		if (parts.length == 2)
+			source = parts[1];
+
+		if (source.startsWith("@")) {
+			extractFromJar(jar, source.substring(1), parts.length == 1 ? "" : destination);
+		} else 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 {
+			File sourceFile;
+			String destinationPath;
+
+			sourceFile = getFile(source);
+			if (parts.length == 1) {
+				// Directories should be copied to the root
+				// but files to their file name ...
+				if (sourceFile.isDirectory())
+					destinationPath = "";
+				else
+					destinationPath = sourceFile.getName();
+			} else {
+				destinationPath = parts[0];
+			}
+			// Handle directories
+			if (sourceFile.isDirectory()) {
+				destinationPath = doResourceDirectory(jar, extra, preprocess, sourceFile,
+						destinationPath);
+				return;
+			}
+
+			// destinationPath = checkDestinationPath(destinationPath);
+
+			if (!sourceFile.exists()) {
+				noSuchFile(jar, name, extra, source, destinationPath);
+			} else
+				copy(jar, destinationPath, sourceFile, preprocess, extra);
+		}
+	}
+
+	private String doResourceDirectory(Jar jar, Map<String, String> extra, boolean preprocess,
+			File sourceFile, String destinationPath) throws Exception {
+		String filter = extra.get("filter:");
+		boolean flatten = isTrue(extra.get("flatten:"));
+		boolean recursive = true;
+		String directive = extra.get("recursive:");
+		if (directive != null) {
+			recursive = isTrue(directive);
+		}
+
+		InstructionFilter iFilter = null;
+		if (filter != null) {
+			iFilter = new InstructionFilter(Instruction.getPattern(filter), recursive);
+		} else {
+			iFilter = new InstructionFilter(null, recursive);
+		}
+
+		Map<String, File> files = newMap();
+		resolveFiles(sourceFile, iFilter, recursive, destinationPath, files, flatten);
+
+		for (Map.Entry<String, File> entry : files.entrySet()) {
+			copy(jar, entry.getKey(), entry.getValue(), preprocess, extra);
+		}
+		return destinationPath;
+	}
+
+	private void resolveFiles(File dir, FileFilter filter, boolean recursive, String path,
+			Map<String, File> files, boolean flatten) {
+
+		if (Analyzer.doNotCopy.matcher(dir.getName()).matches()) {
+			return;
+		}
+
+		File[] fs = dir.listFiles(filter);
+		for (File file : fs) {
+			if (file.isDirectory()) {
+				if (recursive) {
+					String nextPath;
+					if (flatten)
+						nextPath = path;
+					else
+						nextPath = appendPath(path, file.getName());
+
+					resolveFiles(file, filter, recursive, nextPath, files, flatten);
+				}
+				// Directories are ignored otherwise
+			} else {
+				String p = appendPath(path, file.getName());
+				if (files.containsKey(p))
+					warning("Include-Resource overwrites entry %s from file %s", p, file);
+				files.put(p, file);
+			}
+		}
+	}
+
+	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) {
+				String x = extra.get("extra");
+				if (x != null)
+					lastChance.setExtra(x);
+				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 source, String destination) 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 = source.lastIndexOf("!/");
+		Instruction instr = null;
+		if (n > 0) {
+			instr = Instruction.getPattern(source.substring(n + 2));
+			source = source.substring(0, n);
+		}
+
+		// Pattern filter = null;
+		// if (n > 0) {
+		// String fstring = source.substring(n + 2);
+		// source = source.substring(0, n);
+		// filter = wildcard(fstring);
+		// }
+		Jar sub = getJarFromName(source, "extract from jar");
+		if (sub == null)
+			error("Can not find JAR file " + source);
+		else {
+			jar.addAll(sub, instr, destination);
+		}
+	}
+
+	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()) {
+
+			File files[] = from.listFiles();
+			for (int i = 0; i < files.length; i++) {
+				copy(jar, appendPath(path, files[i].getName()), files[i], preprocess, extra);
+			}
+		} else {
+			if (from.exists()) {
+				Resource resource = new FileResource(from);
+				if (preprocess) {
+					resource = new PreprocessResource(this, resource);
+				}
+				String x = extra.get("extra");
+				if (x != null)
+					resource.setExtra(x);
+				if (path.endsWith("/"))
+					path = path + from.getName();
+				jar.putResource(path, resource);
+
+				if (isTrue(extra.get(LIB_DIRECTIVE))) {
+					setProperty(BUNDLE_CLASSPATH, append(getProperty(BUNDLE_CLASSPATH), path));
+				}
+			} 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);
+	}
+
+	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;
+		}
+
+		List<Jar> result = new ArrayList<Jar>();
+		List<Builder> builders;
+
+		builders = getSubBuilders();
+
+		for (Builder builder : builders) {
+			try {
+				Jar jar = builder.build();
+				jar.setName(builder.getBsn());
+				result.add(jar);
+			} catch (Exception e) {
+				error("Sub Building " + builder.getBsn(), e);
+			}
+			if (builder != this)
+				getInfo(builder, builder.getBsn() + ": ");
+		}
+		return result.toArray(new Jar[result.size()]);
+	}
+
+	/**
+	 * Answer a list of builders that represent this file or a list of files
+	 * specified in -sub. This list can be empty. These builders represents to
+	 * be created artifacts and are each scoped to such an artifacts. The
+	 * builders can be used to build the bundles or they can be used to find out
+	 * information about the to be generated bundles.
+	 *
+	 * @return List of 0..n builders representing artifacts.
+	 * @throws Exception
+	 */
+	public List<Builder> getSubBuilders() throws Exception {
+		String sub = (String) getProperty(SUB);
+		if (sub == null || sub.trim().length() == 0 || EMPTY_HEADER.equals(sub))
+			return Arrays.asList(this);
+
+		List<Builder> builders = new ArrayList<Builder>();
+		if (isTrue(getProperty(NOBUNDLES)))
+			return builders;
+
+		Set<Instruction> subs = Instruction.replaceWithInstruction(parseHeader(sub)).keySet();
+
+		List<File> members = new ArrayList<File>(Arrays.asList(getBase().listFiles()));
+
+		nextFile: while (members.size() > 0) {
+
+			File file = members.remove(0);
+
+			// Check if the file is one of our parents
+			Processor p = this;
+			while (p != null) {
+				if (file.equals(p.getPropertiesFile()))
+					continue nextFile;
+				p = p.getParent();
+			}
+
+			// if
+			// (file.getCanonicalFile().equals(getPropertiesFile().getCanonicalFile()))
+			// continue nextFile;
+
+			for (Iterator<Instruction> i = subs.iterator(); i.hasNext();) {
+
+				Instruction instruction = i.next();
+				if (instruction.matches(file.getName())) {
+
+					if (!instruction.isNegated()) {
+
+						Builder builder = getSubBuilder();
+						if (builder != null) {
+							builder.setProperties(file);
+							addClose(builder);
+							builders.add(builder);
+						}
+					}
+
+					// Because we matched (even though we could be negated)
+					// we skip any remaining searches
+					continue nextFile;
+				}
+			}
+		}
+		return builders;
+	}
+
+	public Builder getSubBuilder() throws Exception {
+		Builder builder = new Builder(this);
+		builder.setBase(getBase());
+
+		for (Jar file : getClasspath()) {
+			builder.addClasspath(file);
+		}
+
+		return builder;
+	}
+
+	/**
+	 * 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();
+	}
+
+	/**
+     *
      */
+	public void removeBundleSpecificHeaders() {
+		Set<String> set = new HashSet<String>(Arrays.asList(BUNDLE_SPECIFIC_HEADERS));
+		setForceLocal(set);
+	}
 
-    public void analyze() throws IOException {
-        super.analyze();
-        cleanupVersion(imports);
-        cleanupVersion(exports);
-        String version = getProperty(BUNDLE_VERSION);
-        if (version != null)
-            setProperty(BUNDLE_VERSION, cleanupVersion(version));
-    }
+	/**
+	 * Check if the given resource is in scope of this bundle. That is, it
+	 * checks if the Include-Resource includes this resource or if it is a class
+	 * file it is on the class path and the Export-Pacakge or Private-Package
+	 * include this resource.
+	 *
+	 * For now, include resources are skipped.
+	 *
+	 * @param f
+	 * @return
+	 */
+	public boolean isInScope(Collection<File> resources) throws Exception {
+		Map<String, Map<String, String>> clauses = parseHeader(getProperty(Constants.EXPORT_PACKAGE));
+		clauses.putAll(parseHeader(getProperty(Constants.PRIVATE_PACKAGE)));
+		if (isTrue(getProperty(Constants.UNDERTEST))) {
+			clauses.putAll(parseHeader(getProperty(Constants.TESTPACKAGES,
+					"test;presence:=optional")));
+		}
+		Collection<Instruction> instructions = Instruction.replaceWithInstruction(clauses).keySet();
 
-    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")));
-            }
-        }
-    }
+		for (File r : resources) {
+			String cpEntry = getClasspathEntrySuffix(r);
+			if (cpEntry != null) {
+				String pack = Clazz.getPackage(cpEntry);
+				Instruction i = matches(instructions, pack, null);
+				if (i != null)
+					return !i.isNegated();
+			}
+		}
+		return false;
+	}
 
-    /**
-     * 
-     */
-    private void addSources(Jar dot) {
-        if (!hasSources())
-            return;
+	/**
+	 * Answer the string of the resource that it has in the container.
+	 *
+	 * @param resource
+	 *            The resource to look for
+	 * @return
+	 * @throws Exception
+	 */
+	public String getClasspathEntrySuffix(File resource) throws Exception {
+		for (Jar jar : getClasspath()) {
+			File source = jar.getSource();
+			if (source != null) {
+				source = source.getCanonicalFile();
+				String sourcePath = source.getAbsolutePath();
+				String resourcePath = resource.getAbsolutePath();
 
-        Set<String> packages = new HashSet<String>();
+				if (resourcePath.startsWith(sourcePath)) {
+					// Make sure that the path name is translated correctly
+					// i.e. on Windows the \ must be translated to /
+					String filePath = resourcePath.substring(sourcePath.length() + 1);
 
-        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>> privateMap = replaceWitInstruction(
-                getHeader(PRIVATE_PACKAGE), PRIVATE_PACKAGE);
-        Map<Instruction, Map<String, String>> exportMap = replaceWitInstruction(
-                getHeader(EXPORT_PACKAGE), EXPORT_PACKAGE);
-
-        if (isTrue(getProperty(Constants.UNDERTEST))) {
-            privateMap.putAll(replaceWitInstruction(parseHeader(getProperty(
-                    Constants.TESTPACKAGES, "test;presence:=optional")),
-                    TESTPACKAGES));
-        }
-        if (!privateMap.isEmpty())
-            doExpand(jar, "Private-Package, or -testpackages", privateMap, true);
-
-        if (!exportMap.isEmpty()) {
-            Jar exports = new Jar("exports");
-            doExpand(exports, "Export-Package", exportMap, true);
-            jar.addAll(exports);
-            exports.close();
-        }
-
-        if (privateMap.isEmpty() && exportMap.isEmpty() && !isResourceOnly()) {
-            warning("Neither Export-Package, Private-Package, -testpackages is set, therefore no packages will be included");
-        }
-    }
-
-    /**
-     * 
-     * @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-OPT/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 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 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];
-
-                // Handle directories
-                if (sourceFile.isDirectory()) {
-                    destinationPath = doResourceDirectory(jar, extra,
-                            preprocess, sourceFile, destinationPath);
-                    return;
-                }
-            }
-
-            //destinationPath = checkDestinationPath(destinationPath);
-
-            if (!sourceFile.exists()) {
-                noSuchFile(jar, name, extra, source, destinationPath);
-            } else
-                copy(jar, destinationPath, sourceFile, preprocess, extra);
-        }
-    }
-
-    private String doResourceDirectory(Jar jar, Map<String, String> extra,
-            boolean preprocess, File sourceFile, String destinationPath)
-            throws Exception {
-        String filter = extra.get("filter:");
-        boolean flatten = isTrue(extra.get("flatten:"));
-        boolean recursive = true;
-        String directive = extra.get("recursive:");
-        if (directive != null) {
-            recursive = isTrue(directive);
-        }
-
-        InstructionFilter iFilter = null;
-        if (filter != null) {
-            iFilter = new InstructionFilter(Instruction
-                    .getPattern(filter), recursive);
-        } else {
-            iFilter = new InstructionFilter(null, recursive);
-        }
-
-        destinationPath = checkDestinationPath(destinationPath);
-
-        File[] files = resolveFiles(sourceFile, iFilter, recursive);
-        for (File file : files) {
-            String dp;
-            if (flatten) {
-                if (destinationPath.length() == 0) {
-                    dp = file.getName();
-                } else {
-                    dp = destinationPath + "/"
-                            + file.getName();
-                }
-            } else {
-                dp = destinationPath
-                        + file.getParentFile().getAbsolutePath()
-                                .substring(
-                                        sourceFile
-                                                .getAbsolutePath()
-                                                .length()).replace('\\','/');
-                if (dp.length() > 0) {
-                    dp += "/" + file.getName();
-                } else {
-                    dp = file.getName();
-                }
-            }
-            copy(jar, dp, file, preprocess, extra);
-        }
-        return destinationPath;
-    }
-
-    private String checkDestinationPath(String destinationPath) {
-
-        // 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);
-        return destinationPath;
-    }
-
-    private File[] resolveFiles(File dir, FileFilter filter, boolean recursive) {
-        return resolveFiles(dir, filter, null, recursive);
-    }
-
-    private File[] resolveFiles(File dir, FileFilter filter, File[] files,
-            boolean recursive) {
-        if (files == null) {
-            files = EMPTY_FILE;
-        }
-
-        if (Analyzer.doNotCopy.matcher(dir.getName()).matches()) {
-            return files;
-        }
-
-        File[] fs = dir.listFiles(filter);
-        for (File file : fs) {
-            if (file.isDirectory()) {
-                if (recursive) {
-                    files = resolveFiles(file, filter, files, recursive);
-                }
-            } else {
-                if (files.length == 0) {
-                    files = new File[] { file };
-                } else {
-                    File[] newFiles = new File[files.length + 1];
-                    System.arraycopy(files, 0, newFiles, 0, files.length);
-                    newFiles[newFiles.length - 1] = file;
-                    files = newFiles;
-                }
-            }
-        }
-        return files;
-    }
-
-    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) {
-                String x = extra.get("extra");
-                if (x != null)
-                    lastChance.setExtra(x);
-                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.endsWith("/"))
-                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);
-                }
-                String x = extra.get("extra");
-                if (x != null)
-                    resource.setExtra(x);
-                if ( path.endsWith("/"))
-                    path = path + from.getName();
-                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()]);
-    }
-
-    public Builder getSubBuilder() throws Exception {
-        Builder builder = new Builder(this);
-        builder.setBase(getBase());
-
-        for (Jar file : getClasspath()) {
-            builder.addClasspath(file);
-        }
-
-        return builder;
-    }
-
-    /**
-     * 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();
-    }
-
-    public void removeBundleSpecificHeaders() {
-        Set<String> set = new HashSet<String>(Arrays
-                .asList(BUNDLE_SPECIFIC_HEADERS));
-        setForceLocal(set);
-    }
+					return filePath.replace(File.separatorChar, '/');
+				}
+			}
+		}
+		return null;
+	}
 
 }
diff --git a/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java b/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
index 94b34a3..756064a 100644
--- a/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
+++ b/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
@@ -63,6 +63,7 @@
 
 import aQute.lib.osgi.Analyzer;
 import aQute.lib.osgi.Builder;
+import aQute.lib.osgi.Constants;
 import aQute.lib.osgi.EmbeddedResource;
 import aQute.lib.osgi.FileResource;
 import aQute.lib.osgi.Jar;
@@ -395,7 +396,7 @@
 
         dumpManifest( "BND Manifest:", jar.getManifest(), getLog() );
 
-        String[] removeHeaders = builder.getProperty( Analyzer.REMOVE_HEADERS, "" ).split( "," );
+        String[] removeHeaders = builder.getProperty( Constants.REMOVEHEADERS, "" ).split( "," );
 
         mergeMavenManifest( currentProject, jar, removeHeaders, getLog() );
         builder.setJar( jar );
@@ -852,7 +853,7 @@
         properties.put( Analyzer.BUNDLE_VERSION, getMaven2OsgiConverter().getVersion(currentProject.getVersion()) );
 
         // remove the extraneous Include-Resource and Private-Package entries from generated manifest
-        properties.put( Analyzer.REMOVE_HEADERS, Analyzer.INCLUDE_RESOURCE + ',' + Analyzer.PRIVATE_PACKAGE );
+        properties.put( Constants.REMOVEHEADERS, Analyzer.INCLUDE_RESOURCE + ',' + Analyzer.PRIVATE_PACKAGE );
 
         header( properties, Analyzer.BUNDLE_DESCRIPTION, currentProject.getDescription() );
         StringBuffer licenseText = printLicenses( currentProject.getLicenses() );
diff --git a/bundleplugin/src/main/java/org/apache/felix/bundleplugin/ManifestPlugin.java b/bundleplugin/src/main/java/org/apache/felix/bundleplugin/ManifestPlugin.java
index 4503840..5a136cd 100644
--- a/bundleplugin/src/main/java/org/apache/felix/bundleplugin/ManifestPlugin.java
+++ b/bundleplugin/src/main/java/org/apache/felix/bundleplugin/ManifestPlugin.java
@@ -100,14 +100,14 @@
 
 
     public Manifest getManifest( MavenProject project, Jar[] classpath ) throws IOException, MojoFailureException,
-        MojoExecutionException
+        MojoExecutionException, Exception
     {
         return getManifest( project, new Properties(), new Properties(), classpath );
     }
 
 
     public Manifest getManifest( MavenProject project, Map instructions, Properties properties, Jar[] classpath )
-        throws IOException, MojoFailureException, MojoExecutionException
+        throws IOException, MojoFailureException, MojoExecutionException, Exception
     {
         Analyzer analyzer = getAnalyzer( project, instructions, properties, classpath );
 
@@ -143,14 +143,15 @@
     }
 
 
-    protected Analyzer getAnalyzer( MavenProject project, Jar[] classpath ) throws IOException, MojoExecutionException
+    protected Analyzer getAnalyzer( MavenProject project, Jar[] classpath )
+        throws IOException, MojoExecutionException, Exception
     {
         return getAnalyzer( project, new LinkedHashMap(), new Properties(), classpath );
     }
 
 
     protected Analyzer getAnalyzer( MavenProject project, Map instructions, Properties properties, Jar[] classpath )
-        throws IOException, MojoExecutionException
+        throws IOException, MojoExecutionException, Exception
     {
         File file = project.getArtifact().getFile();
         if ( file == null )
