diff --git a/bundleplugin/pom.xml b/bundleplugin/pom.xml
index 8ce26d3..e7675d0 100644
--- a/bundleplugin/pom.xml
+++ b/bundleplugin/pom.xml
@@ -56,7 +56,7 @@
   <dependency>
    <groupId>biz.aQute</groupId>
    <artifactId>bndlib</artifactId>
-   <version>0.0.308</version>
+   <version>0.0.310</version>
   </dependency>
   <dependency>
     <groupId>net.sf.kxml</groupId>
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/About.java b/bundleplugin/src/main/java/aQute/lib/osgi/About.java
deleted file mode 100644
index 52a2529..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/About.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/* 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;
-
-/**
- * This package contains a number of classes that assists by analyzing JARs and
- * constructing bundles.
- * 
- * The Analyzer class can be used to analyze an existing bundle and can create a
- * manifest specification from proposed (wildcard) Export-Package,
- * Bundle-Includes, and Import-Package headers.
- * 
- * The Builder class can use the headers to construct a JAR from the classpath.
- * 
- * The Verifier class can take an existing JAR and verify that all headers are
- * correctly set. It will verify the syntax of the headers, match it against the
- * proper contents, and verify imports and exports.
- * 
- * A number of utility classes are available.
- * 
- * Jar, provides an abstraction of a Jar file. It has constructors for creating
- * a Jar from a stream, a directory, or a jar file. A Jar, keeps a collection
- * Resource's. There are Resource implementations for File, from ZipFile, or from
- * a stream (which copies the data). The Jar tries to minimize the work during
- * build up so that it is cheap to use. The Resource's can be used to iterate 
- * over the names and later read the resources when needed.
- * 
- * Clazz, provides a parser for the class files. This will be used to define the
- * imports and exports.
- * 
- * A key component in this library is the Map. Headers are translated to Maps of Maps. OSGi
- * header syntax is like:
- * <pre>
- * 	  header = clause ( ',' clause ) *
- *    clause = file ( ';' file ) * ( parameter ) *
- *    param  = attr '=' value | directive ':=' value
- * </pre>
- * These headers are translated to a Map that contains all headers (the order is
- * maintained). Each additional file in a header definition will have its own
- * entry (only native code does not work this way). The clause is represented
- * as another map. The ':' of directives is considered part of the name. This
- * allows attributes and directives to be maintained in the clause map. 
- * 
- * @version $Revision: 1.1 $
- */
-public class About {
-
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/AbstractResource.java b/bundleplugin/src/main/java/aQute/lib/osgi/AbstractResource.java
deleted file mode 100644
index 532b33e..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/AbstractResource.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-
-public abstract class AbstractResource implements Resource {
-    String extra;
-    byte[] calculated;
-    long   lastModified;
-
-    protected AbstractResource(long modified) {
-        lastModified = modified;
-    }
-
-    public String getExtra() {
-        return extra;
-    }
-
-    public long lastModified() {
-        return lastModified;
-    }
-
-    public InputStream openInputStream() throws IOException {
-        return new ByteArrayInputStream(getLocalBytes());
-    }
-
-    private byte[] getLocalBytes() throws IOException {
-        try {
-            if (calculated != null)
-                return calculated;
-
-            return calculated = getBytes();
-        } catch (IOException e) {
-            throw e;
-        } catch (Exception e) {
-            IOException ee = new IOException("Opening resource");
-            ee.initCause(e);
-            throw ee;
-        }
-    }
-
-    public void setExtra(String extra) {
-        this.extra = extra;
-    }
-
-    public void write(OutputStream out) throws IOException {
-        out.write(getLocalBytes());
-    }
-
-    abstract protected byte[] getBytes() throws Exception;
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Analyzer.java b/bundleplugin/src/main/java/aQute/lib/osgi/Analyzer.java
deleted file mode 100644
index f3954bd..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Analyzer.java
+++ /dev/null
@@ -1,1885 +0,0 @@
-/* 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;
-
-/**
- * This class can calculate the required headers for a (potential) JAR file. It
- * analyzes a directory or JAR for the packages that are contained and that are
- * referred to by the bytecodes. The user can the use regular expressions to
- * define the attributes and directives. The matching is not fully regex for
- * convenience. A * and ? get a . prefixed and dots are escaped.
- * 
- * <pre>
- *                                                             			*;auto=true				any		
- *                                                             			org.acme.*;auto=true    org.acme.xyz
- *                                                             			org.[abc]*;auto=true    org.acme.xyz
- * </pre>
- * 
- * Additional, the package instruction can start with a '=' or a '!'. The '!'
- * indicates negation. Any matching package is removed. The '=' is literal, the
- * expression will be copied verbatim and no matching will take place.
- * 
- * Any headers in the given properties are used in the output properties.
- */
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.jar.*;
-import java.util.jar.Attributes.*;
-import java.util.regex.*;
-
-import aQute.bnd.service.*;
-import aQute.lib.filter.*;
-
-public class Analyzer extends Processor {
-
-    static Pattern                         doNotCopy      = Pattern
-                                                                  .compile("CVS|.svn");
-    static String                          version;
-    static Pattern                         versionPattern = Pattern
-                                                                  .compile("(\\d+\\.\\d+)\\.\\d+.*");
-    final Map<String, Map<String, String>> contained      = newHashMap();                            // package
-    final Map<String, Map<String, String>> referred       = newHashMap();                            // package
-    final Map<String, Set<String>>         uses           = newHashMap();                            // package
-    Map<String, Clazz>                     classspace;
-    Map<String, Map<String, String>>       exports;
-    Map<String, Map<String, String>>       imports;
-    Map<String, Map<String, String>>       bundleClasspath;                                          // Bundle
-    final Map<String, Map<String, String>> ignored        = newHashMap();                            // Ignored
-    // packages
-    Jar                                    dot;
-    Map<String, Map<String, String>>       classpathExports;
-
-    String                                 activator;
-
-    final List<Jar>                        classpath      = newList();
-
-    static Properties                      bndInfo;
-
-    boolean                                analyzed;
-    String                                 bsn;
-
-    public Analyzer(Processor parent) {
-        super(parent);
-    }
-
-    public Analyzer() {
-    }
-
-    /**
-     * Specifically for Maven
-     * 
-     * @param properties
-     *            the properties
-     */
-
-    public static Properties getManifest(File dirOrJar) throws IOException {
-        Analyzer analyzer = new Analyzer();
-        analyzer.setJar(dirOrJar);
-        Properties properties = new Properties();
-        properties.put(IMPORT_PACKAGE, "*");
-        properties.put(EXPORT_PACKAGE, "*");
-        analyzer.setProperties(properties);
-        Manifest m = analyzer.calcManifest();
-        Properties result = new Properties();
-        for (Iterator<Object> i = m.getMainAttributes().keySet().iterator(); i
-                .hasNext();) {
-            Attributes.Name name = (Attributes.Name) i.next();
-            result.put(name.toString(), m.getMainAttributes().getValue(name));
-        }
-        return result;
-    }
-
-    /**
-     * Calcualtes the data structures for generating a manifest.
-     * 
-     * @throws IOException
-     */
-    public void analyze() throws IOException {
-        if (!analyzed) {
-            analyzed = true;
-            classpathExports = newHashMap();
-            activator = getProperty(BUNDLE_ACTIVATOR);
-            bundleClasspath = parseHeader(getProperty(BUNDLE_CLASSPATH));
-
-            analyzeClasspath();
-
-            classspace = analyzeBundleClasspath(dot, bundleClasspath,
-                    contained, referred, uses);
-
-            for (AnalyzerPlugin plugin : getPlugins(AnalyzerPlugin.class)) {
-                if (plugin instanceof AnalyzerPlugin) {
-                    AnalyzerPlugin analyzer = (AnalyzerPlugin) plugin;
-                    try {
-                        boolean reanalyze = analyzer.analyzeJar(this);
-                        if (reanalyze)
-                            classspace = analyzeBundleClasspath(dot,
-                                    bundleClasspath, contained, referred, uses);
-                    } catch (Exception e) {
-                        error("Plugin Analyzer " + analyzer
-                                + " throws exception " + e);
-                        e.printStackTrace();
-                    }
-                }
-            }
-
-            if (activator != null) {
-                // Add the package of the activator to the set
-                // of referred classes. This must be done before we remove
-                // contained set.
-                int n = activator.lastIndexOf('.');
-                if (n > 0) {
-                    referred.put(activator.substring(0, n),
-                            new LinkedHashMap<String, String>());
-                }
-            }
-
-            referred.keySet().removeAll(contained.keySet());
-            if (referred.containsKey(".")) {
-                error("The default package '.' is not permitted by the Import-Package syntax. \n"
-                        + " This can be caused by compile errors in Eclipse because Eclipse creates \n"
-                        + "valid class files regardless of compile errors.\n"
-                        + "The following package(s) import from the default package "
-                        + getUsedBy("."));
-            }
-
-            Map<String, Map<String, String>> exportInstructions = parseHeader(getProperty(EXPORT_PACKAGE));
-            Map<String, Map<String, String>> additionalExportInstructions = parseHeader(getProperty(EXPORT_CONTENTS));
-            exportInstructions.putAll(additionalExportInstructions);
-            Map<String, Map<String, String>> importInstructions = parseHeader(getImportPackages());
-            Map<String, Map<String, String>> dynamicImports = parseHeader(getProperty(DYNAMICIMPORT_PACKAGE));
-
-            if (dynamicImports != null) {
-                // Remove any dynamic imports from the referred set.
-                referred.keySet().removeAll(dynamicImports.keySet());
-            }
-
-            Map<String, Map<String, String>> superfluous = newHashMap();
-            // Tricky!
-            for (Iterator<String> i = exportInstructions.keySet().iterator(); i
-                    .hasNext();) {
-                String instr = i.next();
-                if (!instr.startsWith("!"))
-                    superfluous.put(instr, exportInstructions.get(instr));
-            }
-
-            exports = merge("export-package", exportInstructions, contained,
-                    superfluous.keySet(), null);
-
-            // disallow export of default package
-            exports.remove(".");
-
-            for (Iterator<Map.Entry<String, Map<String, String>>> i = superfluous
-                    .entrySet().iterator(); i.hasNext();) {
-                // It is possible to mention metadata directories in the export
-                // explicitly, they are then exported and removed from the
-                // warnings. Note that normally metadata directories are not
-                // exported.
-                Map.Entry<String, Map<String, String>> entry = i.next();
-                String pack = entry.getKey();
-                if (isDuplicate(pack))
-                    i.remove();
-                else if (isMetaData(pack)) {
-                    exports.put(pack, entry.getValue());
-                    i.remove();
-                }
-            }
-
-            if (!superfluous.isEmpty()) {
-                warning("Superfluous export-package instructions: "
-                        + superfluous.keySet());
-            }
-
-            // Add all exports that do not have an -noimport: directive
-            // to the imports.
-            Map<String, Map<String, String>> referredAndExported = newMap(referred);
-            referredAndExported.putAll(addExportsToImports(exports));
-
-            // match the imports to the referred and exported packages,
-            // merge the info for matching packages
-            Set<String> extra = new TreeSet<String>(importInstructions.keySet());
-            imports = merge("import-package", importInstructions,
-                    referredAndExported, extra, ignored);
-
-            // Instructions that have not been used could be superfluous
-            // or if they do not contain wildcards, should be added
-            // as extra imports, the user knows best.
-            for (Iterator<String> i = extra.iterator(); i.hasNext();) {
-                String p = i.next();
-                if (p.startsWith("!") || p.indexOf('*') >= 0
-                        || p.indexOf('?') >= 0 || p.indexOf('[') >= 0) {
-                    if (!isResourceOnly())
-                        warning("Did not find matching referal for " + p);
-                } else {
-                    Map<String, String> map = importInstructions.get(p);
-                    imports.put(p, map);
-                }
-            }
-
-            // See what information we can find to augment the
-            // imports. I.e. look on the classpath
-            augmentImports();
-
-            // Add the uses clause to the exports
-            doUses(exports, uses, imports);
-        }
-    }
-
-    /**
-     * Copy the input collection into an output set but skip names that have
-     * been marked as duplicates or are optional.
-     * 
-     * @param superfluous
-     * @return
-     */
-    Set<Instruction> removeMarkedDuplicates(Collection<Instruction> superfluous) {
-        Set<Instruction> result = new HashSet<Instruction>();
-        for (Iterator<Instruction> i = superfluous.iterator(); i.hasNext();) {
-            Instruction instr = (Instruction) i.next();
-            if (!isDuplicate(instr.getPattern()) && !instr.isOptional())
-                result.add(instr);
-        }
-        return result;
-    }
-
-    /**
-     * Analyzer has an empty default but the builder has a * as default.
-     * 
-     * @return
-     */
-    protected String getImportPackages() {
-        return getProperty(IMPORT_PACKAGE);
-    }
-
-    /**
-     * 
-     * @return
-     */
-    boolean isResourceOnly() {
-        return getProperty(RESOURCEONLY, "false").equalsIgnoreCase("true");
-    }
-
-    /**
-     * Answer the list of packages that use the given package.
-     */
-    Set<String> getUsedBy(String pack) {
-        Set<String> set = newSet();
-        for (Iterator<Map.Entry<String, Set<String>>> i = uses.entrySet()
-                .iterator(); i.hasNext();) {
-            Map.Entry<String, Set<String>> entry = i.next();
-            Set<String> used = entry.getValue();
-            if (used.contains(pack))
-                set.add(entry.getKey());
-        }
-        return set;
-    }
-
-    /**
-     * One of the main workhorses of this class. This will analyze the current
-     * setp and calculate a new manifest according to this setup. This method
-     * will also set the manifest on the main jar dot
-     * 
-     * @return
-     * @throws IOException
-     */
-    public Manifest calcManifest() throws IOException {
-        analyze();
-        Manifest manifest = new Manifest();
-        Attributes main = manifest.getMainAttributes();
-
-        main.put(Attributes.Name.MANIFEST_VERSION, "1.0");
-        main.putValue(BUNDLE_MANIFESTVERSION, "2");
-
-        boolean noExtraHeaders = "true"
-                .equalsIgnoreCase(getProperty(NOEXTRAHEADERS));
-
-        if (!noExtraHeaders) {
-            main.putValue(CREATED_BY, System.getProperty("java.version") + " ("
-                    + System.getProperty("java.vendor") + ")");
-            main.putValue(TOOL, "Bnd-" + getVersion());
-            main.putValue(BND_LASTMODIFIED, "" + System.currentTimeMillis());
-        }
-        String exportHeader = printClauses(exports,
-                "uses:|include:|exclude:|mandatory:|" + IMPORT_DIRECTIVE, true);
-
-        if (exportHeader.length() > 0)
-            main.putValue(EXPORT_PACKAGE, exportHeader);
-        else
-            main.remove(EXPORT_PACKAGE);
-
-        Map<String, Map<String, String>> temp = removeKeys(imports, "java.");
-        if (!temp.isEmpty()) {
-            main.putValue(IMPORT_PACKAGE, printClauses(temp, "resolution:"));
-        } else {
-            main.remove(IMPORT_PACKAGE);
-        }
-
-        temp = newMap(contained);
-        temp.keySet().removeAll(exports.keySet());
-
-        if (!temp.isEmpty())
-            main.putValue(PRIVATE_PACKAGE, printClauses(temp, ""));
-        else
-            main.remove(PRIVATE_PACKAGE);
-
-        if (!ignored.isEmpty()) {
-            main.putValue(IGNORE_PACKAGE, printClauses(ignored, ""));
-        } else {
-            main.remove(IGNORE_PACKAGE);
-        }
-
-        if (bundleClasspath != null && !bundleClasspath.isEmpty())
-            main.putValue(BUNDLE_CLASSPATH, printClauses(bundleClasspath, ""));
-        else
-            main.remove(BUNDLE_CLASSPATH);
-
-        Map<String, Map<String, String>> l = doServiceComponent(getProperty(SERVICE_COMPONENT));
-        if (!l.isEmpty())
-            main.putValue(SERVICE_COMPONENT, printClauses(l, ""));
-        else
-            main.remove(SERVICE_COMPONENT);
-
-        for (Enumeration<?> h = getProperties().propertyNames(); h
-                .hasMoreElements();) {
-            String header = (String) h.nextElement();
-            if (header.trim().length() == 0) {
-                warning("Empty property set with value: "
-                        + getProperties().getProperty(header));
-                continue;
-            }
-            if (!Character.isUpperCase(header.charAt(0))) {
-                if (header.charAt(0) == '@')
-                    doNameSection(manifest, header);
-                continue;
-            }
-
-            if (header.equals(BUNDLE_CLASSPATH)
-                    || header.equals(EXPORT_PACKAGE)
-                    || header.equals(IMPORT_PACKAGE))
-                continue;
-            
-            if ( header.equalsIgnoreCase("Name")) {
-                error("Your bnd file contains a header called 'Name'. This interferes with the manifest name section.");
-                continue;
-            }
-
-            if (Verifier.HEADER_PATTERN.matcher(header).matches()) {
-                String value = getProperty(header);
-                if (value != null && main.getValue(header) == null) {
-                    if (value.trim().length() == 0)
-                        main.remove(header);
-                    else
-                        main.putValue(header, value);
-                }
-            } else {
-                // TODO should we report?
-            }
-        }
-
-        //
-        // Calculate the bundle symbolic name if it is
-        // not set.
-        // 1. set
-        // 2. name of properties file (must be != bnd.bnd)
-        // 3. name of directory, which is usualy project name
-        //
-        String bsn = getBsn();
-        if (main.getValue(BUNDLE_SYMBOLICNAME) == null) {
-            main.putValue(BUNDLE_SYMBOLICNAME, bsn);
-        }
-
-        //
-        // Use the same name for the bundle name as BSN when
-        // the bundle name is not set
-        //
-        if (main.getValue(BUNDLE_NAME) == null) {
-            main.putValue(BUNDLE_NAME, bsn);
-        }
-
-        if (main.getValue(BUNDLE_VERSION) == null)
-            main.putValue(BUNDLE_VERSION, "0");
-
-        // Copy old values into new manifest, when they
-        // exist in the old one, but not in the new one
-        merge(manifest, dot.getManifest());
-
-        // Remove all the headers mentioned in -removeheaders
-        Map<String, Map<String, String>> removes = parseHeader(getProperty(REMOVE_HEADERS));
-        for (Iterator<String> i = removes.keySet().iterator(); i.hasNext();) {
-            String header = i.next();
-            for (Iterator<Object> j = main.keySet().iterator(); j.hasNext();) {
-                Attributes.Name attr = (Attributes.Name) j.next();
-                if (attr.toString().matches(header)) {
-                    j.remove();
-                    progress("Removing header: " + header);
-                }
-            }
-        }
-
-        dot.setManifest(manifest);
-        return manifest;
-    }
-
-    /**
-     * This method is called when the header starts with a @, signifying
-     * a name section header. The name part is defined by replacing all the @
-     * signs to a /, removing the first and the last, and using the last
-     * part as header name:
-     * <pre>
-     * @org@osgi@service@event@Implementation-Title
-     * </pre>
-     * This will be the header Implementation-Title in the org/osgi/service/event
-     * named section.
-     *  
-     * @param manifest
-     * @param header
-     */
-    private void doNameSection(Manifest manifest, String header) {
-        String path = header.replace('@', '/');
-        int n = path.lastIndexOf('/');
-        // Must succeed because we start with @
-        String name = path.substring(n + 1);
-        // Skip first /
-        path = path.substring(1, n);
-        if (name.length() != 0 && path.length() != 0) {
-            Attributes attrs = manifest.getAttributes(path);
-            if (attrs == null) {
-                attrs = new Attributes();
-                manifest.getEntries().put(path, attrs);
-            }
-            attrs.putValue(name, getProperty(header));
-        } else {
-            warning(
-                    "Invalid header (starts with @ but does not seem to be for the Name section): %s",
-                    header);
-        }
-    }
-
-    /**
-     * Clear the key part of a header. I.e. remove everything from the first ';'
-     * 
-     * @param value
-     * @return
-     */
-    public String getBsn() {
-        String value = getProperty(BUNDLE_SYMBOLICNAME);
-        if (value == null) {
-            if (getPropertiesFile() != null)
-                value = getPropertiesFile().getName();
-
-            if (value == null || value.equals("bnd.bnd"))
-                value = getBase().getName();
-            else if (value.endsWith(".bnd"))
-                value = value.substring(0, value.length() - 4);
-        }
-
-        if (value == null)
-            return "untitled";
-
-        int n = value.indexOf(';');
-        if (n > 0)
-            value = value.substring(0, n);
-        return value.trim();
-    }
-
-    /**
-     * Calculate an export header solely based on the contents of a JAR file
-     * 
-     * @param bundle
-     *            The jar file to analyze
-     * @return
-     */
-    public String calculateExportsFromContents(Jar bundle) {
-        String ddel = "";
-        StringBuffer sb = new StringBuffer();
-        Map<String, Map<String, Resource>> map = bundle.getDirectories();
-        for (Iterator<String> i = map.keySet().iterator(); i.hasNext();) {
-            String directory = (String) i.next();
-            if (directory.equals("META-INF")
-                    || directory.startsWith("META-INF/"))
-                continue;
-            if (directory.equals("OSGI-OPT")
-                    || directory.startsWith("OSGI-OPT/"))
-                continue;
-            if (directory.equals("/"))
-                continue;
-
-            if (directory.endsWith("/"))
-                directory = directory.substring(0, directory.length() - 1);
-
-            directory = directory.replace('/', '.');
-            sb.append(ddel);
-            sb.append(directory);
-            ddel = ",";
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Check if a service component header is actually referring to a class. If
-     * so, replace the reference with an XML file reference. This makes it
-     * easier to create and use components.
-     * 
-     * @throws UnsupportedEncodingException
-     * 
-     */
-    public Map<String, Map<String, String>> doServiceComponent(
-            String serviceComponent) throws IOException {
-        Map<String, Map<String, String>> list = newMap();
-        Map<String, Map<String, String>> sc = parseHeader(serviceComponent);
-        if (!sc.isEmpty()) {
-            for (Iterator<Map.Entry<String, Map<String, String>>> i = sc
-                    .entrySet().iterator(); i.hasNext();) {
-                Map.Entry<String, Map<String, String>> entry = i.next();
-                String name = entry.getKey();
-                Map<String, String> info = entry.getValue();
-                if (name == null) {
-                    error("No name in Service-Component header: " + info);
-                    continue;
-                }
-                if (dot.exists(name)) {
-                    // Normal service component
-                    list.put(name, info);
-                } else {
-                    String impl = name;
-                    if (info.containsKey(COMPONENT_IMPLEMENTATION))
-                        impl = info.get(COMPONENT_IMPLEMENTATION);
-
-                    if (!checkClass(impl))
-                        error("Not found Service-Component header: " + name);
-                    else {
-                        // We have a definition, so make an XML resources
-                        Resource resource = createComponentResource(name, info);
-                        dot.putResource("OSGI-INF/" + name + ".xml", resource);
-                        Map<String, String> empty = Collections.emptyMap();
-                        list.put("OSGI-INF/" + name + ".xml", empty);
-                    }
-                }
-            }
-        }
-        return list;
-    }
-
-    public Map<String, Map<String, String>> getBundleClasspath() {
-        return bundleClasspath;
-    }
-
-    public Map<String, Map<String, String>> getContained() {
-        return contained;
-    }
-
-    public Map<String, Map<String, String>> getExports() {
-        return exports;
-    }
-
-    public Map<String, Map<String, String>> getImports() {
-        return imports;
-    }
-
-    public Jar getJar() {
-        return dot;
-    }
-
-    public Map<String, Map<String, String>> getReferred() {
-        return referred;
-    }
-
-    /**
-     * Return the set of unreachable code depending on exports and the bundle
-     * activator.
-     * 
-     * @return
-     */
-    public Set<String> getUnreachable() {
-        Set<String> unreachable = new HashSet<String>(uses.keySet()); // all
-        for (Iterator<String> r = exports.keySet().iterator(); r.hasNext();) {
-            String packageName = r.next();
-            removeTransitive(packageName, unreachable);
-        }
-        if (activator != null) {
-            String pack = activator.substring(0, activator.lastIndexOf('.'));
-            removeTransitive(pack, unreachable);
-        }
-        return unreachable;
-    }
-
-    public Map<String, Set<String>> getUses() {
-        return uses;
-    }
-
-    /**
-     * Get the version from the manifest, a lot of work!
-     * 
-     * @return version or unknown.
-     */
-    public String getVersion() {
-        return getBndInfo("version", "<unknown version>");
-    }
-
-    public long getBndLastModified() {
-        String time = getBndInfo("modified", "0");
-        try {
-            return Long.parseLong(time);
-        } catch (Exception e) {
-        }
-        return 0;
-    }
-
-    public String getBndInfo(String key, String defaultValue) {
-        if (bndInfo == null) {
-            bndInfo = new Properties();
-            try {
-                InputStream in = Analyzer.class.getResourceAsStream("bnd.info");
-                if (in != null) {
-                    bndInfo.load(in);
-                    in.close();
-                }
-            } catch (IOException ioe) {
-                warning("Could not read bnd.info in " + Analyzer.class.getPackage()
-                        + ioe);
-            }
-        }
-        return bndInfo.getProperty(key, defaultValue);
-    }
-
-    /**
-     * Merge the existing manifest with the instructions.
-     * 
-     * @param manifest
-     *            The manifest to merge with
-     * @throws IOException
-     */
-    public void mergeManifest(Manifest manifest) throws IOException {
-        if (manifest != null) {
-            Attributes attributes = manifest.getMainAttributes();
-            for (Iterator<Object> i = attributes.keySet().iterator(); i
-                    .hasNext();) {
-                Name name = (Name) i.next();
-                String key = name.toString();
-                // Dont want instructions
-                if (key.startsWith("-"))
-                    continue;
-
-                if (getProperty(key) == null)
-                    setProperty(key, (String) attributes.get(name));
-            }
-        }
-    }
-
-    // public Signer getSigner() {
-    // String sign = getProperty("-sign");
-    // if (sign == null) return null;
-    //
-    // Map parsed = parseHeader(sign);
-    // Signer signer = new Signer();
-    // String password = (String) parsed.get("password");
-    // if (password != null) {
-    // signer.setPassword(password);
-    // }
-    //
-    // String keystore = (String) parsed.get("keystore");
-    // if (keystore != null) {
-    // File f = new File(keystore);
-    // if (!f.isAbsolute()) f = new File(base, keystore);
-    // signer.setKeystore(f);
-    // } else {
-    // error("Signing requires a keystore");
-    // return null;
-    // }
-    //
-    // String alias = (String) parsed.get("alias");
-    // if (alias != null) {
-    // signer.setAlias(alias);
-    // } else {
-    // error("Signing requires an alias for the key");
-    // return null;
-    // }
-    // return signer;
-    // }
-
-    public void setBase(File file) {
-        super.setBase(file);
-        getProperties().put("project.dir", getBase().getAbsolutePath());
-    }
-
-    /**
-     * Set the classpath for this analyzer by file.
-     * 
-     * @param classpath
-     * @throws IOException
-     */
-    public void setClasspath(File[] classpath) throws IOException {
-        List<Jar> list = new ArrayList<Jar>();
-        for (int i = 0; i < classpath.length; i++) {
-            if (classpath[i].exists()) {
-                Jar current = new Jar(classpath[i]);
-                list.add(current);
-            } else {
-                error("Missing file on classpath: " + classpath[i]);
-            }
-        }
-        for (Iterator<Jar> i = list.iterator(); i.hasNext();) {
-            addClasspath(i.next());
-        }
-    }
-
-    public void setClasspath(Jar[] classpath) {
-        for (int i = 0; i < classpath.length; i++) {
-            addClasspath(classpath[i]);
-        }
-    }
-
-    public void setClasspath(String[] classpath) {
-        for (int i = 0; i < classpath.length; i++) {
-            Jar jar = getJarFromName(classpath[i], " setting classpath");
-            if (jar != null)
-                addClasspath(jar);
-        }
-    }
-
-    /**
-     * Set the JAR file we are going to work in. This will read the JAR in
-     * memory.
-     * 
-     * @param jar
-     * @return
-     * @throws IOException
-     */
-    public Jar setJar(File jar) throws IOException {
-        Jar jarx = new Jar(jar);
-        addClose(jarx);
-        return setJar(jarx);
-    }
-
-    /**
-     * Set the JAR directly we are going to work on.
-     * 
-     * @param jar
-     * @return
-     */
-    public Jar setJar(Jar jar) {
-        this.dot = jar;
-        return jar;
-    }
-
-    protected void begin() {
-        super.begin();
-
-        updateModified(getBndLastModified(), "bnd last modified");
-        String doNotCopy = getProperty(DONOTCOPY);
-        if (doNotCopy != null)
-            Analyzer.doNotCopy = Pattern.compile(doNotCopy);
-
-        verifyManifestHeadersCase(getProperties());
-    }
-
-    /**
-     * Check if the given class or interface name is contained in the jar.
-     * 
-     * @param interfaceName
-     * @return
-     */
-    boolean checkClass(String interfaceName) {
-        String path = interfaceName.replace('.', '/') + ".class";
-        if (classspace.containsKey(path))
-            return true;
-
-        String pack = interfaceName;
-        int n = pack.lastIndexOf('.');
-        if (n > 0)
-            pack = pack.substring(0, n);
-        else
-            pack = ".";
-
-        return imports.containsKey(pack);
-    }
-
-    /**
-     * Create the resource for a DS component.
-     * 
-     * @param list
-     * @param name
-     * @param info
-     * @throws UnsupportedEncodingException
-     */
-    Resource createComponentResource(String name, Map<String, String> info)
-            throws IOException {
-
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"));
-        pw.println("<?xml version='1.0' encoding='utf-8'?>");
-        pw.print("<component name='" + name + "'");
-
-        String factory = info.get(COMPONENT_FACTORY);
-        if (factory != null)
-            pw.print(" factory='" + factory + "'");
-
-        String immediate = info.get(COMPONENT_IMMEDIATE);
-        if (immediate != null)
-            pw.print(" immediate='" + immediate + "'");
-
-        String enabled = info.get(COMPONENT_ENABLED);
-        if (enabled != null)
-            pw.print(" enabled='" + enabled + "'");
-
-        pw.println(">");
-
-        // Allow override of the implementation when people
-        // want to choose their own name
-        String impl = (String) info.get(COMPONENT_IMPLEMENTATION);
-        pw.println("  <implementation class='" + (impl == null ? name : impl)
-                + "'/>");
-
-        String provides = info.get(COMPONENT_PROVIDE);
-        boolean servicefactory = Boolean.getBoolean(info
-                .get(COMPONENT_SERVICEFACTORY)
-                + "");
-        provides(pw, provides, servicefactory);
-        properties(pw, info);
-        reference(info, pw);
-        pw.println("</component>");
-        pw.close();
-        byte[] data = out.toByteArray();
-        out.close();
-        return new EmbeddedResource(data, 0);
-    }
-
-    /**
-     * Try to get a Jar from a file name/path or a url, or in last resort from
-     * the classpath name part of their files.
-     * 
-     * @param name
-     *            URL or filename relative to the base
-     * @param from
-     *            Message identifying the caller for errors
-     * @return null or a Jar with the contents for the name
-     */
-    Jar getJarFromName(String name, String from) {
-        File file = new File(name);
-        if (!file.isAbsolute())
-            file = new File(getBase(), name);
-
-        if (file.exists())
-            try {
-                Jar jar = new Jar(file);
-                addClose(jar);
-                return jar;
-            } catch (Exception e) {
-                error("Exception in parsing jar file for " + from + ": " + name
-                        + " " + e);
-            }
-        // It is not a file ...
-        try {
-            // Lets try a URL
-            URL url = new URL(name);
-            Jar jar = new Jar(fileName(url.getPath()));
-            addClose(jar);
-            URLConnection connection = url.openConnection();
-            InputStream in = connection.getInputStream();
-            long lastModified = connection.getLastModified();
-            if (lastModified == 0)
-                // We assume the worst :-(
-                lastModified = System.currentTimeMillis();
-            EmbeddedResource.build(jar, in, lastModified);
-            in.close();
-            return jar;
-        } catch (IOException ee) {
-            // Check if we have files on the classpath
-            // that have the right name, allows us to specify those
-            // names instead of the full path.
-            for (Iterator<Jar> cp = getClasspath().iterator(); cp.hasNext();) {
-                Jar entry = cp.next();
-                if (entry.source != null && entry.source.getName().equals(name)) {
-                    return entry;
-                }
-            }
-            // error("Can not find jar file for " + from + ": " + name);
-        }
-        return null;
-    }
-
-    private String fileName(String path) {
-        int n = path.lastIndexOf('/');
-        if (n > 0)
-            return path.substring(n + 1);
-        return path;
-    }
-
-    /**
-     * 
-     * @param manifest
-     * @throws Exception
-     */
-    void merge(Manifest result, Manifest old) throws IOException {
-        if (old != null) {
-            for (Iterator<Map.Entry<Object, Object>> e = old
-                    .getMainAttributes().entrySet().iterator(); e.hasNext();) {
-                Map.Entry<Object, Object> entry = e.next();
-                Attributes.Name name = (Attributes.Name) entry.getKey();
-                String value = (String) entry.getValue();
-                if (name.toString().equalsIgnoreCase("Created-By"))
-                    name = new Attributes.Name("Originally-Created-By");
-                if (!result.getMainAttributes().containsKey(name))
-                    result.getMainAttributes().put(name, value);
-            }
-
-            // do not overwrite existing entries
-            Map<String, Attributes> oldEntries = old.getEntries();
-            Map<String, Attributes> newEntries = result.getEntries();
-            for (Iterator<Map.Entry<String, Attributes>> e = oldEntries
-                    .entrySet().iterator(); e.hasNext();) {
-                Map.Entry<String, Attributes> entry = e.next();
-                if (!newEntries.containsKey(entry.getKey())) {
-                    newEntries.put(entry.getKey(), entry.getValue());
-                }
-            }
-        }
-    }
-
-    /**
-     * Print the Service-Component properties element
-     * 
-     * @param pw
-     * @param info
-     */
-    void properties(PrintWriter pw, Map<String, String> info) {
-        Collection<String> properties = split(info.get(COMPONENT_PROPERTIES));
-        for (Iterator<String> p = properties.iterator(); p.hasNext();) {
-            String clause = p.next();
-            int n = clause.indexOf('=');
-            if (n <= 0) {
-                error("Not a valid property in service component: " + clause);
-            } else {
-                String type = null;
-                String name = clause.substring(0, n);
-                if (name.indexOf('@') >= 0) {
-                    String parts[] = name.split("@");
-                    name = parts[1];
-                    type = parts[0];
-                }
-                String value = clause.substring(n + 1).trim();
-                // TODO verify validity of name and value.
-                pw.print("<property name='");
-                pw.print(name);
-                pw.print("'");
-
-                if (type != null) {
-                    if (VALID_PROPERTY_TYPES.matcher(type).matches()) {
-                        pw.print(" type='");
-                        pw.print(type);
-                        pw.print("'");
-                    } else {
-                        warning("Invalid property type '" + type
-                                + "' for property " + name);
-                    }
-                }
-
-                String parts[] = value.split("\\s*(\\||\\n)\\s*");
-                if (parts.length > 1) {
-                    pw.println(">");
-                    for (String part : parts) {
-                        pw.println(part);
-                    }
-                    pw.println("</property>");
-                } else {
-                    pw.print(" value='");
-                    pw.print(parts[0]);
-                    pw.print("'/>");
-                }
-            }
-        }
-    }
-
-    /**
-     * @param pw
-     * @param provides
-     */
-    void provides(PrintWriter pw, String provides, boolean servicefactory) {
-        if (provides != null) {
-            if (!servicefactory)
-                pw.println("  <service>");
-            else
-                pw.println("  <service servicefactory='true'>");
-
-            StringTokenizer st = new StringTokenizer(provides, ",");
-            while (st.hasMoreTokens()) {
-                String interfaceName = st.nextToken();
-                pw.println("    <provide interface='" + interfaceName + "'/>");
-                if (!checkClass(interfaceName))
-                    error("Component definition provides a class that is neither imported nor contained: "
-                            + interfaceName);
-            }
-            pw.println("  </service>");
-        }
-    }
-
-    final static Pattern REFERENCE = Pattern.compile("([^(]+)(\\(.+\\))?");
-
-    /**
-     * @param info
-     * @param pw
-     */
-
-    void reference(Map<String, String> info, PrintWriter pw) {
-        Collection<String> dynamic = split(info.get(COMPONENT_DYNAMIC));
-        Collection<String> optional = split(info.get(COMPONENT_OPTIONAL));
-        Collection<String> multiple = split(info.get(COMPONENT_MULTIPLE));
-
-        for (Iterator<Map.Entry<String, String>> r = info.entrySet().iterator(); r
-                .hasNext();) {
-            Map.Entry<String, String> ref = r.next();
-            String referenceName = (String) ref.getKey();
-            String target = null;
-            String interfaceName = (String) ref.getValue();
-            if (interfaceName == null || interfaceName.length() == 0) {
-                error("Invalid Interface Name for references in Service Component: "
-                        + referenceName + "=" + interfaceName);
-            }
-            char c = interfaceName.charAt(interfaceName.length() - 1);
-            if ("?+*~".indexOf(c) >= 0) {
-                if (c == '?' || c == '*' || c == '~')
-                    optional.add(referenceName);
-                if (c == '+' || c == '*')
-                    multiple.add(referenceName);
-                if (c == '+' || c == '*' || c == '?')
-                    dynamic.add(referenceName);
-                interfaceName = interfaceName.substring(0, interfaceName
-                        .length() - 1);
-            }
-
-            // TODO check if the interface is contained or imported
-
-            if (referenceName.endsWith(":")) {
-                if (!SET_COMPONENT_DIRECTIVES.contains(referenceName))
-                    error("Unrecognized directive in Service-Component header: "
-                            + referenceName);
-                continue;
-            }
-
-            Matcher m = REFERENCE.matcher(interfaceName);
-            if (m.matches()) {
-                interfaceName = m.group(1);
-                target = m.group(2);
-            }
-
-            if (!checkClass(interfaceName))
-                error("Component definition refers to a class that is neither imported nor contained: "
-                        + interfaceName);
-
-            pw.print("  <reference name='" + referenceName + "' interface='"
-                    + interfaceName + "'");
-
-            String cardinality = optional.contains(referenceName) ? "0" : "1";
-            cardinality += "..";
-            cardinality += multiple.contains(referenceName) ? "n" : "1";
-            if (!cardinality.equals("1..1"))
-                pw.print(" cardinality='" + cardinality + "'");
-
-            if (Character.isLowerCase(referenceName.charAt(0))) {
-                String z = referenceName.substring(0, 1).toUpperCase()
-                        + referenceName.substring(1);
-                pw.print(" bind='set" + z + "'");
-                // TODO Verify that the methods exist
-
-                // TODO ProSyst requires both a bind and unbind :-(
-                // if ( dynamic.contains(referenceName) )
-                pw.print(" unbind='unset" + z + "'");
-                // TODO Verify that the methods exist
-            }
-            if (dynamic.contains(referenceName)) {
-                pw.print(" policy='dynamic'");
-            }
-
-            if (target != null) {
-                Filter filter = new Filter(target);
-                if (filter.verify() == null)
-                    pw.print(" target='" + filter.toString() + "'");
-                else
-                    error("Target for " + referenceName
-                            + " is not a correct filter: " + target + " "
-                            + filter.verify());
-            }
-            pw.println("/>");
-        }
-    }
-
-    String stem(String name) {
-        int n = name.lastIndexOf('.');
-        if (n > 0)
-            return name.substring(0, n);
-        else
-            return name;
-    }
-
-    /**
-     * Bnd is case sensitive for the instructions so we better check people are
-     * not using an invalid case. We do allow this to set headers that should
-     * not be processed by us but should be used by the framework.
-     * 
-     * @param properties
-     *            Properties to verify.
-     */
-
-    void verifyManifestHeadersCase(Properties properties) {
-        for (Iterator<Object> i = properties.keySet().iterator(); i.hasNext();) {
-            String header = (String) i.next();
-            for (int j = 0; j < headers.length; j++) {
-                if (!headers[j].equals(header)
-                        && headers[j].equalsIgnoreCase(header)) {
-                    warning("Using a standard OSGi header with the wrong case (bnd is case sensitive!), using: "
-                            + header + " and expecting: " + headers[j]);
-                    break;
-                }
-            }
-        }
-    }
-
-    /**
-     * We will add all exports to the imports unless there is a -noimport
-     * directive specified on an export. This directive is skipped for the
-     * manifest.
-     * 
-     * We also remove any version parameter so that augmentImports can do the
-     * version policy.
-     * 
-     */
-    Map<String, Map<String, String>> addExportsToImports(
-            Map<String, Map<String, String>> exports) {
-        Map<String, Map<String, String>> importsFromExports = newHashMap();
-        for (Map.Entry<String, Map<String, String>> packageEntry : exports
-                .entrySet()) {
-            String packageName = packageEntry.getKey();
-            Map<String, String> parameters = packageEntry.getValue();
-            String noimport = (String) parameters.get(NO_IMPORT_DIRECTIVE);
-            if (noimport == null || !noimport.equalsIgnoreCase("true")) {
-                if (parameters.containsKey("version")) {
-                    parameters = newMap(parameters);
-                    parameters.remove("version");
-                }
-                importsFromExports.put(packageName, parameters);
-            }
-        }
-        return importsFromExports;
-    }
-
-    /**
-     * Create the imports/exports by parsing
-     * 
-     * @throws IOException
-     */
-    void analyzeClasspath() throws IOException {
-        classpathExports = newHashMap();
-        for (Iterator<Jar> c = getClasspath().iterator(); c.hasNext();) {
-            Jar current = c.next();
-            checkManifest(current);
-            for (Iterator<String> j = current.getDirectories().keySet()
-                    .iterator(); j.hasNext();) {
-                String dir = j.next();
-                Resource resource = current.getResource(dir + "/packageinfo");
-                if (resource != null) {
-                    InputStream in = resource.openInputStream();
-                    String version = parsePackageInfo(in);
-                    in.close();
-                    setPackageInfo(dir, "version", version);
-                }
-            }
-        }
-    }
-
-    /**
-     * 
-     * @param jar
-     */
-    void checkManifest(Jar jar) {
-        try {
-            Manifest m = jar.getManifest();
-            if (m != null) {
-                String exportHeader = m.getMainAttributes().getValue(
-                        EXPORT_PACKAGE);
-                if (exportHeader != null) {
-                    Map<String, Map<String, String>> exported = parseHeader(exportHeader);
-                    if (exported != null)
-                        classpathExports.putAll(exported);
-                }
-            }
-        } catch (Exception e) {
-            warning("Erroneous Manifest for " + jar + " " + e);
-        }
-    }
-
-    /**
-     * Find some more information about imports in manifest and other places.
-     */
-    void augmentImports() {
-        for (String packageName : imports.keySet()) {
-            setProperty(CURRENT_PACKAGE, packageName);
-            try {
-                Map<String, String> importAttributes = imports.get(packageName);
-                Map<String, String> exporterAttributes = classpathExports
-                        .get(packageName);
-                if (exporterAttributes == null)
-                    exporterAttributes = exports.get(packageName);
-
-                if (exporterAttributes != null) {
-                    augmentVersion(importAttributes, exporterAttributes);
-                    augmentMandatory(importAttributes, exporterAttributes);
-                    if (exporterAttributes.containsKey(IMPORT_DIRECTIVE))
-                        importAttributes.put(IMPORT_DIRECTIVE,
-                                exporterAttributes.get(IMPORT_DIRECTIVE));
-                }
-
-                // Convert any attribute values that have macros.
-                for (String key : importAttributes.keySet()) {
-                    String value = importAttributes.get(key);
-                    if (value.indexOf('$') >= 0) {
-                        value = getReplacer().process(value);
-                        importAttributes.put(key, value);
-                    }
-                }
-
-                // You can add a remove-attribute: directive with a regular
-                // expression for attributes that need to be removed. We also
-                // remove all attributes that have a value of !. This allows
-                // you to use macros with ${if} to remove values.
-                String remove = importAttributes
-                        .remove(REMOVE_ATTRIBUTE_DIRECTIVE);
-                Instruction removeInstr = null;
-
-                if (remove != null)
-                    removeInstr = Instruction.getPattern(remove);
-
-                for (Iterator<Map.Entry<String, String>> i = importAttributes
-                        .entrySet().iterator(); i.hasNext();) {
-                    Map.Entry<String, String> entry = i.next();
-                    if (entry.getValue().equals("!"))
-                        i.remove();
-                    else if (removeInstr != null
-                            && removeInstr.matches((String) entry.getKey()))
-                        i.remove();
-                    else {
-                        // Not removed ...
-                    }
-                }
-
-            } finally {
-                unsetProperty(CURRENT_PACKAGE);
-            }
-        }
-    }
-
-    /**
-     * If we use an import with mandatory attributes we better all use them
-     * 
-     * @param currentAttributes
-     * @param exporter
-     */
-    private void augmentMandatory(Map<String, String> currentAttributes,
-            Map<String, String> exporter) {
-        String mandatory = (String) exporter.get("mandatory:");
-        if (mandatory != null) {
-            String[] attrs = mandatory.split("\\s*,\\s*");
-            for (int i = 0; i < attrs.length; i++) {
-                if (!currentAttributes.containsKey(attrs[i]))
-                    currentAttributes.put(attrs[i], exporter.get(attrs[i]));
-            }
-        }
-    }
-
-    /**
-     * Check if we can augment the version from the exporter.
-     * 
-     * We allow the version in the import to specify a @ which is replaced with
-     * the exporter's version.
-     * 
-     * @param currentAttributes
-     * @param exporter
-     */
-    private void augmentVersion(Map<String, String> currentAttributes,
-            Map<String, String> exporter) {
-
-        String exportVersion = (String) exporter.get("version");
-        if (exportVersion == null)
-            exportVersion = (String) exporter.get("specification-version");
-        if (exportVersion == null)
-            return;
-
-        exportVersion = cleanupVersion(exportVersion);
-
-        setProperty("@", exportVersion);
-
-        String importRange = currentAttributes.get("version");
-        if (importRange != null) {
-            importRange = cleanupVersion(importRange);
-            importRange = getReplacer().process(importRange);
-        } else
-            importRange = getVersionPolicy();
-
-        unsetProperty("@");
-
-        // See if we can borrow the version
-        // we mist replace the ${@} with the version we
-        // found this can be useful if you want a range to start
-        // with the found version.
-        currentAttributes.put("version", importRange);
-    }
-
-    /**
-     * Add the uses clauses
-     * 
-     * @param exports
-     * @param uses
-     * @throws MojoExecutionException
-     */
-    void doUses(Map<String, Map<String, String>> exports,
-            Map<String, Set<String>> uses,
-            Map<String, Map<String, String>> imports) {
-        if ("true".equalsIgnoreCase(getProperty(NOUSES)))
-            return;
-
-        for (Iterator<String> i = exports.keySet().iterator(); i.hasNext();) {
-            String packageName = i.next();
-            setProperty(CURRENT_PACKAGE, packageName);
-            try {
-                Map<String, String> clause = exports.get(packageName);
-                String override = clause.get(USES_DIRECTIVE);
-                if (override == null)
-                    override = USES_USES;
-
-                Set<String> usedPackages = uses.get(packageName);
-                if (usedPackages != null) {
-                    // Only do a uses on exported or imported packages
-                    // and uses should also not contain our own package
-                    // name
-                    Set<String> sharedPackages = new HashSet<String>();
-                    sharedPackages.addAll(imports.keySet());
-                    sharedPackages.addAll(exports.keySet());
-                    usedPackages.retainAll(sharedPackages);
-                    usedPackages.remove(packageName);
-
-                    StringBuffer sb = new StringBuffer();
-                    String del = "";
-                    for (Iterator<String> u = usedPackages.iterator(); u
-                            .hasNext();) {
-                        String usedPackage = u.next();
-                        if (!usedPackage.startsWith("java.")) {
-                            sb.append(del);
-                            sb.append(usedPackage);
-                            del = ",";
-                        }
-                    }
-                    if (override.indexOf('$') >= 0) {
-                        setProperty(CURRENT_USES, sb.toString());
-                        override = getReplacer().process(override);
-                        unsetProperty(CURRENT_USES);
-                    } else
-                        // This is for backward compatibility 0.0.287
-                        // can be deprecated over time
-                        override = override
-                                .replaceAll(USES_USES, sb.toString()).trim();
-                    if (override.endsWith(","))
-                        override = override.substring(0, override.length() - 1);
-                    if (override.startsWith(","))
-                        override = override.substring(1);
-                    if (override.length() > 0) {
-                        clause.put("uses:", override);
-                    }
-                }
-            } finally {
-                unsetProperty(CURRENT_PACKAGE);
-            }
-        }
-    }
-
-    /**
-     * Transitively remove all elemens from unreachable through the uses link.
-     * 
-     * @param name
-     * @param unreachable
-     */
-    void removeTransitive(String name, Set<String> unreachable) {
-        if (!unreachable.contains(name))
-            return;
-
-        unreachable.remove(name);
-
-        Set<String> ref = uses.get(name);
-        if (ref != null) {
-            for (Iterator<String> r = ref.iterator(); r.hasNext();) {
-                String element = (String) r.next();
-                removeTransitive(element, unreachable);
-            }
-        }
-    }
-
-    /**
-     * Helper method to set the package info
-     * 
-     * @param dir
-     * @param key
-     * @param value
-     */
-    void setPackageInfo(String dir, String key, String value) {
-        if (value != null) {
-            String pack = dir.replace('/', '.');
-            Map<String, String> map = classpathExports.get(pack);
-            if (map == null) {
-                map = new HashMap<String, String>();
-                classpathExports.put(pack, map);
-            }
-            map.put(key, value);
-        }
-    }
-
-    public void close() {
-        super.close();
-        if (dot != null)
-            dot.close();
-
-        if (classpath != null)
-            for (Iterator<Jar> j = classpath.iterator(); j.hasNext();) {
-                Jar jar = j.next();
-                jar.close();
-            }
-    }
-
-    /**
-     * Findpath looks through the contents of the JAR and finds paths that end
-     * with the given regular expression
-     * 
-     * ${findpath (; reg-expr (; replacement)? )? }
-     * 
-     * @param args
-     * @return
-     */
-    public String _findpath(String args[]) {
-        return findPath("findpath", args, true);
-    }
-
-    public String _findname(String args[]) {
-        return findPath("findname", args, false);
-    }
-
-    String findPath(String name, String[] args, boolean fullPathName) {
-        if (args.length > 3) {
-            warning("Invalid nr of arguments to " + name + " "
-                    + Arrays.asList(args) + ", syntax: ${" + name
-                    + " (; reg-expr (; replacement)? )? }");
-            return null;
-        }
-
-        String regexp = ".*";
-        String replace = null;
-
-        switch (args.length) {
-        case 3:
-            replace = args[2];
-        case 2:
-            regexp = args[1];
-        }
-        StringBuffer sb = new StringBuffer();
-        String del = "";
-
-        Pattern expr = Pattern.compile(regexp);
-        for (Iterator<String> e = dot.getResources().keySet().iterator(); e
-                .hasNext();) {
-            String path = e.next();
-            if (!fullPathName) {
-                int n = path.lastIndexOf('/');
-                if (n >= 0) {
-                    path = path.substring(n + 1);
-                }
-            }
-
-            Matcher m = expr.matcher(path);
-            if (m.matches()) {
-                if (replace != null)
-                    path = m.replaceAll(replace);
-
-                sb.append(del);
-                sb.append(path);
-                del = ", ";
-            }
-        }
-        return sb.toString();
-    }
-
-    public void putAll(Map<String, String> additional, boolean force) {
-        for (Iterator<Map.Entry<String, String>> i = additional.entrySet()
-                .iterator(); i.hasNext();) {
-            Map.Entry<String, String> entry = i.next();
-            if (force || getProperties().get(entry.getKey()) == null)
-                setProperty((String) entry.getKey(), (String) entry.getValue());
-        }
-    }
-
-    boolean firstUse = true;
-
-    public List<Jar> getClasspath() {
-        if (firstUse) {
-            firstUse = false;
-            String cp = getProperty(CLASSPATH);
-            if (cp != null)
-                for (String s : split(cp)) {
-                    Jar jar = getJarFromName(s, "getting classpath");
-                    if (jar != null)
-                        addClasspath(jar);
-                }
-        }
-        return classpath;
-    }
-
-    public void addClasspath(Jar jar) {
-        if (isPedantic() && jar.getResources().isEmpty())
-            warning("There is an empty jar or directory on the classpath: "
-                    + jar.getName());
-
-        classpath.add(jar);
-    }
-
-    public void addClasspath(File cp) throws IOException {
-        if (!cp.exists())
-            warning("File on classpath that does not exist: " + cp);
-        Jar jar = new Jar(cp);
-        addClose(jar);
-        classpath.add(jar);
-    }
-
-    public void clear() {
-        classpath.clear();
-    }
-
-    public Jar getTarget() {
-        return dot;
-    }
-
-    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 {
-        Map<String, Clazz> classSpace = new HashMap<String, Clazz>();
-
-        if (bundleClasspath.isEmpty()) {
-            analyzeJar(dot, "", classSpace, contained, referred, uses);
-        } else {
-            for (String path : bundleClasspath.keySet()) {
-                if (path.equals(".")) {
-                    analyzeJar(dot, "", classSpace, contained, referred, uses);
-                    continue;
-                }
-                //
-                // There are 3 cases:
-                // - embedded JAR file
-                // - directory
-                // - error
-                //
-
-                Resource resource = dot.getResource(path);
-                if (resource != null) {
-                    try {
-                        Jar jar = new Jar(path);
-                        addClose(jar);
-                        EmbeddedResource.build(jar, resource);
-                        analyzeJar(jar, "", classSpace, contained, referred,
-                                uses);
-                    } catch (Exception e) {
-                        warning("Invalid bundle classpath entry: " + path + " "
-                                + e);
-                    }
-                } else {
-                    if (dot.getDirectories().containsKey(path)) {
-                        analyzeJar(dot, path + '/', classSpace, contained, referred,
-                                uses);
-                    } else {
-                        warning("No sub JAR or directory " + path);
-                    }
-                }
-            }
-        }
-        return classSpace;
-    }
-
-    /**
-     * We traverse through all the classes that we can find and calculate the
-     * contained and referred set and uses. This method ignores the Bundle
-     * classpath.
-     * 
-     * @param jar
-     * @param contained
-     * @param referred
-     * @param uses
-     * @throws IOException
-     */
-    private void analyzeJar(Jar jar, String prefix,
-            Map<String, Clazz> classSpace,
-            Map<String, Map<String, String>> contained,
-            Map<String, Map<String, String>> referred,
-            Map<String, Set<String>> uses) throws IOException {
-
-        next: for (String path : jar.getResources().keySet()) {
-            if (path.startsWith(prefix)) {
-                String relativePath = path.substring(prefix.length());
-                String pack = getPackage(relativePath);
-
-                if (pack != null && !contained.containsKey(pack)) {
-                    if (!isMetaData(relativePath)) {
-
-                        Map<String, String> map = new LinkedHashMap<String, String>();
-                        contained.put(pack, map);
-                        Resource pinfo = jar.getResource(prefix
-                                + pack.replace('.', '/') + "/packageinfo");
-                        if (pinfo != null) {
-                            InputStream in = pinfo.openInputStream();
-                            String version = parsePackageInfo(in);
-                            in.close();
-                            if (version != null)
-                                map.put("version", version);
-                        }
-                    }
-                }
-
-                if (path.endsWith(".class")) {
-                    Resource resource = jar.getResource(path);
-                    Clazz clazz;
-
-                    try {
-                        InputStream in = resource.openInputStream();
-                        clazz = new Clazz(relativePath, in);
-                        in.close();
-                    } catch (Throwable e) {
-                        error("Invalid class file: " + relativePath, e);
-                        e.printStackTrace();
-                        continue next;
-                    }
-
-                    String calculatedPath = clazz.getClassName() + ".class";
-                    if (!calculatedPath.equals(relativePath))
-                        error("Class in different directory than declared. Path from class name is "
-                                + calculatedPath
-                                + " but the path in the jar is "
-                                + relativePath
-                                + " from " + jar);
-
-                    classSpace.put(relativePath, clazz);
-                    referred.putAll(clazz.getReferred());
-
-                    // Add all the used packages
-                    // to this package
-                    Set<String> t = uses.get(pack);
-                    if (t == null)
-                        uses.put(pack, t = new LinkedHashSet<String>());
-                    t.addAll(clazz.getReferred().keySet());
-                    t.remove(pack);
-                }
-            }
-        }
-    }
-
-    /**
-     * 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_STRING
-     * @return
-     */
-    static Pattern fuzzyVersion      = Pattern
-                                             .compile(
-                                                     "(\\d+)(\\.(\\d+)(\\.(\\d+))?)?([^a-zA-Z0-9](.*))?",
-                                                     Pattern.DOTALL);
-    static Pattern fuzzyVersionRange = Pattern
-                                             .compile(
-                                                     "(\\(|\\[)\\s*([-\\da-zA-Z.]+)\\s*,\\s*([-\\da-zA-Z.]+)\\s*(\\]|\\))",
-                                                     Pattern.DOTALL);
-    static Pattern fuzzyModifier     = Pattern.compile("(\\d+[.-])*(.*)",
-                                             Pattern.DOTALL);
-
-    static Pattern nummeric          = Pattern.compile("\\d*");
-
-    static public String cleanupVersion(String version) {
-        if (Verifier.VERSIONRANGE.matcher(version).matches())
-            return version;
-
-        Matcher m = fuzzyVersionRange.matcher(version);
-        if (m.matches()) {
-            String prefix = m.group(1);
-            String first = m.group(2);
-            String last = m.group(3);
-            String suffix = m.group(4);
-            return prefix + cleanupVersion(first) + "," + cleanupVersion(last)
-                    + suffix;
-        } else {
-            m = fuzzyVersion.matcher(version);
-            if (m.matches()) {
-                StringBuffer result = new StringBuffer();
-                String major = m.group(1);
-                String minor = m.group(3);
-                String micro = m.group(5);
-                String qualifier = m.group(7);
-
-                if (major != null) {
-                    result.append(major);
-                    if (minor != null) {
-                        result.append(".");
-                        result.append(minor);
-                        if (micro != null) {
-                            result.append(".");
-                            result.append(micro);
-                            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);
-        }
-    }
-
-    /**
-     * Decide if the package is a metadata package.
-     * 
-     * @param pack
-     * @return
-     */
-    boolean isMetaData(String pack) {
-        for (int i = 0; i < METAPACKAGES.length; i++) {
-            if (pack.startsWith(METAPACKAGES[i]))
-                return true;
-        }
-        return false;
-    }
-
-    public String getPackage(String clazz) {
-        int n = clazz.lastIndexOf('/');
-        if (n < 0)
-            return ".";
-        return clazz.substring(0, n).replace('/', '.');
-    }
-
-    //
-    // We accept more than correct OSGi versions because in a later
-    // phase we actually cleanup maven versions. But it is a bit yucky
-    //
-    static String parsePackageInfo(InputStream jar) throws IOException {
-        try {
-            Properties p = new Properties();
-            p.load(jar);
-            jar.close();
-            if (p.containsKey("version")) {
-                return p.getProperty("version");
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return null;
-    }
-
-    public String getVersionPolicy() {
-        return getProperty(VERSIONPOLICY, "${version;==;${@}}");
-    }
-
-    /**
-     * The extends macro traverses all classes and returns a list of class names
-     * that extend a base class.
-     */
-
-    static String _classesHelp = "${classes;'implementing'|'extending'|'importing'|'named'|'version'|'any';<pattern>}, Return a list of class fully qualified class names that extend/implement/import any of the contained classes matching the pattern\n";
-
-    public String _classes(String args[]) {
-        // Macro.verifyCommand(args, _classesHelp, new
-        // Pattern[]{null,Pattern.compile("(implementing|implements|extending|extends|importing|imports|any)"),
-        // null}, 3,3);
-        Set<Clazz> matched = new HashSet<Clazz>(classspace.values());
-        for (int i = 1; i < args.length; i += 2) {
-            if (args.length < i + 1)
-                throw new IllegalArgumentException(
-                        "${classes} macro must have odd number of arguments. "
-                                + _classesHelp);
-
-            String typeName = args[i];
-            Clazz.QUERY type = null;
-            if (typeName.equals("implementing")
-                    || typeName.equals("implements"))
-                type = Clazz.QUERY.IMPLEMENTS;
-            else if (typeName.equals("extending") || typeName.equals("extends"))
-                type = Clazz.QUERY.EXTENDS;
-            else if (typeName.equals("importing") || typeName.equals("imports"))
-                type = Clazz.QUERY.IMPORTS;
-            else if (typeName.equals("all"))
-                type = Clazz.QUERY.ANY;
-            else if (typeName.equals("version"))
-                type = Clazz.QUERY.VERSION;
-            else if (typeName.equals("named"))
-                type = Clazz.QUERY.NAMED;
-
-            if (type == null)
-                throw new IllegalArgumentException(
-                        "${classes} has invalid type: " + typeName + ". "
-                                + _classesHelp);
-            // The argument is declared as a dotted name but the classes
-            // use a slashed named. So convert the name before we make it a
-            // instruction.
-            String pattern = args[i + 1].replace('.', '/');
-            Instruction instr = Instruction.getPattern(pattern);
-
-            for (Iterator<Clazz> c = matched.iterator(); c.hasNext();) {
-                Clazz clazz = c.next();
-                if (!clazz.is(type, instr, classspace))
-                    c.remove();
-            }
-        }
-        if (matched.isEmpty())
-            return "";
-
-        return join(matched);
-    }
-
-    /**
-     * Get the exporter of a package ...
-     */
-
-    public String _exporters(String args[]) throws Exception {
-        Macro
-                .verifyCommand(
-                        args,
-                        "${exporters;<packagename>}, returns the list of jars that export the given package",
-                        null, 2, 2);
-        StringBuilder sb = new StringBuilder();
-        String del = "";
-        String pack = args[1].replace('.', '/');
-        for (Jar jar : classpath) {
-            if (jar.getDirectories().containsKey(pack)) {
-                sb.append(del);
-                sb.append(jar.getName());
-            }
-        }
-        return sb.toString();
-    }
-
-    public Map<String, Clazz> getClassspace() {
-        return classspace;
-    }
-
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java b/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
deleted file mode 100644
index 84c35e6..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
+++ /dev/null
@@ -1,1131 +0,0 @@
-/* Copyright 2006 aQute SARL 
- * Licensed under the Apache License, Version 2.0, see http://www.apache.org/licenses/LICENSE-2.0 */
-package aQute.lib.osgi;
-
-import java.io.*;
-import java.security.*;
-import java.security.cert.*;
-import java.security.spec.*;
-import java.util.*;
-import java.util.jar.*;
-import java.util.regex.*;
-import java.util.zip.*;
-
-import aQute.bnd.make.*;
-import aQute.lib.signing.*;
-
-/**
- * Include-Resource: ( [name '=' ] file )+
- * 
- * Private-Package: package-decl ( ',' package-decl )*
- * 
- * Export-Package: package-decl ( ',' package-decl )*
- * 
- * Import-Package: package-decl ( ',' package-decl )*
- * 
- * @version $Revision: 1.4 $
- */
-public class Builder extends Analyzer {
-    private static final int SPLIT_MERGE_LAST  = 1;
-    private static final int SPLIT_MERGE_FIRST = 2;
-    private static final int SPLIT_ERROR       = 3;
-    private static final int SPLIT_FIRST       = 4;
-    private static final int SPLIT_DEFAULT     = 0;
-
-    List<File>               sourcePath        = new ArrayList<File>();
-    Pattern                  NAME_URL          = Pattern
-                                                       .compile("(.*)(http://.*)");
-
-    Make                     make              = new Make(this);
-    private KeyStore         keystore;
-
-    public Builder(Processor parent) {
-        super(parent);
-    }
-
-    public Builder() {
-    }
-
-    public Jar build() throws Exception {
-        if (getProperty(NOPE) != null)
-            return null;
-
-        String sub = getProperty(SUB);
-        if (sub != null && sub.trim().length() > 0)
-            error("Specified "
-                    + SUB
-                    + " but calls build() instead of builds() (might be a programmer error)");
-
-        if (getProperty(CONDUIT) != null)
-            error("Specified "
-                    + CONDUIT
-                    + " but calls build() instead of builds() (might be a programmer error");
-
-        dot = new Jar("dot");
-        addClose(dot);
-        try {
-            long modified = Long.parseLong(getProperty("base.modified"));
-            dot.updateModified(modified, "Base modified");
-        } catch (Exception e) {
-        }
-
-        doExpand(dot);
-        doIncludeResources(dot);
-
-        doConditional(dot);
-
-        // NEW!
-        // Check if we override the calculation of the
-        // manifest. We still need to calculated it because
-        // we need to have analyzed the classpath.
-
-        Manifest manifest = calcManifest();
-
-        String mf = getProperty(MANIFEST);
-        if (mf != null) {
-            File mff = getFile(mf);
-            if (mff.isFile()) {
-                try {
-                    InputStream in = new FileInputStream(mff);
-                    manifest = new Manifest(in);
-                    in.close();
-                } catch (Exception e) {
-                    error(MANIFEST + " while reading manifest file", e);
-                }
-            } else {
-                error(MANIFEST + ", no such file " + mf);
-            }
-        }
-
-        dot.setManifest(manifest);
-
-        // This must happen after we analyzed so
-        // we know what it is on the classpath
-        addSources(dot);
-        if (getProperty(POM) != null)
-            doPom(dot);
-
-        doVerify(dot);
-
-        if (dot.getResources().isEmpty())
-            error("The JAR is empty");
-
-        dot.updateModified(lastModified(), "Last Modified Processor");
-        dot.setName(getBsn());
-
-        sign(dot);
-        return dot;
-    }
-
-    /**
-     * Sign the jar file.
-     * 
-     * -sign : <alias> [ ';' 'password:=' <password> ] [ ';' 'keystore:='
-     * <keystore> ] [ ';' 'sign-password:=' <pw> ] ( ',' ... )*
-     * 
-     * @return
-     */
-
-    void sign(Jar jar) throws Exception {
-        String signing = getProperty("-sign");
-        if (signing == null)
-            return;
-
-        trace("Signing %s, with %s", getBsn(), signing);
-
-        Map<String, Map<String, String>> infos = parseHeader(signing);
-        for (Map.Entry<String, Map<String, String>> entry : infos.entrySet()) {
-            String alias = entry.getKey();
-            String keystoreLocation = entry.getValue().get(
-                    KEYSTORE_LOCATION_DIRECTIVE);
-            String keystoreProvider = entry.getValue().get(
-                    KEYSTORE_PROVIDER_DIRECTIVE);
-            String password = entry.getValue().get(KEYSTORE_PASSWORD_DIRECTIVE);
-            String signpassword = entry.getValue().get(SIGN_PASSWORD_DIRECTIVE);
-            KeyStore keystore = getKeystore(keystoreLocation, keystoreProvider,
-                    password);
-            if (keystore == null) {
-                error(
-                        "Cannot find keystore to sign bundle: location=%s,  provider=%s",
-                        keystoreLocation, keystoreProvider);
-            } else {
-                if (signpassword == null && !"-none".equals(signpassword))
-                    signpassword = password;
-
-                X509Certificate chain[] = getChain(keystore, alias);
-                if (chain == null) {
-                    error(
-                            "Trying to sign bundle but no signing certificate found: %s",
-                            alias);
-                    continue;
-                }
-
-                try {
-                    Key key = keystore.getKey(alias,
-                            (signpassword == null ? null : signpassword
-                                    .toCharArray()));
-                    KeyFactory keyFactory = KeyFactory.getInstance(key
-                            .getAlgorithm());
-                    KeySpec keySpec = keyFactory.getKeySpec(key,
-                            RSAPrivateKeySpec.class);
-                    PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
-
-                    JarSigner signer = new JarSigner(alias, privateKey, chain);
-                    signer.signJar(jar);
-
-                } catch (UnrecoverableKeyException uke) {
-                    error(
-                            "Cannot get key to sign, likely invalid password: %s, for %s : %s",
-                            signpassword, alias, uke);
-                }
-            }
-        }
-    }
-
-    X509Certificate[] getChain(KeyStore keystore, String alias)
-            throws Exception {
-        java.security.cert.Certificate[] chain = keystore
-                .getCertificateChain(alias);
-        X509Certificate certChain[] = new X509Certificate[chain.length];
-
-        CertificateFactory cf = CertificateFactory.getInstance("X.509");
-        for (int count = 0; count < chain.length; count++) {
-            ByteArrayInputStream certIn = new ByteArrayInputStream(chain[count]
-                    .getEncoded());
-            X509Certificate cert = (X509Certificate) cf
-                    .generateCertificate(certIn);
-            certChain[count] = cert;
-        }
-        return certChain;
-    }
-
-    KeyStore getKeystore(String keystoreLocation, String keystoreProvider,
-            String password) throws Exception {
-        if (keystoreLocation == null) {
-            return getKeystore();
-        }
-        if (keystoreProvider == null)
-            keystoreProvider = "JKS";
-
-        KeyStore keystore = KeyStore.getInstance(keystoreProvider);
-        FileInputStream in = new FileInputStream(keystoreLocation);
-        try {
-            keystore.load(in, password == null ? null : password.toCharArray());
-        } finally {
-            in.close();
-        }
-        return keystore;
-    }
-
-    KeyStore getKeystore() throws Exception {
-        if (keystore != null) {
-            return keystore;
-        }
-
-        Map<String, Map<String, String>> header = parseHeader(getProperty(
-                "-keystore", "../cnf/keystore"));
-        if (header.size() == 0) {
-            error("Keystore needed but no -keystore specified");
-            return null;
-        }
-
-        if (header.size() > 1) {
-            warning("Multiple keystores specified, can only specify one: %s",
-                    header);
-        }
-        for (Map.Entry<String, Map<String, String>> entry : header.entrySet()) {
-            return keystore = getKeystore(entry.getKey(), entry.getValue().get(
-                    "provider:"), entry.getValue().get("password:"));
-        }
-        return null;
-    }
-
-    public boolean hasSources() {
-        return isTrue(getProperty(SOURCES));
-    }
-
-    protected String getImportPackages() {
-        String ip = super.getImportPackages();
-        if (ip != null)
-            return ip;
-
-        return "*";
-    }
-
-    private void doConditional(Jar dot) throws IOException {
-        Map<String, Map<String, String>> conditionals = getHeader(CONDITIONAL_PACKAGE);
-        int size;
-        do {
-            size = dot.getDirectories().size();
-            analyze();
-            analyzed = false;
-            Map<String, Map<String, String>> imports = getImports();
-
-            // Match the packages specified in conditionals
-            // against the imports. Any match must become a
-            // Private-Package
-            Map<String, Map<String, String>> filtered = merge(
-                    CONDITIONAL_PACKAGE, conditionals, imports,
-                    new HashSet<String>(), null);
-
-            // Imports can also specify a private import. These
-            // packages must also be copied to the bundle
-            for (Map.Entry<String, Map<String, String>> entry : getImports()
-                    .entrySet()) {
-                String type = entry.getValue().get("import:");
-                if (type != null && type.equals("private"))
-                    filtered.put(entry.getKey(), entry.getValue());
-            }
-
-            // remove existing packages to prevent merge errors
-            filtered.keySet().removeAll(dot.getPackages());
-            doExpand(dot, CONDITIONAL_PACKAGE + " Private imports",
-                    replaceWitInstruction(filtered, CONDITIONAL_PACKAGE), false);
-        } while (dot.getDirectories().size() > size);
-        analyzed = true;
-    }
-
-    /**
-     * Intercept the call to analyze and cleanup versions after we have analyzed
-     * the setup. We do not want to cleanup if we are going to verify.
-     */
-
-    public void analyze() throws IOException {
-        super.analyze();
-        cleanupVersion(imports);
-        cleanupVersion(exports);
-        String version = getProperty(BUNDLE_VERSION);
-        if (version != null)
-            setProperty(BUNDLE_VERSION, cleanupVersion(version));
-    }
-
-    public void cleanupVersion(Map<String, Map<String, String>> mapOfMap) {
-        for (Iterator<Map.Entry<String, Map<String, String>>> e = mapOfMap
-                .entrySet().iterator(); e.hasNext();) {
-            Map.Entry<String, Map<String, String>> entry = e.next();
-            Map<String, String> attributes = entry.getValue();
-            if (attributes.containsKey("version")) {
-                attributes.put("version", cleanupVersion(attributes
-                        .get("version")));
-            }
-        }
-    }
-
-    /**
-     * 
-     */
-    private void addSources(Jar dot) {
-        if (!hasSources())
-            return;
-
-        Set<String> packages = new HashSet<String>();
-
-        try {
-            ByteArrayOutputStream out = new ByteArrayOutputStream();
-            getProperties().store(out, "Generated by BND, at " + new Date());
-            dot.putResource("OSGI-OPT/bnd.bnd", new EmbeddedResource(out
-                    .toByteArray(), 0));
-            out.close();
-        } catch (Exception e) {
-            error("Can not embed bnd file in JAR: " + e);
-        }
-
-        for (Iterator<String> cpe = classspace.keySet().iterator(); cpe
-                .hasNext();) {
-            String path = cpe.next();
-            path = path.substring(0, path.length() - ".class".length())
-                    + ".java";
-            String pack = getPackage(path).replace('.', '/');
-            if (pack.length() > 1)
-                pack = pack + "/";
-            boolean found = false;
-            String[] fixed = { "packageinfo", "package.html",
-                    "module-info.java", "package-info.java" };
-            for (Iterator<File> i = getSourcePath().iterator(); i.hasNext();) {
-                File root = i.next();
-                File f = getFile(root, path);
-                if (f.exists()) {
-                    found = true;
-                    if (!packages.contains(pack)) {
-                        packages.add(pack);
-                        File bdir = getFile(root, pack);
-                        for (int j = 0; j < fixed.length; j++) {
-                            File ff = getFile(bdir, fixed[j]);
-                            if (ff.isFile()) {
-                                dot.putResource("OSGI-OPT/src/" + pack
-                                        + fixed[j], new FileResource(ff));
-                            }
-                        }
-                    }
-                    dot
-                            .putResource("OSGI-OPT/src/" + path,
-                                    new FileResource(f));
-                }
-            }
-            if (!found) {
-                for (Jar jar : classpath) {
-                    Resource resource = jar.getResource(path);
-                    if (resource != null) {
-                        dot.putResource("OSGI-OPT/src", resource);
-                    } else {
-                        resource = jar.getResource("OSGI-OPT/src/" + path);
-                        if (resource != null) {
-                            dot.putResource("OSGI-OPT/src", resource);
-                        }
-                    }
-                }
-            }
-            if (getSourcePath().isEmpty())
-                warning("Including sources but " + SOURCEPATH
-                        + " does not contain any source directories ");
-            // TODO copy from the jars where they came from
-        }
-    }
-
-    boolean firstUse = true;
-
-    public Collection<File> getSourcePath() {
-        if (firstUse) {
-            firstUse = false;
-            String sp = getProperty(SOURCEPATH);
-            if (sp != null) {
-                Map<String, Map<String, String>> map = parseHeader(sp);
-                for (Iterator<String> i = map.keySet().iterator(); i.hasNext();) {
-                    String file = i.next();
-                    if (!isDuplicate(file)) {
-                        File f = getFile(file);
-                        if (!f.isDirectory()) {
-                            error("Adding a sourcepath that is not a directory: "
-                                    + f);
-                        } else {
-                            sourcePath.add(f);
-                        }
-                    }
-                }
-            }
-        }
-        return sourcePath;
-    }
-
-    private void doVerify(Jar dot) throws Exception {
-        Verifier verifier = new Verifier(dot, getProperties());
-        verifier.setPedantic(isPedantic());
-
-        // Give the verifier the benefit of our analysis
-        // prevents parsing the files twice
-        verifier.setClassSpace(classspace, contained, referred, uses);
-        verifier.verify();
-        getInfo(verifier);
-    }
-
-    private void doExpand(Jar jar) throws IOException {
-        if (getClasspath().size() == 0
-                && (getProperty(EXPORT_PACKAGE) != null || getProperty(PRIVATE_PACKAGE) != null))
-            warning("Classpath is empty. Private-Package and Export-Package can only expand from the classpath when there is one");
-
-        Map<Instruction, Map<String, String>> all = newMap();
-
-        all.putAll(replaceWitInstruction(getHeader(PRIVATE_PACKAGE),
-                PRIVATE_PACKAGE));
-
-        all.putAll(replaceWitInstruction(getHeader(EXPORT_PACKAGE),
-                EXPORT_PACKAGE));
-
-        if (isTrue(getProperty(Constants.UNDERTEST))) {
-            all.putAll(replaceWitInstruction(parseHeader(getProperty(
-                    Constants.TESTPACKAGES, "test;presence:=optional")),
-                    TESTPACKAGES));
-        }
-
-        if (all.isEmpty() && !isResourceOnly()) {
-            warning("Neither Export-Package, Private-Package, -testpackages is set, therefore no packages will be included");
-        }
-
-        doExpand(jar, "Export-Package, Private-Package, or -testpackages", all,
-                true);
-    }
-
-    /**
-     * 
-     * @param jar
-     * @param name
-     * @param instructions
-     */
-    private void doExpand(Jar jar, String name,
-            Map<Instruction, Map<String, String>> instructions,
-            boolean mandatory) {
-        Set<Instruction> superfluous = removeMarkedDuplicates(instructions
-                .keySet());
-
-        for (Iterator<Jar> c = getClasspath().iterator(); c.hasNext();) {
-            Jar now = c.next();
-            doExpand(jar, instructions, now, superfluous);
-        }
-
-        if (mandatory && superfluous.size() > 0) {
-            StringBuffer sb = new StringBuffer();
-            String del = "Instructions in " + name + " that are never used: ";
-            for (Iterator<Instruction> i = superfluous.iterator(); i.hasNext();) {
-                Instruction p = i.next();
-                sb.append(del);
-                sb.append(p.getPattern());
-                del = ", ";
-            }
-            warning(sb.toString());
-        }
-    }
-
-    /**
-     * Iterate over each directory in the class path entry and check if that
-     * directory is a desired package.
-     * 
-     * @param included
-     * @param classpathEntry
-     */
-    private void doExpand(Jar jar,
-            Map<Instruction, Map<String, String>> included, Jar classpathEntry,
-            Set<Instruction> superfluous) {
-
-        loop: for (Map.Entry<String, Map<String, Resource>> directory : classpathEntry
-                .getDirectories().entrySet()) {
-            String path = directory.getKey();
-
-            if (doNotCopy.matcher(getName(path)).matches())
-                continue;
-
-            if (directory.getValue() == null)
-                continue;
-
-            String pack = path.replace('/', '.');
-            Instruction instr = matches(included, pack, superfluous);
-            if (instr != null) {
-                // System.out.println("Pattern match: " + pack + " " +
-                // instr.getPattern() + " " + instr.isNegated());
-                if (!instr.isNegated()) {
-                    Map<String, Resource> contents = directory.getValue();
-
-                    // What to do with split packages? Well if this
-                    // directory already exists, we will check the strategy
-                    // and react accordingly.
-                    boolean overwriteResource = true;
-                    if (jar.hasDirectory(path)) {
-                        Map<String, String> directives = included.get(instr);
-
-                        switch (getSplitStrategy((String) directives
-                                .get(SPLIT_PACKAGE_DIRECTIVE))) {
-                        case SPLIT_MERGE_LAST:
-                            overwriteResource = true;
-                            break;
-
-                        case SPLIT_MERGE_FIRST:
-                            overwriteResource = false;
-                            break;
-
-                        case SPLIT_ERROR:
-                            error(diagnostic(pack, getClasspath(),
-                                    classpathEntry.source));
-                            continue loop;
-
-                        case SPLIT_FIRST:
-                            continue loop;
-
-                        default:
-                            warning(diagnostic(pack, getClasspath(),
-                                    classpathEntry.source));
-                            overwriteResource = false;
-                            break;
-                        }
-                    }
-
-                    jar.addDirectory(contents, overwriteResource);
-
-                    String key = path + "/bnd.info";
-                    Resource r = jar.getResource(key);
-                    if (r != null)
-                        jar.putResource(key, new PreprocessResource(this, r));
-
-                    if (hasSources()) {
-                        String srcPath = "OSGI-INF/src/" + path;
-                        Map<String, Resource> srcContents = classpathEntry
-                                .getDirectories().get(srcPath);
-                        if (srcContents != null) {
-                            jar.addDirectory(srcContents, overwriteResource);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Analyze the classpath for a split package
-     * 
-     * @param pack
-     * @param classpath
-     * @param source
-     * @return
-     */
-    private String diagnostic(String pack, List<Jar> classpath, File source) {
-        // Default is like merge-first, but with a warning
-        // Find the culprits
-        pack = pack.replace('.', '/');
-        List<Jar> culprits = new ArrayList<Jar>();
-        for (Iterator<Jar> i = classpath.iterator(); i.hasNext();) {
-            Jar culprit = (Jar) i.next();
-            if (culprit.getDirectories().containsKey(pack)) {
-                culprits.add(culprit);
-            }
-        }
-        return "Split package "
-                + pack
-                + "\nUse directive -split-package:=(merge-first|merge-last|error|first) on Export/Private Package instruction to get rid of this warning\n"
-                + "Package found in   " + culprits + "\n"
-                + "Reference from     " + source + "\n" + "Classpath          "
-                + classpath;
-    }
-
-    private int getSplitStrategy(String type) {
-        if (type == null)
-            return SPLIT_DEFAULT;
-
-        if (type.equals("merge-last"))
-            return SPLIT_MERGE_LAST;
-
-        if (type.equals("merge-first"))
-            return SPLIT_MERGE_FIRST;
-
-        if (type.equals("error"))
-            return SPLIT_ERROR;
-
-        if (type.equals("first"))
-            return SPLIT_FIRST;
-
-        error("Invalid strategy for split-package: " + type);
-        return SPLIT_DEFAULT;
-    }
-
-    private Map<Instruction, Map<String, String>> replaceWitInstruction(
-            Map<String, Map<String, String>> header, String type) {
-        Map<Instruction, Map<String, String>> map = newMap();
-        for (Iterator<Map.Entry<String, Map<String, String>>> e = header
-                .entrySet().iterator(); e.hasNext();) {
-            Map.Entry<String, Map<String, String>> entry = e.next();
-            String pattern = entry.getKey();
-            Instruction instr = Instruction.getPattern(pattern);
-            String presence = entry.getValue().get(PRESENCE_DIRECTIVE);
-            if ("optional".equals(presence))
-                instr.setOptional();
-            map.put(instr, entry.getValue());
-        }
-        return map;
-    }
-
-    private Instruction matches(
-            Map<Instruction, Map<String, String>> instructions, String pack,
-            Set<Instruction> superfluousPatterns) {
-        for (Instruction pattern : instructions.keySet()) {
-            if (pattern.matches(pack)) {
-                superfluousPatterns.remove(pattern);
-                return pattern;
-            }
-        }
-        return null;
-    }
-
-    private Map<String, Map<String, String>> getHeader(String string) {
-        if (string == null)
-            return Collections.emptyMap();
-        return parseHeader(getProperty(string));
-    }
-
-    /**
-     * Parse the Bundle-Includes header. Files in the bundles Include header are
-     * included in the jar. The source can be a directory or a file.
-     * 
-     * @throws IOException
-     * @throws FileNotFoundException
-     */
-    private void doIncludeResources(Jar jar) throws Exception {
-        String includes = getProperty("Bundle-Includes");
-        if (includes == null) {
-            includes = getProperty(INCLUDERESOURCE);
-            if ( includes == null )
-                includes = getProperty("Include-Resource");
-        }
-        else
-            warning("Please use -includeresource instead of Bundle-Includes");
-
-        if (includes == null)
-            return;
-
-        Map<String, Map<String, String>> clauses = parseHeader(includes);
-
-        for (Iterator<Map.Entry<String, Map<String, String>>> i = clauses
-                .entrySet().iterator(); i.hasNext();) {
-            Map.Entry<String, Map<String, String>> entry = i.next();
-            doIncludeResource(jar, entry.getKey(), entry.getValue());
-        }
-    }
-
-    private void doIncludeResource(Jar jar, String name,
-            Map<String, String> extra) throws ZipException, IOException,
-            Exception {
-        boolean preprocess = false;
-        if (name.startsWith("{") && name.endsWith("}")) {
-            preprocess = true;
-            name = name.substring(1, name.length() - 1).trim();
-        }
-
-        if (name.startsWith("@")) {
-            extractFromJar(jar, name.substring(1));
-        } else
-        /*
-         * NEW
-         */
-        if (extra.containsKey("literal")) {
-            String literal = (String) extra.get("literal");
-            Resource r = new EmbeddedResource(literal.getBytes("UTF-8"), 0);
-            String x = (String) extra.get("extra");
-            if (x != null)
-                r.setExtra(x);
-            jar.putResource(name, r);
-        } else {
-            String source;
-            File sourceFile;
-            String destinationPath;
-
-            String parts[] = name.split("\\s*=\\s*");
-            if (parts.length == 1) {
-                // Just a copy, destination path defined by
-                // source path.
-                source = parts[0];
-                sourceFile = getFile(source);
-                // Directories should be copied to the root
-                // but files to their file name ...
-                if (sourceFile.isDirectory())
-                    destinationPath = "";
-                else
-                    destinationPath = sourceFile.getName();
-            } else {
-                source = parts[1];
-                sourceFile = getFile(source);
-                destinationPath = parts[0];
-            }
-
-            // Some people insist on ending a directory with
-            // a slash ... it now also works if you do /=dir
-            if (destinationPath.endsWith("/"))
-                destinationPath = destinationPath.substring(0, destinationPath
-                        .length() - 1);
-
-            if (!sourceFile.exists()) {
-                noSuchFile(jar, name, extra, source, destinationPath);
-            } else
-                copy(jar, destinationPath, sourceFile, preprocess, extra);
-        }
-    }
-
-    private void noSuchFile(Jar jar, String clause, Map<String, String> extra,
-            String source, String destinationPath) throws Exception {
-        Jar src = getJarFromName(source, "Include-Resource " + source);
-        if (src != null) {
-            JarResource jarResource = new JarResource(src);
-            jar.putResource(destinationPath, jarResource);
-        } else {
-            Resource lastChance = make.process(source);
-            if (lastChance != null) {
-                jar.putResource(destinationPath, lastChance);
-            } else
-                error("Input file does not exist: " + source);
-        }
-    }
-
-    /**
-     * Extra resources from a Jar and add them to the given jar. The clause is
-     * the
-     * 
-     * @param jar
-     * @param clauses
-     * @param i
-     * @throws ZipException
-     * @throws IOException
-     */
-    private void extractFromJar(Jar jar, String name) throws ZipException,
-            IOException {
-        // Inline all resources and classes from another jar
-        // optionally appended with a modified regular expression
-        // like @zip.jar!/META-INF/MANIFEST.MF
-        int n = name.lastIndexOf("!/");
-        Pattern filter = null;
-        if (n > 0) {
-            String fstring = name.substring(n + 2);
-            name = name.substring(0, n);
-            filter = wildcard(fstring);
-        }
-        Jar sub = getJarFromName(name, "extract from jar");
-        if (sub == null)
-            error("Can not find JAR file " + name);
-        else
-            jar.addAll(sub, filter);
-    }
-
-    private Pattern wildcard(String spec) {
-        StringBuffer sb = new StringBuffer();
-        for (int j = 0; j < spec.length(); j++) {
-            char c = spec.charAt(j);
-            switch (c) {
-            case '.':
-                sb.append("\\.");
-                break;
-
-            case '*':
-                // test for ** (all directories)
-                if (j < spec.length() - 1 && spec.charAt(j + 1) == '*') {
-                    sb.append(".*");
-                    j++;
-                } else
-                    sb.append("[^/]*");
-                break;
-            default:
-                sb.append(c);
-                break;
-            }
-        }
-        String s = sb.toString();
-        try {
-            return Pattern.compile(s);
-        } catch (Exception e) {
-            error("Invalid regular expression on wildcarding: " + spec
-                    + " used *");
-        }
-        return null;
-    }
-
-    private void copy(Jar jar, String path, File from, boolean preprocess,
-            Map<String, String> extra) throws Exception {
-        if (doNotCopy.matcher(from.getName()).matches())
-            return;
-
-        if (from.isDirectory()) {
-            String next = path;
-            if (next.length() != 0)
-                next += '/';
-
-            File files[] = from.listFiles();
-            for (int i = 0; i < files.length; i++) {
-                copy(jar, next + files[i].getName(), files[i], preprocess,
-                        extra);
-            }
-        } else {
-            if (from.exists()) {
-                Resource resource = new FileResource(from);
-                if (preprocess) {
-                    resource = new PreprocessResource(this, resource);
-                }
-                jar.putResource(path, resource);
-            } else {
-                error("Input file does not exist: " + from);
-            }
-        }
-    }
-
-    private String getName(String where) {
-        int n = where.lastIndexOf('/');
-        if (n < 0)
-            return where;
-
-        return where.substring(n + 1);
-    }
-
-    public void setSourcepath(File[] files) {
-        for (int i = 0; i < files.length; i++)
-            addSourcepath(files[i]);
-    }
-
-    public void addSourcepath(File cp) {
-        if (!cp.exists())
-            warning("File on sourcepath that does not exist: " + cp);
-
-        sourcePath.add(cp);
-    }
-
-    /**
-     * Create a POM reseource for Maven containing as much information as
-     * possible from the manifest.
-     * 
-     * @param output
-     * @param builder
-     * @throws FileNotFoundException
-     * @throws IOException
-     */
-    public void doPom(Jar dot) throws FileNotFoundException, IOException {
-        {
-            Manifest manifest = dot.getManifest();
-            String name = manifest.getMainAttributes().getValue(
-                    Analyzer.BUNDLE_NAME);
-            String description = manifest.getMainAttributes().getValue(
-                    Analyzer.BUNDLE_DESCRIPTION);
-            String docUrl = manifest.getMainAttributes().getValue(
-                    Analyzer.BUNDLE_DOCURL);
-            String version = manifest.getMainAttributes().getValue(
-                    Analyzer.BUNDLE_VERSION);
-            String bundleVendor = manifest.getMainAttributes().getValue(
-                    Analyzer.BUNDLE_VENDOR);
-            ByteArrayOutputStream s = new ByteArrayOutputStream();
-            PrintStream ps = new PrintStream(s);
-            String bsn = manifest.getMainAttributes().getValue(
-                    Analyzer.BUNDLE_SYMBOLICNAME);
-            String licenses = manifest.getMainAttributes().getValue(
-                    BUNDLE_LICENSE);
-
-            if (bsn == null) {
-                error("Can not create POM unless Bundle-SymbolicName is set");
-                return;
-            }
-
-            bsn = bsn.trim();
-            int n = bsn.lastIndexOf('.');
-            if (n <= 0) {
-                error("Can not create POM unless Bundle-SymbolicName contains a .");
-                ps.close();
-                s.close();
-                return;
-            }
-            String groupId = bsn.substring(0, n);
-            String artifactId = bsn.substring(n + 1);
-            ps
-                    .println("<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'>");
-            ps.println("  <modelVersion>4.0.0</modelVersion>");
-            ps.println("  <groupId>" + groupId + "</groupId>");
-
-            n = artifactId.indexOf(';');
-            if (n > 0)
-                artifactId = artifactId.substring(0, n).trim();
-
-            ps.println("  <artifactId>" + artifactId + "</artifactId>");
-            ps.println("  <version>" + version + "</version>");
-            if (description != null) {
-                ps.println("  <description>");
-                ps.print("    ");
-                ps.println(description);
-                ps.println("  </description>");
-            }
-            if (name != null) {
-                ps.print("  <name>");
-                ps.print(name);
-                ps.println("</name>");
-            }
-            if (docUrl != null) {
-                ps.print("  <url>");
-                ps.print(docUrl);
-                ps.println("</url>");
-            }
-
-            if (bundleVendor != null) {
-                Matcher m = NAME_URL.matcher(bundleVendor);
-                String namePart = bundleVendor;
-                String urlPart = null;
-                if (m.matches()) {
-                    namePart = m.group(1);
-                    urlPart = m.group(2);
-                }
-                ps.println("  <organization>");
-                ps.print("    <name>");
-                ps.print(namePart.trim());
-                ps.println("</name>");
-                if (urlPart != null) {
-                    ps.print("    <url>");
-                    ps.print(urlPart.trim());
-                    ps.println("</url>");
-                }
-                ps.println("  </organization>");
-            }
-            if (licenses != null) {
-                ps.println("  <licenses>");
-                Map<String, Map<String, String>> map = parseHeader(licenses);
-                for (Iterator<Map.Entry<String, Map<String, String>>> e = map
-                        .entrySet().iterator(); e.hasNext();) {
-                    Map.Entry<String, Map<String, String>> entry = e.next();
-                    ps.println("    <license>");
-                    Map<String, String> values = entry.getValue();
-                    print(ps, values, "name", "name", (String) values
-                            .get("url"));
-                    print(ps, values, "url", "url", null);
-                    print(ps, values, "distribution", "distribution", "repo");
-                    ps.println("    </license>");
-                }
-                ps.println("  </licenses>");
-            }
-            ps.println("</project>");
-            ps.close();
-            s.close();
-            dot
-                    .putResource("pom.xml", new EmbeddedResource(s
-                            .toByteArray(), 0));
-        }
-    }
-
-    /**
-     * Utility function to print a tag from a map
-     * 
-     * @param ps
-     * @param values
-     * @param string
-     * @param tag
-     * @param object
-     */
-    private void print(PrintStream ps, Map<String, String> values,
-            String string, String tag, String object) {
-        String value = (String) values.get(string);
-        if (value == null)
-            value = object;
-        if (value == null)
-            return;
-        ps.println("    <" + tag + ">" + value.trim() + "</" + tag + ">");
-    }
-
-    public void close() {
-        super.close();
-    }
-
-    /**
-     * Build Multiple jars. If the -sub command is set, we filter the file with
-     * the given patterns.
-     * 
-     * @return
-     * @throws Exception
-     */
-    public Jar[] builds() throws Exception {
-        begin();
-
-        // Are we acting as a conduit for another JAR?
-        String conduit = getProperty(CONDUIT);
-        if (conduit != null) {
-            Map<String, Map<String, String>> map = parseHeader(conduit);
-            Jar[] result = new Jar[map.size()];
-            int n = 0;
-            for (String file : map.keySet()) {
-                Jar c = new Jar(getFile(file));
-                addClose(c);
-                String name = map.get(file).get("name");
-                if (name != null)
-                    c.setName(name);
-
-                result[n++] = c;
-            }
-            return result;
-        }
-
-        // If no -sub property, then reuse this builder object
-        // other wise, build all the sub parts.
-        String sub = getProperty(SUB);
-        if (sub == null) {
-            Jar jar = build();
-            if (jar == null)
-                return new Jar[0];
-
-            return new Jar[] { jar };
-        }
-
-        List<Jar> result = new ArrayList<Jar>();
-
-        // Get the Instruction objects that match the sub header
-        Set<Instruction> subs = replaceWitInstruction(parseHeader(sub), SUB)
-                .keySet();
-
-        // Get the member files of this directory
-        List<File> members = new ArrayList<File>(Arrays.asList(getBase()
-                .listFiles()));
-
-        getProperties().remove(SUB);
-        // For each member file
-        nextFile: while (members.size() > 0) {
-
-            File file = members.remove(0);
-            if (file.equals(getPropertiesFile()))
-                continue nextFile;
-
-            for (Iterator<Instruction> i = subs.iterator(); i.hasNext();) {
-
-                Instruction instruction = i.next();
-                if (instruction.matches(file.getName())) {
-
-                    if (!instruction.isNegated()) {
-
-                        Builder builder = null;
-                        try {
-                            builder = getSubBuilder();
-                            addClose(builder);
-                            builder.setProperties(file);
-                            builder.setProperty(SUB, "");
-                            // Recursively build
-                            // TODO
-                            Jar jar = builder.build();
-                            jar.setName(builder.getBsn());
-                            result.add(jar);
-                        } catch (Exception e) {
-                            e.printStackTrace();
-                            error("Sub Building " + file, e);
-                        }
-                        if (builder != null)
-                            getInfo(builder, file.getName() + ": ");
-                    }
-
-                    // Because we matched (even though we could be negated)
-                    // we skip any remaining searches
-                    continue nextFile;
-                }
-            }
-        }
-        setProperty(SUB, sub);
-        return result.toArray(new Jar[result.size()]);
-    }
-
-    protected Builder getSubBuilder() throws Exception {
-        return new Builder(this);
-    }
-
-    /**
-     * A macro to convert a maven version to an OSGi version
-     */
-
-    public String _maven_version(String args[]) {
-        if (args.length > 2)
-            error("${maven_version} macro receives too many arguments "
-                    + Arrays.toString(args));
-        else if (args.length < 2)
-            error("${maven_version} macro has no arguments, use ${maven_version;1.2.3-SNAPSHOT}");
-        else {
-            return cleanupVersion(args[1]);
-        }
-        return null;
-    }
-
-    public String _permissions(String args[]) throws IOException {
-        StringBuilder sb = new StringBuilder();
-
-        for (String arg : args) {
-            if ("packages".equals(arg) || "all".equals(arg)) {
-                for (String imp : getImports().keySet()) {
-                    if (!imp.startsWith("java.")) {
-                        sb.append("(org.osgi.framework.PackagePermission \"");
-                        sb.append(imp);
-                        sb.append("\" \"import\")\r\n");
-                    }
-                }
-                for (String exp : getExports().keySet()) {
-                    sb.append("(org.osgi.framework.PackagePermission \"");
-                    sb.append(exp);
-                    sb.append("\" \"export\")\r\n");
-                }
-            } else if ("admin".equals(arg) || "all".equals(arg)) {
-                sb.append("(org.osgi.framework.AdminPermission)");
-            } else if ("permissions".equals(arg))
-                ;
-            else
-                error("Invalid option in ${permissions}: %s", arg);
-        }
-        return sb.toString();
-    }
-
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/ClassDataCollector.java b/bundleplugin/src/main/java/aQute/lib/osgi/ClassDataCollector.java
deleted file mode 100644
index e09e00f..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/ClassDataCollector.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package aQute.lib.osgi;
-
-public interface ClassDataCollector {
-    void classBegin(int access, String name);
-    void extendsClass(String name);
-    void implementsInterfaces(String name[]);
-    void field(int access, String descriptor);
-    void method(int access, String descriptor);
-    void addReference(String token);
-    void classEnd();
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Clazz.java b/bundleplugin/src/main/java/aQute/lib/osgi/Clazz.java
deleted file mode 100644
index ce709df..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Clazz.java
+++ /dev/null
@@ -1,812 +0,0 @@
-/* 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.nio.*;
-import java.util.*;
-
-public class Clazz {
-    public static enum QUERY {
-        IMPLEMENTS, EXTENDS, IMPORTS, NAMED, ANY, VERSION
-    };
-
-    static protected class Assoc {
-        Assoc(byte tag, int a, int b) {
-            this.tag = tag;
-            this.a = a;
-            this.b = b;
-        }
-
-        byte tag;
-        int  a;
-        int  b;
-    }
-
-    final static byte                SkipTable[] = { 0, // 0 non existent
-            -1, // 1 CONSTANT_utf8 UTF 8, handled in
-            // method
-            -1, // 2
-            4, // 3 CONSTANT_Integer
-            4, // 4 CONSTANT_Float
-            8, // 5 CONSTANT_Long (index +=2!)
-            8, // 6 CONSTANT_Double (index +=2!)
-            -1, // 7 CONSTANT_Class
-            2, // 8 CONSTANT_String
-            4, // 9 CONSTANT_FieldRef
-            4, // 10 CONSTANT_MethodRef
-            4, // 11 CONSTANT_InterfaceMethodRef
-            4, // 12 CONSTANT_NameAndType
-                                                 };
-
-    String                           className;
-    Object                           pool[];
-    int                              intPool[];
-    Map<String, Map<String, String>> imports     = new HashMap<String, Map<String, String>>();
-    String                           path;
-
-    // static String type = "([BCDFIJSZ\\[]|L[^<>]+;)";
-    // static Pattern descriptor = Pattern.compile("\\(" + type + "*\\)(("
-    // + type + ")|V)");
-    int                              minor       = 0;
-    int                              major       = 0;
-
-    String                           sourceFile;
-    Set<String>                      xref;
-    Set<Integer>                     classes;
-    Set<Integer>                     descriptors;
-    int                              forName     = 0;
-    int                              class$      = 0;
-    String[]                         interfaces;
-    String                           zuper;
-    ClassDataCollector               cd          = new ClassDataCollector() {
-                                                     public void addReference(
-                                                             String token) {
-                                                     }
-
-                                                     public void classBegin(
-                                                             int access,
-                                                             String name) {
-                                                     }
-
-                                                     public void classEnd() {
-                                                     }
-
-                                                     public void extendsClass(
-                                                             String name) {
-                                                     }
-
-                                                     public void field(
-                                                             int access,
-                                                             String descriptor) {
-                                                     }
-
-                                                     public void implementsInterfaces(
-                                                             String[] name) {
-                                                     }
-
-                                                     public void method(
-                                                             int access,
-                                                             String descriptor) {
-                                                     }
-                                                 };
-
-    public Clazz(String path) {
-        this.path = path;
-    }
-
-    public Clazz(String path, InputStream in) throws IOException {
-        this.path = path;
-        DataInputStream din = new DataInputStream(in);
-        parseClassFile(din);
-        din.close();
-    }
-
-    Set<String> parseClassFile(DataInputStream in) throws IOException {
-
-        xref = new HashSet<String>();
-        classes = new HashSet<Integer>();
-        descriptors = new HashSet<Integer>();
-
-        boolean crawl = false; // Crawl the byte code
-        int magic = in.readInt();
-        if (magic != 0xCAFEBABE)
-            throw new IOException("Not a valid class file (no CAFEBABE header)");
-
-        minor = in.readUnsignedShort(); // minor version
-        major = in.readUnsignedShort(); // major version
-        int count = in.readUnsignedShort();
-        pool = new Object[count];
-        intPool = new int[count];
-
-        process: for (int poolIndex = 1; poolIndex < count; poolIndex++) {
-            byte tag = in.readByte();
-            switch (tag) {
-            case 0:
-                break process;
-            case 1:
-                constantUtf8(in, poolIndex);
-                break;
-
-            // For some insane optimization reason are
-            // the long and the double two entries in the
-            // constant pool. See 4.4.5
-            case 5:
-                constantLong(in, poolIndex);
-                poolIndex++;
-                break;
-
-            case 6:
-                constantDouble(in, poolIndex);
-                poolIndex++;
-                break;
-
-            case 7:
-                constantClass(in, poolIndex);
-                break;
-
-            case 8:
-                constantString(in, poolIndex);
-                break;
-
-            case 10: // Method ref
-                methodRef(in, poolIndex);
-                break;
-
-            // Name and Type
-            case 12:
-                nameAndType(in, poolIndex, tag);
-                break;
-
-            // We get the skip count for each record type
-            // from the SkipTable. This will also automatically
-            // abort when
-            default:
-                if (tag == 2)
-                    throw new IOException("Invalid tag " + tag);
-                in.skipBytes(SkipTable[tag]);
-                break;
-            }
-        }
-
-        pool(pool, intPool);
-        /*
-         * Parse after the constant pool, code thanks to Hans Christian
-         * Falkenberg
-         */
-
-        int access_flags = in.readUnsignedShort(); // access
-        int this_class = in.readUnsignedShort();
-        className = (String) pool[intPool[this_class]];
-        cd.classBegin(access_flags, className);
-
-        try {
-
-            int super_class = in.readUnsignedShort();
-            zuper = (String) pool[intPool[super_class]];
-            if (zuper != null) {
-                addReference(zuper);
-                cd.extendsClass(zuper);
-            }
-
-            int interfacesCount = in.readUnsignedShort();
-            if (interfacesCount > 0) {
-                interfaces = new String[interfacesCount];
-                for (int i = 0; i < interfacesCount; i++)
-                    interfaces[i] = (String) pool[intPool[in
-                            .readUnsignedShort()]];
-                cd.implementsInterfaces(interfaces);
-            }
-
-            int fieldsCount = in.readUnsignedShort();
-            for (int i = 0; i < fieldsCount; i++) {
-                access_flags = in.readUnsignedShort(); // skip access flags
-                int name_index = in.readUnsignedShort();
-                int descriptor_index = in.readUnsignedShort();
-
-                // Java prior to 1.5 used a weird
-                // static variable to hold the com.X.class
-                // result construct. If it did not find it
-                // it would create a variable class$com$X
-                // that would be used to hold the class
-                // object gotten with Class.forName ...
-                // Stupidly, they did not actively use the
-                // class name for the field type, so bnd
-                // would not see a reference. We detect
-                // this case and add an artificial descriptor
-                String name = pool[name_index].toString(); // name_index
-                if (name.startsWith("class$")) {
-                    crawl = true;
-                }
-                cd.field(access_flags, pool[descriptor_index].toString());
-                descriptors.add(new Integer(descriptor_index));
-                doAttributes(in, false);
-            }
-
-            //
-            // Check if we have to crawl the code to find
-            // the ldc(_w) <string constant> invokestatic Class.forName
-            // if so, calculate the method ref index so we
-            // can do this efficiently
-            //
-            if (crawl) {
-                forName = findMethod("java/lang/Class", "forName",
-                        "(Ljava/lang/String;)Ljava/lang/Class;");
-                class$ = findMethod(className, "class$",
-                        "(Ljava/lang/String;)Ljava/lang/Class;");
-            }
-
-            //
-            // Handle the methods
-            //
-            int methodCount = in.readUnsignedShort();
-            for (int i = 0; i < methodCount; i++) {
-                access_flags = in.readUnsignedShort();
-                /* int name_index = */in.readUnsignedShort();
-                int descriptor_index = in.readUnsignedShort();
-                // String s = (String) pool[name_index];
-                descriptors.add(new Integer(descriptor_index));
-                cd.method(access_flags, pool[descriptor_index].toString());
-                doAttributes(in, crawl);
-            }
-
-            doAttributes(in, false);
-
-            //
-            // Now iterate over all classes we found and
-            // parse those as well. We skip duplicates
-            //
-
-            for (Iterator<Integer> e = classes.iterator(); e.hasNext();) {
-                int class_index = e.next().shortValue();
-                doClassReference((String) pool[class_index]);
-            }
-
-            //
-            // Parse all the descriptors we found
-            //
-
-            for (Iterator<Integer> e = descriptors.iterator(); e.hasNext();) {
-                Integer index = e.next();
-                String prototype = (String) pool[index.intValue()];
-                if (prototype != null)
-                    parseDescriptor(prototype);
-                else
-                    System.err.println("Unrecognized descriptor: " + index);
-            }
-            Set<String> xref = this.xref;
-            reset();
-            return xref;
-        } finally {
-            cd.classEnd();
-        }
-    }
-
-    protected void pool(Object[] pool, int[] intPool) {
-    }
-
-    /**
-     * @param in
-     * @param poolIndex
-     * @param tag
-     * @throws IOException
-     */
-    protected void nameAndType(DataInputStream in, int poolIndex, byte tag)
-            throws IOException {
-        int name_index = in.readUnsignedShort();
-        int descriptor_index = in.readUnsignedShort();
-        descriptors.add(new Integer(descriptor_index));
-        pool[poolIndex] = new Assoc(tag, name_index, descriptor_index);
-    }
-
-    /**
-     * @param in
-     * @param poolIndex
-     * @param tag
-     * @throws IOException
-     */
-    private void methodRef(DataInputStream in, int poolIndex)
-            throws IOException {
-        int class_index = in.readUnsignedShort();
-        int name_and_type_index = in.readUnsignedShort();
-        pool[poolIndex] = new Assoc((byte) 10, class_index, name_and_type_index);
-    }
-
-    /**
-     * @param in
-     * @param poolIndex
-     * @throws IOException
-     */
-    private void constantString(DataInputStream in, int poolIndex)
-            throws IOException {
-        int string_index = in.readUnsignedShort();
-        intPool[poolIndex] = string_index;
-    }
-
-    /**
-     * @param in
-     * @param poolIndex
-     * @throws IOException
-     */
-    protected void constantClass(DataInputStream in, int poolIndex)
-            throws IOException {
-        int class_index = in.readUnsignedShort();
-        classes.add(new Integer(class_index));
-        intPool[poolIndex] = class_index;
-    }
-
-    /**
-     * @param in
-     * @throws IOException
-     */
-    protected void constantDouble(DataInputStream in, int poolIndex)
-            throws IOException {
-        in.skipBytes(8);
-    }
-
-    /**
-     * @param in
-     * @throws IOException
-     */
-    protected void constantLong(DataInputStream in, int poolIndex)
-            throws IOException {
-        in.skipBytes(8);
-    }
-
-    /**
-     * @param in
-     * @param poolIndex
-     * @throws IOException
-     */
-    protected void constantUtf8(DataInputStream in, int poolIndex)
-            throws IOException {
-        // CONSTANT_Utf8
-
-        String name = in.readUTF();
-        xref.add(name);
-        pool[poolIndex] = name;
-    }
-
-    /**
-     * Find a method reference in the pool that points to the given class,
-     * methodname and descriptor.
-     * 
-     * @param clazz
-     * @param methodname
-     * @param descriptor
-     * @return index in constant pool
-     */
-    private int findMethod(String clazz, String methodname, String descriptor) {
-        for (int i = 1; i < pool.length; i++) {
-            if (pool[i] instanceof Assoc) {
-                Assoc methodref = (Assoc) pool[i];
-                if (methodref.tag == 10) {
-                    // Method ref
-                    int class_index = methodref.a;
-                    int class_name_index = intPool[class_index];
-                    if (clazz.equals(pool[class_name_index])) {
-                        int name_and_type_index = methodref.b;
-                        Assoc name_and_type = (Assoc) pool[name_and_type_index];
-                        if (name_and_type.tag == 12) {
-                            // Name and Type
-                            int name_index = name_and_type.a;
-                            int type_index = name_and_type.b;
-                            if (methodname.equals(pool[name_index])) {
-                                if (descriptor.equals(pool[type_index])) {
-                                    return i;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return -1;
-    }
-
-    private void doClassReference(String next) {
-        if (next != null) {
-            String normalized = normalize(next);
-            if (normalized != null) {
-                cd.addReference(next);
-                String pack = getPackage(normalized);
-                packageReference(pack);
-            }
-        } else
-            throw new IllegalArgumentException("Invalid class, parent=");
-    }
-
-    /**
-     * Called for each attribute in the class, field, or method.
-     * 
-     * @param in
-     *            The stream
-     * @throws IOException
-     */
-    private void doAttributes(DataInputStream in, boolean crawl)
-            throws IOException {
-        int attributesCount = in.readUnsignedShort();
-        for (int j = 0; j < attributesCount; j++) {
-            // skip name CONSTANT_Utf8 pointer
-            doAttribute(in, crawl);
-        }
-    }
-
-    /**
-     * Process a single attribute, if not recognized, skip it.
-     * 
-     * @param in
-     *            the data stream
-     * @throws IOException
-     */
-    private void doAttribute(DataInputStream in, boolean crawl)
-            throws IOException {
-        int attribute_name_index = in.readUnsignedShort();
-        String attributeName = (String) pool[attribute_name_index];
-        if (attribute_name_index == 560)
-            System.out.println("Index " + attribute_name_index + ":"
-                    + attributeName);
-        long attribute_length = in.readInt();
-        attribute_length &= 0xFFFFFFFF;
-        if ("RuntimeVisibleAnnotations".equals(attributeName))
-            doAnnotations(in);
-        else if ("RuntimeVisibleParameterAnnotations".equals(attributeName))
-            doParameterAnnotations(in);
-        else if ("SourceFile".equals(attributeName))
-            doSourceFile(in);
-        else if ("Code".equals(attributeName) && crawl)
-            doCode(in);
-        else {
-            if (attribute_length > 0x7FFFFFFF) {
-                throw new IllegalArgumentException("Attribute > 2Gb");
-            }
-            in.skipBytes((int) attribute_length);
-        }
-    }
-
-    /**
-     * <pre>
-     * Code_attribute {
-     * 		u2 attribute_name_index;
-     * 		u4 attribute_length;
-     * 		u2 max_stack;
-     * 		u2 max_locals;
-     * 		u4 code_length;
-     * 		u1 code[code_length];
-     * 		u2 exception_table_length;
-     * 		{    	u2 start_pc;
-     * 		      	u2 end_pc;
-     * 		      	u2  handler_pc;
-     * 		      	u2  catch_type;
-     * 		}	exception_table[exception_table_length];
-     * 		u2 attributes_count;
-     * 		attribute_info attributes[attributes_count];
-     * 	}
-     * </pre>
-     * 
-     * @param in
-     * @param pool
-     * @throws IOException
-     */
-    private void doCode(DataInputStream in) throws IOException {
-        /* int max_stack = */in.readUnsignedShort();
-        /* int max_locals = */in.readUnsignedShort();
-        int code_length = in.readInt();
-        byte code[] = new byte[code_length];
-        in.readFully(code);
-        crawl(code);
-        int exception_table_length = in.readUnsignedShort();
-        in.skipBytes(exception_table_length * 8);
-        doAttributes(in, false);
-    }
-
-    /**
-     * We must find Class.forName references ...
-     * 
-     * @param code
-     */
-    protected void crawl(byte[] code) {
-        ByteBuffer bb = ByteBuffer.wrap(code);
-        bb.order(ByteOrder.BIG_ENDIAN);
-        int lastReference = -1;
-
-        while (bb.remaining() > 0) {
-            int instruction = 0xFF & bb.get();
-            switch (instruction) {
-            case OpCodes.ldc:
-                lastReference = 0xFF & bb.get();
-                break;
-
-            case OpCodes.ldc_w:
-                lastReference = 0xFFFF & bb.getShort();
-                break;
-
-            case OpCodes.invokestatic:
-                int methodref = 0xFFFF & bb.getShort();
-                if ((methodref == forName || methodref == class$)
-                        && lastReference != -1
-                        && pool[intPool[lastReference]] instanceof String) {
-                    String clazz = (String) pool[intPool[lastReference]];
-                    doClassReference(clazz.replace('.', '/'));
-                }
-                break;
-
-            case OpCodes.tableswitch:
-                // Skip to place divisible by 4
-                while ((bb.position() & 0x3) != 0)
-                    bb.get();
-                /* int deflt = */
-                bb.getInt();
-                int low = bb.getInt();
-                int high = bb.getInt();
-                bb.position(bb.position() + (high - low + 1) * 4);
-                lastReference = -1;
-                break;
-
-            case OpCodes.lookupswitch:
-                // Skip to place divisible by 4
-                while ((bb.position() & 0x3) != 0)
-                    bb.get();
-                /* deflt = */
-                bb.getInt();
-                int npairs = bb.getInt();
-                bb.position(bb.position() + npairs * 8);
-                lastReference = -1;
-                break;
-
-            default:
-                lastReference = -1;
-                bb.position(bb.position() + OpCodes.OFFSETS[instruction]);
-            }
-        }
-    }
-
-    private void doSourceFile(DataInputStream in) throws IOException {
-        int sourcefile_index = in.readUnsignedShort();
-        this.sourceFile = pool[sourcefile_index].toString();
-    }
-
-    private void doParameterAnnotations(DataInputStream in) throws IOException {
-        int num_parameters = in.readUnsignedByte();
-        for (int p = 0; p < num_parameters; p++) {
-            int num_annotations = in.readUnsignedShort(); // # of annotations
-            for (int a = 0; a < num_annotations; a++) {
-                doAnnotation(in);
-            }
-        }
-    }
-
-    private void doAnnotations(DataInputStream in) throws IOException {
-        int num_annotations = in.readUnsignedShort(); // # of annotations
-        for (int a = 0; a < num_annotations; a++) {
-            doAnnotation(in);
-        }
-    }
-
-    private void doAnnotation(DataInputStream in) throws IOException {
-        int type_index = in.readUnsignedShort();
-        descriptors.add(new Integer(type_index));
-        int num_element_value_pairs = in.readUnsignedShort();
-        for (int v = 0; v < num_element_value_pairs; v++) {
-            /* int element_name_index = */in.readUnsignedShort();
-            doElementValue(in);
-        }
-    }
-
-    private void doElementValue(DataInputStream in) throws IOException {
-        int tag = in.readUnsignedByte();
-        switch (tag) {
-        case 'B':
-        case 'C':
-        case 'D':
-        case 'F':
-        case 'I':
-        case 'J':
-        case 'S':
-        case 'Z':
-        case 's':
-            /* int const_value_index = */
-            in.readUnsignedShort();
-            break;
-
-        case 'e':
-            int type_name_index = in.readUnsignedShort();
-            descriptors.add(new Integer(type_name_index));
-            /* int const_name_index = */
-            in.readUnsignedShort();
-            break;
-
-        case 'c':
-            int class_info_index = in.readUnsignedShort();
-            descriptors.add(new Integer(class_info_index));
-            break;
-
-        case '@':
-            doAnnotation(in);
-            break;
-
-        case '[':
-            int num_values = in.readUnsignedShort();
-            for (int i = 0; i < num_values; i++) {
-                doElementValue(in);
-            }
-            break;
-
-        default:
-            throw new IllegalArgumentException(
-                    "Invalid value for Annotation ElementValue tag " + tag);
-        }
-    }
-
-    void packageReference(String pack) {
-        if (pack.indexOf('<') >= 0)
-            System.out.println("Oops: " + pack);
-        if (!imports.containsKey(pack))
-            imports.put(pack, new LinkedHashMap<String, String>());
-    }
-
-    public void parseDescriptor(String prototype) {
-        if (prototype.startsWith("("))
-            parseMethodDescriptor(prototype);
-        else
-            addReference(prototype);
-    }
-
-    void parseMethodDescriptor(String prototype) {
-        int last = prototype.indexOf(')');
-        if (last < 0)
-            throw new IllegalArgumentException(
-                    "Invalid method descriptor in class file: " + className
-                            + " " + prototype);
-
-        for (int i = 1; i < last; i++) {
-            if (prototype.charAt(i) == 'L') {
-                int next = prototype.indexOf(';', i);
-                addReference(prototype.substring(i, next));
-                i = next;
-            }
-        }
-        addReference(prototype.substring(last + 1));
-    }
-
-    private void addReference(String token) {
-        cd.addReference(token);
-        while (token.startsWith("["))
-            token = token.substring(1);
-
-        if (token.startsWith("L")) {
-            String clazz = normalize(token.substring(1));
-            if (clazz.startsWith("java/"))
-                return;
-            String pack = getPackage(clazz);
-            packageReference(pack);
-        }
-    }
-
-    static String normalize(String s) {
-        if (s.startsWith("[L"))
-            return normalize(s.substring(2));
-        if (s.startsWith("["))
-            if (s.length() == 2)
-                return null;
-            else
-                return normalize(s.substring(1));
-        if (s.endsWith(";"))
-            return normalize(s.substring(0, s.length() - 1));
-        return s + ".class";
-    }
-
-    public static String getPackage(String clazz) {
-        int n = clazz.lastIndexOf('/');
-        if (n < 0)
-            return ".";
-        return clazz.substring(0, n).replace('/', '.');
-    }
-
-    public Map<String, Map<String, String>> getReferred() {
-        return imports;
-    }
-
-    String getClassName() {
-        return className;
-    }
-
-    public String getPath() {
-        return path;
-    }
-
-    public Set<String> xref(InputStream in) throws IOException {
-        DataInputStream din = new DataInputStream(in);
-        Set<String> set = parseClassFile(din);
-        din.close();
-        return set;
-    }
-
-    public String getSourceFile() {
-        return sourceFile;
-    }
-
-    /**
-     * .class construct for different compilers
-     * 
-     * sun 1.1 Detect static variable class$com$acme$MyClass 1.2 " 1.3 " 1.4 "
-     * 1.5 ldc_w (class) 1.6 "
-     * 
-     * eclipse 1.1 class$0, ldc (string), invokestatic Class.forName 1.2 " 1.3 "
-     * 1.5 ldc (class) 1.6 "
-     * 
-     * 1.5 and later is not an issue, sun pre 1.5 is easy to detect the static
-     * variable that decodes the class name. For eclipse, the class$0 gives away
-     * we have a reference encoded in a string.
-     * compilerversions/compilerversions.jar contains test versions of all
-     * versions/compilers.
-     */
-
-    public void reset() {
-        pool = null;
-        intPool = null;
-        xref = null;
-        classes = null;
-        descriptors = null;
-    }
-
-    public boolean is(QUERY query, Instruction instr,
-            Map<String, Clazz> classspace) {
-        switch (query) {
-        case ANY:
-            return true;
-
-        case NAMED:
-            if (instr.matches(getClassName()))
-                return !instr.isNegated();
-            return false;
-
-        case VERSION:
-            String v = major + "/" + minor;
-            if (instr.matches(v))
-                return !instr.isNegated();
-            return false;
-
-        case IMPLEMENTS:
-            for (int i = 0; interfaces != null && i < interfaces.length; i++) {
-                if (instr.matches(interfaces[i]))
-                    return !instr.isNegated();
-            }
-            break;
-        case EXTENDS:
-            if (zuper == null)
-                return false;
-
-            if (instr.matches(zuper))
-                return !instr.isNegated();
-            break;
-
-        case IMPORTS:
-            for (String imp : imports.keySet()) {
-                if (instr.matches(imp.replace('.', '/')))
-                    return !instr.isNegated();
-            }
-        }
-
-        if (zuper == null || classspace == null)
-            return false;
-
-        Clazz clazz = classspace.get(zuper);
-        if (clazz == null)
-            return false;
-
-        return clazz.is(query, instr, classspace);
-    }
-
-    public String toString() {
-        return getFQN();
-    }
-
-    public String getFQN() {
-        return getClassName().replace('/', '.');
-    }
-
-    public void setClassDataCollector(ClassDataCollector cd) {
-        this.cd = cd;
-    }
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java b/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java
deleted file mode 100644
index 9535bac..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package aQute.lib.osgi;
-
-import java.util.*;
-import java.util.regex.*;
-
-public interface Constants {
-    String               BUNDLE_CLASSPATH                    = "Bundle-ClassPath";
-    String               BUNDLE_COPYRIGHT                    = "Bundle-Copyright";
-    String               BUNDLE_DESCRIPTION                  = "Bundle-Description";
-    String               BUNDLE_NAME                         = "Bundle-Name";
-    String               BUNDLE_NATIVECODE                   = "Bundle-NativeCode";
-    String               EXPORT_PACKAGE                      = "Export-Package";
-    String               EXPORT_SERVICE                      = "Export-Service";
-    String               IMPORT_PACKAGE                      = "Import-Package";
-    String               DYNAMICIMPORT_PACKAGE               = "DynamicImport-Package";
-    String               IMPORT_SERVICE                      = "Import-Service";
-    String               BUNDLE_VENDOR                       = "Bundle-Vendor";
-    String               BUNDLE_VERSION                      = "Bundle-Version";
-    String               BUNDLE_DOCURL                       = "Bundle-DocURL";
-    String               BUNDLE_CONTACTADDRESS               = "Bundle-ContactAddress";
-    String               BUNDLE_ACTIVATOR                    = "Bundle-Activator";
-    String               BUNDLE_REQUIREDEXECUTIONENVIRONMENT = "Bundle-RequiredExecutionEnvironment";
-    String               BUNDLE_SYMBOLICNAME                 = "Bundle-SymbolicName";
-    String               BUNDLE_LOCALIZATION                 = "Bundle-Localization";
-    String               REQUIRE_BUNDLE                      = "Require-Bundle";
-    String               FRAGMENT_HOST                       = "Fragment-Host";
-    String               BUNDLE_MANIFESTVERSION              = "Bundle-ManifestVersion";
-    String               SERVICE_COMPONENT                   = "Service-Component";
-    String               BUNDLE_LICENSE                      = "Bundle-License";
-    String               PRIVATE_PACKAGE                     = "Private-Package";
-    String               IGNORE_PACKAGE                      = "Ignore-Package";
-    String               INCLUDE_RESOURCE                    = "Include-Resource";
-    String               CONDITIONAL_PACKAGE                 = "Conditional-Package";
-    String               BND_LASTMODIFIED                    = "Bnd-LastModified";
-    String               CREATED_BY                          = "Created-By";
-    String               TOOL                                = "Tool";
-
-    String               headers[]                           = {
-            BUNDLE_ACTIVATOR, BUNDLE_CONTACTADDRESS, BUNDLE_COPYRIGHT,
-            BUNDLE_DESCRIPTION, BUNDLE_DOCURL, BUNDLE_LOCALIZATION,
-            BUNDLE_NATIVECODE, BUNDLE_VENDOR, BUNDLE_VERSION, BUNDLE_LICENSE,
-            BUNDLE_CLASSPATH, SERVICE_COMPONENT, EXPORT_PACKAGE,
-            IMPORT_PACKAGE, BUNDLE_LOCALIZATION, BUNDLE_MANIFESTVERSION,
-            BUNDLE_NAME, BUNDLE_NATIVECODE,
-            BUNDLE_REQUIREDEXECUTIONENVIRONMENT, BUNDLE_SYMBOLICNAME,
-            BUNDLE_VERSION, FRAGMENT_HOST, PRIVATE_PACKAGE, IGNORE_PACKAGE,
-            INCLUDE_RESOURCE, REQUIRE_BUNDLE, IMPORT_SERVICE, EXPORT_SERVICE,
-            CONDITIONAL_PACKAGE, BND_LASTMODIFIED           };
-
-    String               BUILDPATH                           = "-buildpath";
-    String               BUMPPOLICY                          = "-bumppolicy";
-    String               CONDUIT                             = "-conduit";
-    String               CLASSPATH                           = "-classpath";
-    String               DEPENDSON                           = "-dependson";
-    String               DONOTCOPY                           = "-donotcopy";
-    String               EXPORT_CONTENTS                     = "-exportcontents";
-    String               FAIL_OK                             = "-failok";
-    String               INCLUDE                             = "-include";
-    String               INCLUDERESOURCE                             = "-includeresource";
-    String               MAKE                                = "-make";
-    String               MANIFEST                            = "-manifest";
-    String               NOEXTRAHEADERS                      = "-noextraheaders";
-    String               NOUSES                              = "-nouses";
-    String               NOPE                                = "-nope";
-    String               PEDANTIC                            = "-pedantic";
-    String               PLUGIN                              = "-plugin";
-    String               POM                                 = "-pom";
-    String               REMOVE_HEADERS                      = "-removeheaders";
-    String               RESOURCEONLY                        = "-resourceonly";
-    String               SOURCES                             = "-sources";
-    String               SOURCEPATH                          = "-sourcepath";
-    String               SUB                                 = "-sub";
-    String               RUNPROPERTIES                       = "-runproperties";
-    String               RUNSYSTEMPACKAGES                   = "-runsystempackages";
-    String               RUNBUNDLES                          = "-runbundles";
-    String               RUNPATH                             = "-runpath";
-    String               RUNVM                               = "-runvm";
-
-    String               REPORTNEWER                         = "-reportnewer";
-    String               SIGN                                = "-sign";
-    String               TESTPACKAGES                        = "-testpackages";
-    String               TESTREPORT                          = "-testreport";
-    String               UNDERTEST                           = "-undertest";
-    String               VERBOSE                             = "-verbose";
-    String               VERSIONPOLICY                       = "-versionpolicy";
-
-    String               options[]                           = { BUILDPATH,
-            BUMPPOLICY, CONDUIT, CLASSPATH, DEPENDSON, DONOTCOPY,
-            EXPORT_CONTENTS, FAIL_OK, INCLUDE, INCLUDERESOURCE, MAKE, MANIFEST, NOEXTRAHEADERS,
-            NOUSES, NOPE, PEDANTIC, PLUGIN, POM, REMOVE_HEADERS, RESOURCEONLY,
-            SOURCES, SOURCEPATH, SOURCES, SOURCEPATH, SUB, RUNBUNDLES, RUNPATH,
-            RUNSYSTEMPACKAGES, RUNPROPERTIES, REPORTNEWER, UNDERTEST,
-            TESTPACKAGES, TESTREPORT, VERBOSE               };
-
-    char                 DUPLICATE_MARKER                    = '~';
-
-    String               SPLIT_PACKAGE_DIRECTIVE             = "-split-package:";
-    String               IMPORT_DIRECTIVE                    = "-import:";
-    String               NO_IMPORT_DIRECTIVE                 = "-noimport:";
-    String               REMOVE_ATTRIBUTE_DIRECTIVE          = "-remove-attribute:";
-    String               USES_DIRECTIVE                      = "uses:";
-    String               PRESENCE_DIRECTIVE                  = "presence:";
-
-    String               KEYSTORE_LOCATION_DIRECTIVE         = "keystore:";
-    String               KEYSTORE_PROVIDER_DIRECTIVE         = "provider:";
-    String               KEYSTORE_PASSWORD_DIRECTIVE         = "password:";
-    String               SIGN_PASSWORD_DIRECTIVE             = "sign-password:";
-
-    String               directives[]                        = {
-            SPLIT_PACKAGE_DIRECTIVE, NO_IMPORT_DIRECTIVE, IMPORT_DIRECTIVE,
-            "resolution:", "include:", "uses:", "exclude:", USES_DIRECTIVE,
-            KEYSTORE_LOCATION_DIRECTIVE, KEYSTORE_PROVIDER_DIRECTIVE,
-            KEYSTORE_PASSWORD_DIRECTIVE, SIGN_PASSWORD_DIRECTIVE,
-
-                                                             // TODO
-                                                             };
-
-    String               USES_USES                           = "<<USES>>";
-    String               CURRENT_USES                        = "@uses";
-    String               IMPORT_REFERENCE                    = "reference";
-    String               IMPORT_PRIVATE                      = "private";
-    String[]             importDirectives                    = {
-            IMPORT_REFERENCE, IMPORT_PRIVATE                };
-
-    String               COMPONENT_FACTORY                   = "factory:";
-    String               COMPONENT_SERVICEFACTORY            = "servicefactory:";
-    String               COMPONENT_IMMEDIATE                 = "immediate:";
-    String               COMPONENT_ENABLED                   = "enabled:";
-    String               COMPONENT_DYNAMIC                   = "dynamic:";
-    String               COMPONENT_MULTIPLE                  = "multiple:";
-    String               COMPONENT_PROVIDE                   = "provide:";
-    String               COMPONENT_OPTIONAL                  = "optional:";
-    String               COMPONENT_PROPERTIES                = "properties:";
-    String               COMPONENT_IMPLEMENTATION            = "implementation:";
-    String[]             componentDirectives                 = new String[] {
-            COMPONENT_FACTORY, COMPONENT_IMMEDIATE, COMPONENT_ENABLED,
-            COMPONENT_DYNAMIC, COMPONENT_MULTIPLE, COMPONENT_PROVIDE,
-            COMPONENT_OPTIONAL, COMPONENT_PROPERTIES, COMPONENT_IMPLEMENTATION,
-            COMPONENT_SERVICEFACTORY                        };
-
-    // static Map EES = new HashMap();
-    static Set<String>   SET_COMPONENT_DIRECTIVES            = new HashSet<String>(
-                                                                     Arrays
-                                                                             .asList(componentDirectives));
-
-    static final Pattern VALID_PROPERTY_TYPES                = Pattern
-                                                                     .compile("(String|Long|Double|Float|Integer|Byte|Character|Boolean|Short)");
-
-    String               DEFAULT_BND_EXTENSION               = ".bnd";
-    String               DEFAULT_JAR_EXTENSION               = ".jar";
-    String               DEFAULT_BAR_EXTENSION               = ".bar";
-    String[]             METAPACKAGES                        = { "META-INF",
-            "OSGI-INF", "OSGI-OPT"                          };
-
-    int                  STRATEGY_HIGHEST                    = 1;
-    int                  STRATEGY_LOWEST                     = -1;
-
-    String               CURRENT_VERSION                     = "@";
-    String               CURRENT_PACKAGE                     = "@package";
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/EmbeddedResource.java b/bundleplugin/src/main/java/aQute/lib/osgi/EmbeddedResource.java
deleted file mode 100644
index 771dbf7..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/EmbeddedResource.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/* 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.zip.*;
-
-public class EmbeddedResource implements Resource {
-	byte	data[];
-	long 	lastModified;
-	String	extra;
-
-	public EmbeddedResource(byte data[], long lastModified) {
-		this.data = data;
-		this.lastModified = lastModified;
-	}
-
-	public InputStream openInputStream() throws FileNotFoundException {
-		return new ByteArrayInputStream(data);
-	}
-
-	public void write(OutputStream out) throws IOException {
-		out.write(data);
-	}
-
-	public String toString() {
-		return ":" + data.length + ":";
-	}
-
-	public static void build(Jar jar, InputStream in, long lastModified) throws IOException {
-		ZipInputStream jin = new ZipInputStream(in);
-		ZipEntry entry = jin.getNextEntry();
-		while (entry != null) {
-			if (!entry.isDirectory()) {
-				byte data[] = collect(jin);
-				jar.putResource(entry.getName(), new EmbeddedResource(data, lastModified), true);
-			}
-			entry = jin.getNextEntry();
-		}
-		jin.close();
-	}
-
-	/**
-	 * Convenience method to turn an inputstream into a byte array. The method
-	 * uses a recursive algorithm to minimize memory usage.
-	 * 
-	 * @param in stream with data
-	 * @param offset where we are in the stream
-	 * @returns byte array filled with data
-	 */
-    static byte[] collect(InputStream in) throws IOException {
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        copy(in,out);
-        return out.toByteArray();
-    }
-
-    static void copy(InputStream in, OutputStream out) throws IOException {
-        int available = in.available();
-        if ( available <= 10000)
-            available = 64000;
-        byte [] buffer = new byte[available];
-        int size;
-        while ( (size=in.read(buffer))>0)
-            out.write(buffer,0,size);
-    }
-
-	public long lastModified() {
-		return lastModified;
-	}
-
-	public static void build(Jar sub, Resource resource) throws IOException {
-			InputStream in = resource.openInputStream();
-			build(sub,in, resource.lastModified());
-			in.close();
-	}
-
-	public String getExtra() {
-		return extra;
-	}
-
-	public void setExtra(String extra) {
-		this.extra = extra;
-	}
-
-	public long size() {
-	    return data.length;
-	}
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/FileResource.java b/bundleplugin/src/main/java/aQute/lib/osgi/FileResource.java
deleted file mode 100644
index fa70e21..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/FileResource.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/* 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.regex.Pattern;
-
-public class FileResource implements Resource {
-	File	file;
-	String	extra;
-	
-	public FileResource(File file) {
-		this.file = file;
-	}
-
-	public InputStream openInputStream() throws FileNotFoundException {
-		return new FileInputStream(file);
-	}
-
-	public static void build(Jar jar, File directory, Pattern doNotCopy) {
-		traverse(
-				jar,
-				directory.getAbsolutePath().length(),
-				directory,
-				doNotCopy);
-	}
-
-	public String toString() {
-		return ":" + file.getName() + ":";
-	}
-
-	public void write(OutputStream out) throws IOException {
-		copy(this, out);
-	}
-
-	static synchronized void copy(Resource resource, OutputStream out)
-			throws IOException {
-		InputStream in = resource.openInputStream();
-		try {
-			byte buffer[] = new byte[20000];
-			int size = in.read(buffer);
-			while (size > 0) {
-				out.write(buffer, 0, size);
-				size = in.read(buffer);
-			}
-		}
-		finally {
-			in.close();
-		}
-	}
-
-	static void traverse(Jar jar, int rootlength, File directory,
-			Pattern doNotCopy) {
-		if (doNotCopy.matcher(directory.getName()).matches())
-			return;
-
-		File files[] = directory.listFiles();
-		for (int i = 0; i < files.length; i++) {
-			if (files[i].isDirectory())
-				traverse(jar, rootlength, files[i], doNotCopy);
-			else {
-				String path = files[i].getAbsolutePath().substring(
-						rootlength + 1);
-				if (File.separatorChar != '/')
-					path = path.replace(File.separatorChar, '/');
-				jar.putResource(path, new FileResource(files[i]), true);
-			}
-		}
-	}
-
-	public long lastModified() {
-		return file.lastModified();
-	}
-
-	public String getExtra() {
-		return extra;
-	}
-
-	public void setExtra(String extra) {
-		this.extra = extra;
-	}
-	
-	public long size() {
-	    return (int) file.length();
-	}
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java b/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java
deleted file mode 100644
index b78cc57..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * $Header: /cvs/xierpa/aQute.util.jar/src/aQute/lib/osgi/Instruction.java,v 1.1 2007-01-03 19:54:32 pkriens Exp $
- * 
- * Copyright (c) OSGi Alliance (2006). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package aQute.lib.osgi;
-
-import java.util.regex.*;
-
-public class Instruction {
-    Pattern pattern;
-    String  instruction;
-    boolean negated;
-    boolean optional;
-    
-    public Instruction(String instruction, boolean negated) {
-        this.instruction = instruction;
-        this.negated = negated;
-    }
-
-    public boolean matches(String value) {
-        return getMatcher(value).matches();
-    }
-
-    public boolean isNegated() {
-        return negated;
-    }
-
-    public String getPattern() {
-        return instruction;
-    }
-
-    /**
-     * Convert a string based pattern to a regular expression based pattern.
-     * This is called an instruction, this object makes it easier to handle the
-     * different cases
-     * 
-     * @param string
-     * @return
-     */
-    public static Instruction getPattern(String string) {
-        boolean negated = false;
-        if (string.startsWith("!")) {
-            negated = true;
-            string = string.substring(1);
-        }
-        StringBuffer sb = new StringBuffer();
-        for (int c = 0; c < string.length(); c++) {
-            switch (string.charAt(c)) {
-            case '.':
-                sb.append("\\.");
-                break;
-            case '*':
-                sb.append(".*");
-                break;
-            case '?':
-                sb.append(".?");
-                break;
-            default:
-                sb.append(string.charAt(c));
-                break;
-            }
-        }
-        string = sb.toString();
-        if (string.endsWith("\\..*")) {
-            sb.append("|");
-            sb.append(string.substring(0, string.length() - 4));
-        }
-        return new Instruction(sb.toString(), negated);
-    }
-
-    public String toString() {
-        return getPattern();
-    }
-
-    public Matcher getMatcher(String value) {
-        if (pattern == null) {
-            pattern = Pattern.compile(instruction);
-        }
-        return pattern.matcher(value);
-    }
-
-    public int hashCode() {
-        return instruction.hashCode();
-    }
-
-    public boolean equals(Object other) {
-        return other != null && (other instanceof Instruction)
-                && instruction.equals(((Instruction) other).instruction);
-    }
-
-    public void setOptional() {
-        optional = true;
-    }
-    
-    public boolean isOptional() {
-        return optional;
-    }
-
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java b/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java
deleted file mode 100644
index fe34cc5..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java
+++ /dev/null
@@ -1,408 +0,0 @@
-/* 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.*;
-
-import aQute.libg.reporter.*;
-
-public class Jar implements Closeable {
-    public static final Object[]       EMPTY_ARRAY = new Jar[0];
-    Map<String, Resource>              resources   = new TreeMap<String, Resource>();
-    Map<String, Map<String, Resource>> directories = new TreeMap<String, Map<String, Resource>>();
-    Manifest                           manifest;
-    boolean                            manifestFirst;
-    String                             name;
-    File                               source;
-    ZipFile                            zipFile;
-    long                               lastModified;
-    String                             lastModifiedReason;
-    Reporter                           reporter;
-
-    public Jar(String name) {
-        this.name = name;
-    }
-
-    public Jar(String name, File dirOrFile) throws ZipException, IOException {
-        this(name);
-        source = dirOrFile;
-        if (dirOrFile.isDirectory())
-            FileResource.build(this, dirOrFile, Analyzer.doNotCopy);
-        else {
-            zipFile = ZipResource.build(this, dirOrFile);
-        }
-    }
-
-    public Jar(String name, InputStream in, long lastModified)
-            throws IOException {
-        this(name);
-        EmbeddedResource.build(this, in, lastModified);
-    }
-
-    public Jar(String name, String path) throws IOException {
-        this(name);
-        File f = new File(path);
-        InputStream in = new FileInputStream(f);
-        EmbeddedResource.build(this, in, f.lastModified());
-        in.close();
-    }
-
-    public Jar(File jar) throws IOException {
-        this(getName(jar), jar);
-    }
-
-    /**
-     * Make the JAR file name the project name if we get a src or bin directory.
-     * 
-     * @param f
-     * @return
-     */
-    private static String getName(File f) {
-        f = f.getAbsoluteFile();
-        String name = f.getName();
-        if (name.equals("bin") || name.equals("src"))
-            return f.getParentFile().getName();
-        else {
-            if ( name.endsWith(".jar"))
-                name = name.substring(0, name.length()-4);
-            return name;
-        }
-    }
-
-    public Jar(String string, InputStream resourceAsStream) throws IOException {
-        this(string, resourceAsStream, 0);
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String toString() {
-        return "Jar:" + name;
-    }
-
-    public boolean putResource(String path, Resource resource) {
-        return putResource(path, resource, true);
-    }
-
-    public boolean putResource(String path, Resource resource, boolean overwrite) {
-        updateModified(resource.lastModified(), path);
-
-        if (path.equals("META-INF/MANIFEST.MF")) {
-            manifest = null;
-            if (resources.isEmpty())
-                manifestFirst = true;
-        }
-        String dir = getDirectory(path);
-        Map<String, Resource> s = directories.get(dir);
-        if (s == null) {
-            s = new TreeMap<String, Resource>();
-            directories.put(dir, s);
-            int n = dir.lastIndexOf('/');
-            while (n > 0) {
-                String dd = dir.substring(0, n);
-                if (directories.containsKey(dd))
-                    break;
-                directories.put(dd, null);
-                n = dd.lastIndexOf('/');
-            }
-        }
-        boolean duplicate = s.containsKey(path);
-        if (!duplicate || overwrite) {
-            resources.put(path, resource);
-            s.put(path, resource);
-        }
-        return duplicate;
-    }
-
-    public Resource getResource(String path) {
-        return resources.get(path);
-    }
-
-    private String getDirectory(String path) {
-        int n = path.lastIndexOf('/');
-        if (n < 0)
-            return "";
-
-        return path.substring(0, n);
-    }
-
-    public Map<String, Map<String, Resource>> getDirectories() {
-        return directories;
-    }
-
-    public Map<String, Resource> getResources() {
-        return resources;
-    }
-
-    public boolean addDirectory(Map<String, Resource> directory,
-            boolean overwrite) {
-        boolean duplicates = false;
-        if (directory == null)
-            return false;
-
-        for (Map.Entry<String, Resource> entry : directory.entrySet()) {
-            String key = entry.getKey();
-            if (!key.endsWith(".java")) {
-                duplicates |= putResource(key, (Resource) entry.getValue(),
-                        overwrite);
-            }
-        }
-        return duplicates;
-    }
-
-    public Manifest getManifest() throws IOException {
-        if (manifest == null) {
-            Resource manifestResource = getResource("META-INF/MANIFEST.MF");
-            if (manifestResource != null) {
-                InputStream in = manifestResource.openInputStream();
-                manifest = new Manifest(in);
-                in.close();
-            }
-        }
-        return manifest;
-    }
-
-    public boolean exists(String path) {
-        return resources.containsKey(path);
-    }
-
-    public void setManifest(Manifest manifest) {
-        manifestFirst = true;
-        this.manifest = manifest;
-    }
-
-    public void write(File file) throws Exception {
-        try {
-            OutputStream out = new FileOutputStream(file);
-            write(out);
-            out.close();
-            return;
-
-        } catch (Exception t) {
-            file.delete();
-            throw t;
-        }
-    }
-
-    public void write(String file) throws Exception {
-        write(new File(file));
-    }
-
-    public void write(OutputStream out) throws IOException {
-        JarOutputStream jout = new JarOutputStream(out);
-        Set<String> done = new HashSet<String>();
-
-        Set<String> directories = new HashSet<String>();
-        doManifest(done, jout);
-        for (Map.Entry<String, Resource> entry : getResources().entrySet()) {
-            // Skip metainf contents
-            if (!done.contains(entry.getKey()))
-                writeResource(jout, directories, (String) entry.getKey(),
-                        (Resource) entry.getValue());
-        }
-        jout.finish();
-    }
-
-    private void doManifest(Set<String> done, JarOutputStream jout)
-            throws IOException {
-        JarEntry ze = new JarEntry("META-INF/MANIFEST.MF");
-        jout.putNextEntry(ze);
-        writeManifest(jout);
-        jout.closeEntry();
-        done.add(ze.getName());
-    }
-
-    
-    /**
-     * Cleanup the manifest for writing. Cleaning up consists of 
-     * adding a space after any \n to prevent the manifest to see
-     * this newline as a delimiter.
-     * 
-     * @param out Output
-     * @throws IOException
-     */
-
-    public void writeManifest(OutputStream out) throws IOException {
-        writeManifest(getManifest(), out);
-    }
-    
-    public static void writeManifest(Manifest manifest, OutputStream out ) throws IOException {
-        manifest = clean(manifest);
-        manifest.write(out);
-    }
-
-    private static Manifest clean(Manifest org) {
-        Manifest result = new Manifest();
-        for (Map.Entry<?,?> entry : org.getMainAttributes().entrySet()) {
-            String nice = clean((String) entry.getValue());
-            result.getMainAttributes().put(entry.getKey(),
-                    nice);
-        }
-        for (String name : org.getEntries().keySet() ) {
-            Attributes attrs = result.getAttributes(name);
-            if ( attrs == null ) {
-                attrs = new Attributes();
-                result.getEntries().put(name, attrs);
-            }           
-
-            for (Map.Entry<?,?> entry : org.getAttributes(name).entrySet()) {
-                String nice = clean((String) entry.getValue());
-                attrs.put(
-                        (Attributes.Name) entry.getKey(), nice);
-            }
-        }
-        return result;
-    }
-
-
-
-    private static String clean(String s) {
-        if (s.indexOf('\n') < 0)
-            return s;
-
-        StringBuffer sb = new StringBuffer(s);
-        for (int i = 0; i < sb.length(); i++) {
-            if (sb.charAt(i) == '\n')
-                sb.insert(++i, ' ');
-        }
-        return sb.toString();
-    }
-
-
-    private void writeResource(JarOutputStream jout, Set<String> directories,
-            String path, Resource resource) throws IOException {
-        if (resource == null)
-            return;
-
-        createDirectories(directories, jout, path);
-        ZipEntry ze = new ZipEntry(path);
-        ze.setMethod(ZipEntry.DEFLATED);
-        long lastModified = resource.lastModified();
-        if (lastModified == 0L) {
-            lastModified = System.currentTimeMillis();
-        }
-        ze.setTime(lastModified);
-        if (resource.getExtra() != null)
-            ze.setExtra(resource.getExtra().getBytes());
-        jout.putNextEntry(ze);
-        try {
-            resource.write(jout);
-        } catch (Exception e) {
-            throw new IllegalArgumentException("Cannot write resource: " + path
-                    + " " + e);
-        }
-        jout.closeEntry();
-    }
-
-    void createDirectories(Set<String> directories, JarOutputStream zip,
-            String name) throws IOException {
-        int index = name.lastIndexOf('/');
-        if (index > 0) {
-            String path = name.substring(0, index);
-            if (directories.contains(path))
-                return;
-            createDirectories(directories, zip, path);
-            ZipEntry ze = new ZipEntry(path + '/');
-            zip.putNextEntry(ze);
-            zip.closeEntry();
-            directories.add(path);
-        }
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Add all the resources in the given jar that match the given filter.
-     * 
-     * @param sub
-     *            the jar
-     * @param filter
-     *            a pattern that should match the resoures in sub to be added
-     */
-    public boolean addAll(Jar sub, Pattern filter) {
-        boolean dupl = false;
-        for (String name : sub.getResources().keySet()) {
-            if ("META-INF/MANIFEST.MF".equals(name))
-                continue;
-
-            if (filter == null || filter.matcher(name).matches())
-                dupl |= putResource(name, sub.getResource(name), true);
-        }
-        return dupl;
-    }
-
-    public void close() {
-        if (zipFile != null)
-            try {
-                zipFile.close();
-            } catch (IOException e) {
-                // Ignore
-            }
-        resources = null;
-        directories = null;
-        manifest = null;
-        source = null;
-    }
-
-    public long lastModified() {
-        return lastModified;
-    }
-
-    public void updateModified(long time, String reason) {
-        if (time > lastModified) {
-            lastModified = time;
-            lastModifiedReason = reason;
-        }
-    }
-
-    public void setReporter(Reporter reporter) {
-        this.reporter = reporter;
-    }
-
-    public boolean hasDirectory(String path) {
-        return directories.get(path) != null;
-    }
-
-    public List<String> getPackages() {
-        List<String> list = new ArrayList<String>(directories.size());
-
-        for (Iterator<String> i = directories.keySet().iterator(); i.hasNext();) {
-            String path = i.next();
-            String pack = path.replace('/', '.');
-            list.add(pack);
-        }
-        return list;
-    }
-
-    public File getSource() {
-        return source;
-    }
-
-    public boolean addAll(Jar src) {
-        return addAll(src, null);
-    }
-
-    public boolean rename(String oldPath, String newPath) {
-        Resource resource = remove(oldPath);
-        if (resource == null)
-            return false;
-
-        return putResource(newPath, resource);
-    }
-
-    public Resource remove(String path) {
-        Resource resource = resources.remove(path);
-        String dir = getDirectory(path);
-        Map<String, Resource> mdir = directories.get(dir);
-        // must be != null
-        mdir.remove(path);
-        return resource;
-    }
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/JarResource.java b/bundleplugin/src/main/java/aQute/lib/osgi/JarResource.java
deleted file mode 100644
index b633de1..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/JarResource.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-
-public class JarResource implements Resource {
-	Jar		jar;
-	String extra;
-	
-	public JarResource(Jar jar ) {
-		this.jar = jar;
-	}
-	
-	public String getExtra() {
-		return extra;
-	}
-
-	public long lastModified() {
-		return jar.lastModified();
-	}
-
-
-	public void write(OutputStream out) throws IOException {
-		jar.write(out);
-	}
-	
-	public InputStream openInputStream() throws IOException {
-		ByteArrayOutputStream out = new ByteArrayOutputStream();
-		write(out);
-		out.close();
-		ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
-		return in;
-	}
-
-	public void setExtra(String extra) {
-		this.extra = extra;
-	}
-	
-	public Jar getJar() { 
-	    return jar;
-	}
-
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java b/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java
deleted file mode 100644
index 22748ae..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java
+++ /dev/null
@@ -1,832 +0,0 @@
-/* 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.lang.reflect.*;
-import java.net.*;
-import java.text.*;
-import java.util.*;
-import java.util.regex.*;
-
-import aQute.libg.sed.*;
-import aQute.libg.version.*;
-
-/**
- * Provide a macro processor. This processor can replace variables in strings
- * based on a properties and a domain. The domain can implement functions that
- * start with a "_" and take args[], the names of these functions are available
- * as functions in the macro processor (without the _). Macros can nest to any
- * depth but may not contain loops.
- * 
- */
-public class Macro implements Replacer {
-    Properties properties;
-    Processor  domain;
-    Object     targets[];
-    boolean    flattening;
-
-    public Macro(Properties properties, Processor domain, Object... targets) {
-        this.properties = properties;
-        this.domain = domain;
-        this.targets = targets;
-        if (targets != null) {
-            for (Object o : targets) {
-                assert o != null;
-            }
-        }
-    }
-
-    public Macro(Processor processor) {
-        this(new Properties(), processor);
-    }
-
-    public String process(String line) {
-        return process(line, null);
-    }
-
-    String process(String line, Link link) {
-        StringBuffer sb = new StringBuffer();
-        process(line, 0, '\u0000', '\u0000', sb, link);
-        return sb.toString();
-    }
-
-    int process(CharSequence org, int index, char begin, char end,
-            StringBuffer result, Link link) {
-        StringBuilder line = new StringBuilder(org);
-        int nesting = 1;
-
-        StringBuffer variable = new StringBuffer();
-        outer: while (index < line.length()) {
-            char c1 = line.charAt(index++);
-            if (c1 == end) {
-                if (--nesting == 0) {
-                    result.append(replace(variable.toString(), link));
-                    return index;
-                }
-            } else if (c1 == begin)
-                nesting++;
-            else if (c1 == '\\' && index < line.length() - 1
-                    && line.charAt(index) == '$') {
-                // remove the escape backslash and interpret the dollar as a
-                // literal
-                index++;
-                variable.append('$');
-                continue outer;
-            } else if (c1 == '$' && index < line.length() - 2) {
-                char c2 = line.charAt(index);
-                char terminator = getTerminator(c2);
-                if (terminator != 0) {
-                    index = process(line, index + 1, c2, terminator, variable,
-                            link);
-                    continue outer;
-                }
-            }
-            variable.append(c1);
-        }
-        result.append(variable);
-        return index;
-    }
-
-    char getTerminator(char c) {
-        switch (c) {
-        case '(':
-            return ')';
-        case '[':
-            return ']';
-        case '{':
-            return '}';
-        case '<':
-            return '>';
-        case '\u00ab': // Guillemet double << >>
-            return '\u00bb';
-        case '\u2039': // Guillemet single
-            return '\u203a';
-        }
-        return 0;
-    }
-
-    protected String replace(String key, Link link) {
-        if (link != null && link.contains(key))
-            return "${infinite:" + link.toString() + "}";
-
-        if (key != null) {
-            key = key.trim();
-            if (key.length() > 0) {
-                String value = (String) properties.getProperty(key);
-                if (value != null)
-                    return process(value, new Link(link, key));
-
-                value = doCommands(key);
-                if (value != null)
-                    return process(value, new Link(link, key));
-
-                if (key != null && key.trim().length() > 0) {
-                    value = System.getProperty(key);
-                    if (value != null)
-                        return value;
-                }
-                if (!flattening)
-                    domain.warning("No translation found for macro: " + key);
-            } else {
-                domain.warning("Found empty macro key");
-            }
-        } else {
-            domain.warning("Found null macro key");
-        }
-        return "${" + key + "}";
-    }
-
-    /**
-     * Parse the key as a command. A command consist of parameters separated by
-     * ':'.
-     * 
-     * @param key
-     * @return
-     */
-    static Pattern commands = Pattern.compile("(?<!\\\\);");
-
-    private String doCommands(String key) {
-        String[] args = commands.split(key);
-        if (args == null || args.length == 0)
-            return null;
-
-        for (int i = 0; i < args.length; i++)
-            if (args[i].indexOf('\\') >= 0)
-                args[i] = args[i].replaceAll("\\\\;", ";");
-
-        Processor rover = domain;
-        while (rover != null) {
-            String result = doCommand(rover, args[0], args);
-            if (result != null)
-                return result;
-
-            rover = rover.getParent();
-        }
-
-        for (int i = 0; targets != null && i < targets.length; i++) {
-            String result = doCommand(targets[i], args[0], args);
-            if (result != null)
-                return result;
-        }
-
-        return doCommand(this, args[0], args);
-    }
-
-    private String doCommand(Object target, String method, String[] args) {
-        if (target == null)
-            ; // System.out.println("Huh? Target should never be null " +
-                // domain);
-        else {
-            String cname = "_" + method.replaceAll("-", "_");
-            try {
-                Method m = target.getClass().getMethod(cname,
-                        new Class[] { String[].class });
-                return (String) m.invoke(target, new Object[] { args });
-            } catch (NoSuchMethodException e) {
-                // Ignore
-            } catch (InvocationTargetException e) {
-                domain.warning("Exception in replace: " + e.getCause());
-                e.printStackTrace();
-            } catch (Exception e) {
-                domain.warning("Exception in replace: " + e + " method="
-                        + method);
-                e.printStackTrace();
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Return a unique list where the duplicates are removed.
-     * 
-     * @param args
-     * @return
-     */
-    static String _uniqHelp = "${uniq;<list> ...}";
-
-    public String _uniq(String args[]) {
-        verifyCommand(args, _uniqHelp, null, 1, Integer.MAX_VALUE);
-        Set<String> set = new LinkedHashSet<String>();
-        for (int i = 1; i < args.length; i++) {
-            Processor.split(args[i], set);
-        }
-        return Processor.join(set, ",");
-    }
-
-    public String _filter(String args[]) {
-        return filter(args, false);
-    }
-
-    public String _filterout(String args[]) {
-        return filter(args, true);
-
-    }
-
-    static String _filterHelp = "${%s;<list>;<regex>}";
-
-    String filter(String[] args, boolean include) {
-        verifyCommand(args, String.format(_filterHelp, args[0]), null, 3, 3);
-
-        Collection<String> list = new ArrayList<String>(Processor
-                .split(args[1]));
-        Pattern pattern = Pattern.compile(args[2]);
-
-        for (Iterator<String> i = list.iterator(); i.hasNext();) {
-            if (pattern.matcher(i.next()).matches() == include)
-                i.remove();
-        }
-        return Processor.join(list);
-    }
-
-    static String _sortHelp = "${sort;<list>...}";
-
-    public String _sort(String args[]) {
-        verifyCommand(args, _sortHelp, null, 2, Integer.MAX_VALUE);
-
-        List<String> result = new ArrayList<String>();
-        for (int i = 1; i < args.length; i++) {
-            Processor.split(args[i], result);
-        }
-        Collections.sort(result);
-        return Processor.join(result);
-    }
-
-    static String _joinHelp = "${join;<list>...}";
-
-    public String _join(String args[]) {
-
-        verifyCommand(args, _joinHelp, null, 1, Integer.MAX_VALUE);
-
-        List<String> result = new ArrayList<String>();
-        for (int i = 1; i < args.length; i++) {
-            Processor.split(args[i], result);
-        }
-        return Processor.join(result);
-    }
-
-    static String _ifHelp = "${if;<condition>;<iftrue> [;<iffalse>] }";
-
-    public String _if(String args[]) {
-        verifyCommand(args, _ifHelp, null, 3, 4);
-        String condition = args[1].trim();
-        if (condition.length() != 0)
-            return args[2];
-        if (args.length > 3)
-            return args[3];
-        else
-            return "";
-    }
-
-    public String _now(String args[]) {
-        return new Date().toString();
-    }
-
-    public static String _fmodifiedHelp = "${fmodified;<list of filenames>...}, return latest modification date";
-
-    public String _fmodified(String args[]) throws Exception {
-        verifyCommand(args, _fmodifiedHelp, null, 2, Integer.MAX_VALUE);
-
-        long time = 0;
-        Collection<String> names = new ArrayList<String>();
-        for (int i = 1; i < args.length; i++) {
-            Processor.split(args[i], names);
-        }
-        for (String name : names) {
-            File f = new File(name);
-            if (f.exists() && f.lastModified() > time)
-                time = f.lastModified();
-        }
-        return "" + time;
-    }
-
-    public String _long2date(String args[]) {
-        try {
-            return new Date(Long.parseLong(args[1])).toString();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return "not a valid long";
-    }
-
-    public String _literal(String args[]) {
-        if (args.length != 2)
-            throw new RuntimeException(
-                    "Need a value for the ${literal;<value>} macro");
-        return "${" + args[1] + "}";
-    }
-
-    public String _def(String args[]) {
-        if (args.length != 2)
-            throw new RuntimeException(
-                    "Need a value for the ${def;<value>} macro");
-
-        String value = properties.getProperty(args[1]);
-        if (value == null)
-            return "";
-        else
-            return value;
-    }
-
-    /**
-     * 
-     * replace ; <list> ; regex ; replace
-     * 
-     * @param args
-     * @return
-     */
-    public String _replace(String args[]) {
-        if (args.length != 4) {
-            domain.warning("Invalid nr of arguments to replace "
-                    + Arrays.asList(args));
-            return null;
-        }
-
-        String list[] = args[1].split("\\s*,\\s*");
-        StringBuffer sb = new StringBuffer();
-        String del = "";
-        for (int i = 0; i < list.length; i++) {
-            String element = list[i].trim();
-            if (!element.equals("")) {
-                sb.append(del);
-                sb.append(element.replaceAll(args[2], args[3]));
-                del = ", ";
-            }
-        }
-
-        return sb.toString();
-    }
-
-    public String _warning(String args[]) {
-        for (int i = 1; i < args.length; i++) {
-            domain.warning(process(args[i]));
-        }
-        return "";
-    }
-
-    public String _error(String args[]) {
-        for (int i = 1; i < args.length; i++) {
-            domain.error(process(args[i]));
-        }
-        return "";
-    }
-
-    /**
-     * toclassname ; <path>.class ( , <path>.class ) *
-     * 
-     * @param args
-     * @return
-     */
-    static String _toclassnameHelp = "${classname;<list of class names>}, convert class paths to FQN class names ";
-
-    public String _toclassname(String args[]) {
-        verifyCommand(args, _toclassnameHelp, null, 2, 2);
-        Collection<String> paths = Processor.split(args[1]);
-
-        List<String> names = new ArrayList<String>(paths.size());
-        for (String path : paths) {
-            if (path.endsWith(".class")) {
-                String name = path.substring(0, path.length() - 6).replace('/',
-                        '.');
-                names.add(name);
-            } else if (path.endsWith(".java")) {
-                String name = path.substring(0, path.length() - 5).replace('/',
-                        '.');
-                names.add(name);
-            } else {
-                domain
-                        .warning("in toclassname, "
-                                + args[1]
-                                + " is not a class path because it does not end in .class");
-            }
-        }
-        return Processor.join(names, ",");
-    }
-
-    /**
-     * toclassname ; <path>.class ( , <path>.class ) *
-     * 
-     * @param args
-     * @return
-     */
-
-    static String _toclasspathHelp = "${toclasspath;<list>}, convert a list of class names to paths";
-
-    public String _toclasspath(String args[]) {
-        verifyCommand(args, _toclasspathHelp, null, 2, 2);
-
-        Collection<String> names = Processor.split(args[1]);
-        Collection<String> paths = new ArrayList<String>(names.size());
-        for (String name : names) {
-            String path = name.replace('.', '/') + ".class";
-            paths.add(path);
-        }
-        return Processor.join(paths, ",");
-    }
-
-    public String _dir(String args[]) {
-        if (args.length < 2) {
-            domain.warning("Need at least one file name for ${dir;...}");
-            return null;
-        } else {
-            String del = "";
-            StringBuffer sb = new StringBuffer();
-            for (int i = 1; i < args.length; i++) {
-                File f = new File(args[i]).getAbsoluteFile();
-                if (f.exists() && f.getParentFile().exists()) {
-                    sb.append(del);
-                    sb.append(f.getParentFile().getAbsolutePath());
-                    del = ",";
-                }
-            }
-            return sb.toString();
-        }
-
-    }
-
-    public String _basename(String args[]) {
-        if (args.length < 2) {
-            domain.warning("Need at least one file name for ${basename;...}");
-            return null;
-        } else {
-            String del = "";
-            StringBuffer sb = new StringBuffer();
-            for (int i = 1; i < args.length; i++) {
-                File f = new File(args[i]).getAbsoluteFile();
-                if (f.exists() && f.getParentFile().exists()) {
-                    sb.append(del);
-                    sb.append(f.getName());
-                    del = ",";
-                }
-            }
-            return sb.toString();
-        }
-
-    }
-
-    public String _isfile(String args[]) {
-        if (args.length < 2) {
-            domain.warning("Need at least one file name for ${isfile;...}");
-            return null;
-        } else {
-            boolean isfile = true;
-            for (int i = 1; i < args.length; i++) {
-                File f = new File(args[i]).getAbsoluteFile();
-                isfile &= f.isFile();
-            }
-            return isfile ? "true" : "false";
-        }
-
-    }
-
-    public String _isdir(String args[]) {
-        if (args.length < 2) {
-            domain.warning("Need at least one file name for ${isdir;...}");
-            return null;
-        } else {
-            boolean isdir = true;
-            for (int i = 1; i < args.length; i++) {
-                File f = new File(args[i]).getAbsoluteFile();
-                isdir &= f.isDirectory();
-            }
-            return isdir ? "true" : "false";
-        }
-
-    }
-
-    public String _tstamp(String args[]) {
-        String format = "yyyyMMddhhmm";
-        long now = System.currentTimeMillis();
-
-        if (args.length > 1) {
-            format = args[1];
-            if (args.length > 2) {
-                now = Long.parseLong(args[2]);
-                if (args.length > 3) {
-                    domain.warning("Too many arguments for tstamp: "
-                            + Arrays.toString(args));
-                }
-            }
-        }
-        SimpleDateFormat sdf = new SimpleDateFormat(format);
-        return sdf.format(new Date(now));
-    }
-
-    /**
-     * Wildcard a directory. The lists can contain Instruction that are matched
-     * against the given directory
-     * 
-     * ${wc;<dir>;<list>(;<list>)*}
-     * 
-     * @author aqute
-     * 
-     */
-
-    public String _lsr(String args[]) {
-        return ls(args, true);
-    }
-
-    public String _lsa(String args[]) {
-        return ls(args, false);
-    }
-
-    String ls(String args[], boolean relative) {
-        if (args.length < 2)
-            throw new IllegalArgumentException(
-                    "the ${ls} macro must at least have a directory as parameter");
-
-        File dir = new File(args[1]);
-        if (!dir.isAbsolute())
-            throw new IllegalArgumentException(
-                    "the ${ls} macro directory parameter is not absolute: "
-                            + dir);
-
-        if (!dir.exists())
-            throw new IllegalArgumentException(
-                    "the ${ls} macro directory parameter does not exist: "
-                            + dir);
-
-        if (!dir.isDirectory())
-            throw new IllegalArgumentException(
-                    "the ${ls} macro directory parameter points to a file instead of a directory: "
-                            + dir);
-
-        String[] files = dir.list();
-        List<String> result;
-
-        if (args.length < 3) {
-            result = Arrays.asList(files);
-        } else
-            result = new ArrayList<String>();
-
-        for (int i = 2; i < args.length; i++) {
-            String parts[] = args[i].split("\\s*,\\s*");
-            for (String pattern : parts) {
-                // So make it in to an instruction
-                Instruction instr = Instruction.getPattern(pattern);
-
-                // For each project, match it against the instruction
-                for (int f = 0; f < files.length; f++) {
-                    if (files[f] != null) {
-                        if (instr.matches(files[f])) {
-                            if (!instr.isNegated()) {
-                                if (relative)
-                                    result.add(files[f]);
-                                else
-                                    result.add(new File(dir, files[f])
-                                            .getAbsolutePath());
-                            }
-                            files[f] = null;
-                        }
-                    }
-                }
-            }
-        }
-        return Processor.join(result, ",");
-    }
-
-    public String _currenttime(String args[]) {
-        return Long.toString(System.currentTimeMillis());
-    }
-
-    /**
-     * Modify a version to set a version policy. Thed policy is a mask that is
-     * mapped to a version.
-     * 
-     * <pre>
-     * +           increment
-     * -           decrement
-     * =           maintain
-     * &tilde;           discard
-     * 
-     * ==+      = maintain major, minor, increment micro, discard qualifier
-     * &tilde;&tilde;&tilde;=     = just get the qualifier
-     * version=&quot;[${version;==;${@}},${version;=+;${@}})&quot;
-     * </pre>
-     * 
-     * 
-     * 
-     * 
-     * @param args
-     * @return
-     */
-    static String  _versionHelp      = "${version;<mask>;<version>}, modify a version\n"
-                                             + "<mask> ::= [ M [ M [ M [ MQ ]]]\n"
-                                             + "M ::= '+' | '-' | MQ\n"
-                                             + "MQ ::= '~' | '='";
-    static Pattern _versionPattern[] = new Pattern[] { null, null,
-            Pattern.compile("[-+=~]{0,3}[=~]?"), Verifier.VERSION };
-
-    public String _version(String args[]) {
-        verifyCommand(args, _versionHelp, null, 3, 3);
-
-        String mask = args[1];
-
-        Version version = new Version(args[2]);
-        StringBuilder sb = new StringBuilder();
-        String del = "";
-
-        for (int i = 0; i < mask.length(); i++) {
-            char c = mask.charAt(i);
-            String result = null;
-            if (c != '~') {
-                if (i == 3) {
-                    result = version.getQualifier();
-                } else {
-                    int x = version.get(i);
-                    switch (c) {
-                    case '+':
-                        x++;
-                        break;
-                    case '-':
-                        x--;
-                        break;
-                    case '=':
-                        break;
-                    }
-                    result = Integer.toString(x);
-                }
-                if (result != null) {
-                    sb.append(del);
-                    del = ".";
-                    sb.append(result);
-                }
-            }
-        }
-        return sb.toString();
-    }
-
-    /**
-     * System command. Execute a command and insert the result.
-     * 
-     * @param args
-     * @param help
-     * @param patterns
-     * @param low
-     * @param high
-     */
-    public String _system(String args[]) throws Exception {
-        verifyCommand(args,
-                "${system;<command>[;<in>]}, execute a system command", null,
-                2, 3);
-        String command = args[1];
-        String input = null;
-
-        if (args.length > 2) {
-            input = args[2];
-        }
-
-        Process process = Runtime.getRuntime().exec(command, null,
-                domain.getBase());
-        if (input != null) {
-            process.getOutputStream().write(input.getBytes("UTF-8"));
-        }
-        process.getOutputStream().close();
-
-        String s = getString(process.getInputStream());
-        process.getInputStream().close();
-        int exitValue = process.waitFor();
-        if (exitValue != 0) {
-            domain.error("System command " + command + " failed with "
-                    + exitValue);
-        }
-        return s.trim();
-    }
-
-    /**
-     * Get the contents of a file.
-     * 
-     * @param in
-     * @return
-     * @throws IOException
-     */
-
-    public String _cat(String args[]) throws IOException {
-        verifyCommand(args, "${cat;<in>}, get the content of a file", null, 2,
-                2);
-        File f = domain.getFile(args[1]);
-        if (f.isFile()) {
-            InputStream in = new FileInputStream(f);
-            return getString(in);
-        } else if (f.isDirectory()) {
-            return Arrays.toString(f.list());
-        } else {
-            try {
-                URL url = new URL(args[1]);
-                InputStream in = url.openStream();
-                return getString(in);
-            } catch (MalformedURLException mfue) {
-                // Ignore here
-            }
-            return null;
-        }
-    }
-
-    public static String getString(InputStream in) throws IOException {
-        try {
-            StringBuilder sb = new StringBuilder();
-            BufferedReader rdr = new BufferedReader(new InputStreamReader(in));
-            String line = null;
-            while ((line = rdr.readLine()) != null) {
-                sb.append(line);
-                sb.append("\n");
-            }
-            return sb.toString();
-        } finally {
-            in.close();
-        }
-    }
-
-    public static void verifyCommand(String args[], String help,
-            Pattern[] patterns, int low, int high) {
-        String message = "";
-        if (args.length > high) {
-            message = "too many arguments";
-        } else if (args.length < low) {
-            message = "too few arguments";
-        } else {
-            for (int i = 0; patterns != null && i < patterns.length
-                    && i < args.length - 1; i++) {
-                if (patterns[i] != null
-                        && !patterns[i].matcher(args[i + 1]).matches()) {
-                    message += String.format(
-                            "Argument %s (%s) does not match %s\n", i, args[i],
-                            patterns[i].pattern());
-                }
-            }
-        }
-        if (message.length() != 0) {
-            StringBuilder sb = new StringBuilder();
-            String del = "${";
-            for (String arg : args) {
-                sb.append(del);
-                sb.append(arg);
-                del = ";";
-            }
-            sb.append("}, is not understood. ");
-            sb.append(message);
-            throw new IllegalArgumentException(sb.toString());
-        }
-    }
-
-    // Helper class to track expansion of variables
-    // on the stack.
-    static class Link {
-        Link   previous;
-        String key;
-
-        public Link(Link previous, String key) {
-            this.previous = previous;
-            this.key = key;
-        }
-
-        public boolean contains(String key) {
-            if (this.key.equals(key))
-                return true;
-
-            if (previous == null)
-                return false;
-
-            return previous.contains(key);
-        }
-
-        public String toString() {
-            StringBuffer sb = new StringBuffer();
-            String del = "[";
-            for (Link r = this; r != null; r = r.previous) {
-                sb.append(del);
-                sb.append(r.key);
-                del = ",";
-            }
-            sb.append("]");
-            return sb.toString();
-        }
-    }
-
-    /**
-     * Take all the properties and translate them to actual values. This method
-     * takes the set properties and traverse them over all entries, including
-     * the default properties for that properties. The values no longer contain
-     * macros.
-     * 
-     * @return A new Properties with the flattened values
-     */
-    public Properties getFlattenedProperties() {
-        // Some macros only work in a lower processor, so we
-        // do not report unknown macros while flattening
-        flattening = true;
-        try {
-            Properties flattened = new Properties();
-            for (Enumeration<?> e = properties.propertyNames(); e
-                    .hasMoreElements();) {
-                String key = (String) e.nextElement();
-                if (!key.startsWith("_"))
-                    flattened.put(key, process(properties.getProperty(key)));
-            }
-            return flattened;
-        } finally {
-            flattening = false;
-        }
-    };
-
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/OpCodes.java b/bundleplugin/src/main/java/aQute/lib/osgi/OpCodes.java
deleted file mode 100644
index f0d3134..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/OpCodes.java
+++ /dev/null
@@ -1,1196 +0,0 @@
-package aQute.lib.osgi;
-
-public class OpCodes {
-	final static short	nop				= 0x00;			// [No change] performs
-														// no
-	// operation
-	final static short	aconst_null		= 0x01;			// ? null pushes a null
-	// reference onto the stack
-	final static short	iconst_m1		= 0x02;			// ? -1 loads the int
-														// value -1
-	// onto the stack
-	final static short	iconst_0		= 0x03;			// ? 0 loads the int
-														// value 0
-	// onto the stack
-	final static short	iconst_1		= 0x04;			// ? 1 loads the int
-														// value 1
-	// onto the stack
-	final static short	iconst_2		= 0x05;			// ? 2 loads the int
-														// value 2
-	// onto the stack
-	final static short	iconst_3		= 0x06;			// ? 3 loads the int
-														// value 3
-	// onto the stack
-	final static short	iconst_4		= 0x07;			// ? 4 loads the int
-														// value 4
-	// onto the stack
-	final static short	iconst_5		= 0x08;			// ? 5 loads the int
-														// value 5
-	// onto the stack
-	final static short	lconst_0		= 0x09;			// ? 0L pushes the long
-														// 0 onto
-	// the stack
-	final static short	bipush			= 0x10;			// byte ? value pushes a
-														// byte
-	// onto the stack as an integer
-	// value
-	final static short	sipush			= 0x11;			// byte1, byte2 ? value
-														// pushes a
-	// signed integer (byte1 << 8 +
-	// byte2) onto the stack
-	final static short	ldc				= 0x12;			// index ? value pushes
-														// a
-	// constant #index from a
-	// constant pool (String, int,
-	// float or class type) onto the
-	// stack
-	final static short	ldc_w			= 0x13;			// indexbyte1,
-														// indexbyte2 ?
-	// value pushes a constant
-	// #index from a constant pool
-	// (String, int, float or class
-	// type) onto the stack (wide
-	// index is constructed as
-	// indexbyte1 << 8 + indexbyte2)
-	final static short	ldc2_w			= 0x14;			// indexbyte1,
-														// indexbyte2 ?
-	// value pushes a constant
-	// #index from a constant pool
-	// (double or long) onto the
-	// stack (wide index is
-	// constructed as indexbyte1 <<
-	// 8 + indexbyte2)
-	final static short	iload			= 0x15;			// index ? value loads
-														// an int
-	// value from a variable #index
-	final static short	lload			= 0x16;			// index ? value load a
-														// long
-	// value from a local variable
-	// #index
-	final static short	fload			= 0x17;			// index ? value loads a
-														// float
-	// value from a local variable
-	// #index
-	final static short	dload			= 0x18;			// index ? value loads a
-														// double
-	// value from a local variable
-	// #index
-	final static short	aload			= 0x19;			// index ? objectref
-														// loads a
-	// reference onto the stack from
-	// a local variable #index
-	final static short	lload_2			= 0x20;			// ? value load a long
-														// value
-	// from a local variable 2
-	final static short	lload_3			= 0x21;			// ? value load a long
-														// value
-	// from a local variable 3
-	final static short	fload_0			= 0x22;			// ? value loads a float
-														// value
-	// from local variable 0
-	final static short	fload_1			= 0x23;			// ? value loads a float
-														// value
-	// from local variable 1
-	final static short	fload_2			= 0x24;			// ? value loads a float
-														// value
-	// from local variable 2
-	final static short	fload_3			= 0x25;			// ? value loads a float
-														// value
-	// from local variable 3
-	final static short	dload_0			= 0x26;			// ? value loads a
-														// double from
-	// local variable 0
-	final static short	dload_1			= 0x27;			// ? value loads a
-														// double from
-	// local variable 1
-	final static short	dload_2			= 0x28;			// ? value loads a
-														// double from
-	// local variable 2
-	final static short	dload_3			= 0x29;			// ? value loads a
-														// double from
-	// local variable 3
-	final static short	faload			= 0x30;			// arrayref, index ?
-														// value loads
-	// a float from an array
-	final static short	daload			= 0x31;			// arrayref, index ?
-														// value loads
-	// a double from an array
-	final static short	aaload			= 0x32;			// arrayref, index ?
-														// value loads
-	// onto the stack a reference
-	// from an array
-	final static short	baload			= 0x33;			// arrayref, index ?
-														// value loads
-	// a byte or Boolean value from
-	// an array
-	final static short	caload			= 0x34;			// arrayref, index ?
-														// value loads
-	// a char from an array
-	final static short	saload			= 0x35;			// arrayref, index ?
-														// value load
-	// short from array
-	final static short	istore			= 0x36;			// index value ? store
-														// int value
-	// into variable #index
-	final static short	lstore			= 0x37;			// index value ? store a
-														// long
-	// value in a local variable
-	// #index
-	final static short	fstore			= 0x38;			// index value ? stores
-														// a float
-	// value into a local variable
-	// #index
-	final static short	dstore			= 0x39;			// index value ? stores
-														// a double
-	// value into a local variable
-	// #index
-	final static short	lstore_1		= 0x40;			// value ? store a long
-														// value in
-	// a local variable 1
-	final static short	lstore_2		= 0x41;			// value ? store a long
-														// value in
-	// a local variable 2
-	final static short	lstore_3		= 0x42;			// value ? store a long
-														// value in
-	// a local variable 3
-	final static short	fstore_0		= 0x43;			// value ? stores a
-														// float value
-	// into local variable 0
-	final static short	fstore_1		= 0x44;			// value ? stores a
-														// float value
-	// into local variable 1
-	final static short	fstore_2		= 0x45;			// value ? stores a
-														// float value
-	// into local variable 2
-	final static short	fstore_3		= 0x46;			// value ? stores a
-														// float value
-	// into local variable 3
-	final static short	dstore_0		= 0x47;			// value ? stores a
-														// double into
-	// local variable 0
-	final static short	dstore_1		= 0x48;			// value ? stores a
-														// double into
-	// local variable 1
-	final static short	dstore_2		= 0x49;			// value ? stores a
-														// double into
-	// local variable 2
-	final static short	lastore			= 0x50;			// arrayref, index,
-														// value ?
-	// store a long to an array
-	final static short	fastore			= 0x51;			// arreyref, index,
-														// value ?
-	// stores a float in an array
-	final static short	dastore			= 0x52;			// arrayref, index,
-														// value ?
-	// stores a double into an array
-	final static short	aastore			= 0x53;			// arrayref, index,
-														// value ?
-	// stores into a reference to an
-	// array
-	final static short	bastore			= 0x54;			// arrayref, index,
-														// value ?
-	// stores a byte or Boolean
-	// value into an array
-	final static short	castore			= 0x55;			// arrayref, index,
-														// value ?
-	// stores a char into an array
-	final static short	sastore			= 0x56;			// arrayref, index,
-														// value ?
-	// store short to array
-	final static short	pop				= 0x57;			// value ? discards the
-														// top
-	// value on the stack
-	final static short	pop2			= 0x58;			// {value2, value1} ?
-														// discards
-	// the top two values on the
-	// stack (or one value, if it is
-	// a double or long)
-	final static short	dup				= 0x59;			// value ? value, value
-	// duplicates the value on top
-	// of the stack
-	final static short	iadd			= 0x60;			// value1, value2 ?
-														// result adds
-	// two ints together
-	final static short	ladd			= 0x61;			// value1, value2 ?
-														// result add
-	// two longs
-	final static short	fadd			= 0x62;			// value1, value2 ?
-														// result adds
-	// two floats
-	final static short	dadd			= 0x63;			// value1, value2 ?
-														// result adds
-	// two doubles
-	final static short	isub			= 0x64;			// value1, value2 ?
-														// result int
-	// subtract
-	final static short	lsub			= 0x65;			// value1, value2 ?
-														// result
-	// subtract two longs
-	final static short	fsub			= 0x66;			// value1, value2 ?
-														// result
-	// subtracts two floats
-	final static short	dsub			= 0x67;			// value1, value2 ?
-														// result
-	// subtracts a double from
-	// another
-	final static short	imul			= 0x68;			// value1, value2 ?
-														// result
-	// multiply two integers
-	final static short	lmul			= 0x69;			// value1, value2 ?
-														// result
-	// multiplies two longs
-	final static short	irem			= 0x70;			// value1, value2 ?
-														// result
-	// logical int remainder
-	final static short	lrem			= 0x71;			// value1, value2 ?
-														// result
-	// remainder of division of two
-	// longs
-	final static short	frem			= 0x72;			// value1, value2 ?
-														// result gets
-	// the remainder from a division
-	// between two floats
-	final static short	drem			= 0x73;			// value1, value2 ?
-														// result gets
-	// the remainder from a division
-	// between two doubles
-	final static short	ineg			= 0x74;			// value ? result negate
-														// int
-	final static short	lneg			= 0x75;			// value ? result
-														// negates a long
-	final static short	fneg			= 0x76;			// value ? result
-														// negates a
-	// float
-	final static short	dneg			= 0x77;			// value ? result
-														// negates a
-	// double
-	final static short	ishl			= 0x78;			// value1, value2 ?
-														// result int
-	// shift left
-	final static short	lshl			= 0x79;			// value1, value2 ?
-														// result
-	// bitwise shift left of a long
-	// value1 by value2 positions
-	final static short	ior				= 0x80;			// value1, value2 ?
-														// result
-	// logical int or
-	final static short	lor				= 0x81;			// value1, value2 ?
-														// result
-	// bitwise or of two longs
-	final static short	ixor			= 0x82;			// value1, value2 ?
-														// result int
-	// xor
-	final static short	lxor			= 0x83;			// value1, value2 ?
-														// result
-	// bitwise exclusive or of two
-	// longs
-	final static short	iinc			= 0x84;			// index, const [No
-														// change]
-	// increment local variable
-	// #index by signed byte const
-	final static short	i2l				= 0x85;			// value ? result
-														// converts an
-	// int into a long
-	final static short	i2f				= 0x86;			// value ? result
-														// converts an
-	// int into a float
-	final static short	i2d				= 0x87;			// value ? result
-														// converts an
-	// int into a double
-	final static short	l2i				= 0x88;			// value ? result
-														// converts a
-	// long to an int
-	final static short	l2f				= 0x89;			// value ? result
-														// converts a
-	// long to a float
-	final static short	d2f				= 0x90;			// value ? result
-														// converts a
-	// double to a float
-	final static short	i2b				= 0x91;			// value ? result
-														// converts an
-	// int into a byte
-	final static short	i2c				= 0x92;			// value ? result
-														// converts an
-	// int into a character
-	final static short	i2s				= 0x93;			// value ? result
-														// converts an
-	// int into a short
-	final static short	lcmp			= 0x94;			// value1, value2 ?
-														// result
-	// compares two longs values
-	final static short	fcmpl			= 0x95;			// value1, value2 ?
-														// result
-	// compares two floats
-	final static short	fcmpg			= 0x96;			// value1, value2 ?
-														// result
-	// compares two floats
-	final static short	dcmpl			= 0x97;			// value1, value2 ?
-														// result
-	// compares two doubles
-	final static short	dcmpg			= 0x98;			// value1, value2 ?
-														// result
-	// compares two doubles
-	final static short	ifeq			= 0x99;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is 0, branch
-	// to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	lconst_1		= 0x0a;			// ? 1L pushes the long
-														// 1 onto
-	// the stack
-	final static short	fconst_0		= 0x0b;			// ? 0.0f pushes 0.0f on
-														// the
-	// stack
-	final static short	fconst_1		= 0x0c;			// ? 1.0f pushes 1.0f on
-														// the
-	// stack
-	final static short	fconst_2		= 0x0d;			// ? 2.0f pushes 2.0f on
-														// the
-	// stack
-	final static short	dconst_0		= 0x0e;			// ? 0.0 pushes the
-														// constant 0.0
-	// onto the stack
-	final static short	dconst_1		= 0x0f;			// ? 1.0 pushes the
-														// constant 1.0
-	// onto the stack
-	final static short	iload_0			= 0x1a;			// ? value loads an int
-														// value
-	// from variable 0
-	final static short	iload_1			= 0x1b;			// ? value loads an int
-														// value
-	// from variable 1
-	final static short	iload_2			= 0x1c;			// ? value loads an int
-														// value
-	// from variable 2
-	final static short	iload_3			= 0x1d;			// ? value loads an int
-														// value
-	// from variable 3
-	final static short	lload_0			= 0x1e;			// ? value load a long
-														// value
-	// from a local variable 0
-	final static short	lload_1			= 0x1f;			// ? value load a long
-														// value
-	// from a local variable 1
-	final static short	aload_0			= 0x2a;			// ? objectref loads a
-														// reference
-	// onto the stack from local
-	// variable 0
-	final static short	aload_1			= 0x2b;			// ? objectref loads a
-														// reference
-	// onto the stack from local
-	// variable 1
-	final static short	aload_2			= 0x2c;			// ? objectref loads a
-														// reference
-	// onto the stack from local
-	// variable 2
-	final static short	aload_3			= 0x2d;			// ? objectref loads a
-														// reference
-	// onto the stack from local
-	// variable 3
-	final static short	iaload			= 0x2e;			// arrayref, index ?
-														// value loads
-	// an int from an array
-	final static short	laload			= 0x2f;			// arrayref, index ?
-														// value load
-	// a long from an array
-	final static short	astore			= 0x3a;			// index objectref ?
-														// stores a
-	// reference into a local
-	// variable #index
-	final static short	istore_0		= 0x3b;			// value ? store int
-														// value into
-	// variable 0
-	final static short	istore_1		= 0x3c;			// value ? store int
-														// value into
-	// variable 1
-	final static short	istore_2		= 0x3d;			// value ? store int
-														// value into
-	// variable 2
-	final static short	istore_3		= 0x3e;			// value ? store int
-														// value into
-	// variable 3
-	final static short	lstore_0		= 0x3f;			// value ? store a long
-														// value in
-	// a local variable 0
-	final static short	dstore_3		= 0x4a;			// value ? stores a
-														// double into
-	// local variable 3
-	final static short	astore_0		= 0x4b;			// objectref ? stores a
-	// reference into local variable
-	// 0
-	final static short	astore_1		= 0x4c;			// objectref ? stores a
-	// reference into local variable
-	// 1
-	final static short	astore_2		= 0x4d;			// objectref ? stores a
-	// reference into local variable
-	// 2
-	final static short	astore_3		= 0x4e;			// objectref ? stores a
-	// reference into local variable
-	// 3
-	final static short	iastore			= 0x4f;			// arrayref, index,
-														// value ?
-	// stores an int into an array
-	final static short	dup_x1			= 0x5a;			// value2, value1 ?
-														// value1,
-	// value2, value1 inserts a copy
-	// of the top value into the
-	// stack two values from the top
-	final static short	dup_x2			= 0x5b;			// value3, value2,
-														// value1 ?
-	// value1, value3, value2,
-	// value1 inserts a copy of the
-	// top value into the stack two
-	// (if value2 is double or long
-	// it takes up the entry of
-	// value3, too) or three values
-	// (if value2 is neither double
-	// nor long) from the top
-	final static short	dup2			= 0x5c;			// {value2, value1} ?
-														// {value2,
-	// value1}, {value2, value1}
-	// duplicate top two stack words
-	// (two values, if value1 is not
-	// double nor long; a single
-	// value, if value1 is double or
-	// long)
-	final static short	dup2_x1			= 0x5d;			// value3, {value2,
-														// value1} ?
-	// {value2, value1}, value3,
-	// {value2, value1} duplicate
-	// two words and insert beneath
-	// third word (see explanation
-	// above)
-	final static short	dup2_x2			= 0x5e;			// {value4, value3},
-														// {value2,
-	// value1} ? {value2, value1},
-	// {value4, value3}, {value2,
-	// value1} duplicate two words
-	// and insert beneath fourth
-	// word
-	final static short	swap			= 0x5f;			// value2, value1 ?
-														// value1,
-	// value2 swaps two top words on
-	// the stack (note that value1
-	// and value2 must not be double
-	// or long)
-	final static short	fmul			= 0x6a;			// value1, value2 ?
-														// result
-	// multiplies two floats
-	final static short	dmul			= 0x6b;			// value1, value2 ?
-														// result
-	// multiplies two doubles
-	final static short	idiv			= 0x6c;			// value1, value2 ?
-														// result
-	// divides two integers
-	final static short	ldiv			= 0x6d;			// value1, value2 ?
-														// result
-	// divide two longs
-	final static short	fdiv			= 0x6e;			// value1, value2 ?
-														// result
-	// divides two floats
-	final static short	ddiv			= 0x6f;			// value1, value2 ?
-														// result
-	// divides two doubles
-	final static short	ishr			= 0x7a;			// value1, value2 ?
-														// result int
-	// shift right
-	final static short	lshr			= 0x7b;			// value1, value2 ?
-														// result
-	// bitwise shift right of a long
-	// value1 by value2 positions
-	final static short	iushr			= 0x7c;			// value1, value2 ?
-														// result int
-	// shift right
-	final static short	lushr			= 0x7d;			// value1, value2 ?
-														// result
-	// bitwise shift right of a long
-	// value1 by value2 positions,
-	// unsigned
-	final static short	iand			= 0x7e;			// value1, value2 ?
-														// result
-	// performs a logical and on two
-	// integers
-	final static short	land			= 0x7f;			// value1, value2 ?
-														// result
-	// bitwise and of two longs
-	final static short	l2d				= 0x8a;			// value ? result
-														// converts a
-	// long to a double
-	final static short	f2i				= 0x8b;			// value ? result
-														// converts a
-	// float to an int
-	final static short	f2l				= 0x8c;			// value ? result
-														// converts a
-	// float to a long
-	final static short	f2d				= 0x8d;			// value ? result
-														// converts a
-	// float to a double
-	final static short	d2i				= 0x8e;			// value ? result
-														// converts a
-	// double to an int
-	final static short	d2l				= 0x8f;			// value ? result
-														// converts a
-	// double to a long
-	final static short	ifne			= 0x9a;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is not 0,
-	// branch to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	iflt			= 0x9b;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is less than
-	// 0, branch to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	ifge			= 0x9c;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is greater
-	// than or equal to 0, branch to
-	// instruction at branchoffset
-	// (signed short constructed
-	// from unsigned bytes
-	// branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	ifgt			= 0x9d;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is greater
-	// than 0, branch to instruction
-	// at branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	ifle			= 0x9e;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is less than
-	// or equal to 0, branch to
-	// instruction at branchoffset
-	// (signed short constructed
-	// from unsigned bytes
-	// branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_icmpeq		= 0x9f;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if ints are
-	// equal, branch to instruction
-	// at branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_icmpne		= 0xa0;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if ints are
-	// not equal, branch to
-	// instruction at branchoffset
-	// (signed short constructed
-	// from unsigned bytes
-	// branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_icmplt		= 0xa1;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if value1 is
-	// less than value2, branch to
-	// instruction at branchoffset
-	// (signed short constructed
-	// from unsigned bytes
-	// branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_icmpge		= 0xa2;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if value1 is
-	// greater than or equal to
-	// value2, branch to instruction
-	// at branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_icmpgt		= 0xa3;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if value1 is
-	// greater than value2, branch
-	// to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_icmple		= 0xa4;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if value1 is
-	// less than or equal to value2,
-	// branch to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_acmpeq		= 0xa5;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if
-	// references are equal, branch
-	// to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	if_acmpne		= 0xa6;			// branchbyte1,
-														// branchbyte2
-	// value1, value2 ? if
-	// references are not equal,
-	// branch to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	goto_			= 0xa7;			// branchbyte1,
-														// branchbyte2 [no
-	// change] goes to another
-	// instruction at branchoffset
-	// (signed short constructed
-	// from unsigned bytes
-	// branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	jsr				= 0xa8;			// branchbyte1,
-														// branchbyte2 ?
-	// address jump to subroutine at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2) and place the
-	// return address on the stack
-	final static short	ret				= 0xa9;			// index [No change]
-														// continue
-	// execution from address taken
-	// from a local variable #index
-	// (the asymmetry with jsr is
-	// intentional)
-	final static short	tableswitch		= 0xaa;			// [0-3 bytes padding],
-	// defaultbyte1, defaultbyte2,
-	// defaultbyte3, defaultbyte4,
-	// lowbyte1, lowbyte2, lowbyte3,
-	// lowbyte4, highbyte1,
-	// highbyte2, highbyte3,
-	// highbyte4, jump offsets...
-	// index ? continue execution
-	// from an address in the table
-	// at offset index
-	final static short	lookupswitch	= 0xab;			// <0-3 bytes padding>,
-	// defaultbyte1, defaultbyte2,
-	// defaultbyte3, defaultbyte4,
-	// npairs1, npairs2, npairs3,
-	// npairs4, match-offset
-	// pairs... key ? a target
-	// address is looked up from a
-	// table using a key and
-	// execution continues from the
-	// instruction at that address
-	final static short	ireturn			= 0xac;			// value ? [empty]
-														// returns an
-	// integer from a method
-	final static short	lreturn			= 0xad;			// value ? [empty]
-														// returns a
-	// long value
-	final static short	freturn			= 0xae;			// value ? [empty]
-														// returns a
-	// float
-	final static short	dreturn			= 0xaf;			// value ? [empty]
-														// returns a
-	// double from a method
-	final static short	areturn			= 0xb0;			// objectref ? [empty]
-														// returns a
-	// reference from a method
-	final static short	return_			= 0xb1;			// ? [empty] return void
-														// from
-	// method
-	final static short	getstatic		= 0xb2;			// index1, index2 ?
-														// value gets a
-	// static field value of a
-	// class, where the field is
-	// identified by field reference
-	// in the constant pool index
-	// (index1 << 8 + index2)
-	final static short	putstatic		= 0xb3;			// indexbyte1,
-														// indexbyte2 value
-	// ? set static field to value
-	// in a class, where the field
-	// is identified by a field
-	// reference index in constant
-	// pool (indexbyte1 << 8 +
-	// indexbyte2)
-	final static short	getfield		= 0xb4;			// index1, index2
-														// objectref ?
-	// value gets a field value of
-	// an object objectref, where
-	// the field is identified by
-	// field reference in the
-	// constant pool index (index1
-	// << 8 + index2)
-	final static short	putfield		= 0xb5;			// indexbyte1,
-														// indexbyte2
-	// objectref, value ? set field
-	// to value in an object
-	// objectref, where the field is
-	// identified by a field
-	// reference index in constant
-	// pool (indexbyte1 << 8 +
-	// indexbyte2)
-	final static short	invokevirtual	= 0xb6;			// indexbyte1,
-														// indexbyte2
-	// objectref, [arg1, arg2, ...]
-	// ? invoke virtual method on
-	// object objectref, where the
-	// method is identified by
-	// method reference index in
-	// constant pool (indexbyte1 <<
-	// 8 + indexbyte2)
-	final static short	invokespecial	= 0xb7;			// indexbyte1,
-														// indexbyte2
-	// objectref, [arg1, arg2, ...]
-	// ? invoke instance method on
-	// object objectref, where the
-	// method is identified by
-	// method reference index in
-	// constant pool (indexbyte1 <<
-	// 8 + indexbyte2)
-	final static short	invokestatic	= 0xb8;			// indexbyte1,
-														// indexbyte2 [arg1,
-	// arg2, ...] ? invoke a static
-	// method, where the method is
-	// identified by method
-	// reference index in constant
-	// pool (indexbyte1 << 8 +
-	// indexbyte2)
-	final static short	invokeinterface	= 0xb9;			// indexbyte1,
-														// indexbyte2,
-	// count, 0 objectref, [arg1,
-	// arg2, ...] ? invokes an
-	// interface method on object
-	// objectref, where the
-	// interface method is
-	// identified by method
-	// reference index in constant
-	// pool (indexbyte1 << 8 +
-	// indexbyte2)
-	final static short	xxxunusedxxx	= 0xba;			// this opcode is
-														// reserved "for
-	// historical reasons"
-	final static short	new_			= 0xbb;			// indexbyte1,
-														// indexbyte2 ?
-	// objectref creates new object
-	// of type identified by class
-	// reference in constant pool
-	// index (indexbyte1 << 8 +
-	// indexbyte2)
-	final static short	newarray		= 0xbc;			// atype count ?
-														// arrayref
-	// creates new array with count
-	// elements of primitive type
-	// identified by atype
-	final static short	anewarray		= 0xbd;			// indexbyte1,
-														// indexbyte2 count
-	// ? arrayref creates a new
-	// array of references of length
-	// count and component type
-	// identified by the class
-	// reference index (indexbyte1
-	// << 8 + indexbyte2) in the
-	// constant pool
-	final static short	arraylength		= 0xbe;			// arrayref ? length
-														// gets the
-	// length of an array
-	final static short	athrow			= 0xbf;			// objectref ? [empty],
-	// objectref throws an error or
-	// exception (notice that the
-	// rest of the stack is cleared,
-	// leaving only a reference to
-	// the Throwable)
-	final static short	checkcast		= 0xc0;			// indexbyte1,
-														// indexbyte2
-	// objectref ? objectref checks
-	// whether an objectref is of a
-	// certain type, the class
-	// reference of which is in the
-	// constant pool at index
-	// (indexbyte1 << 8 +
-	// indexbyte2)
-	final static short	instanceof_		= 0xc1;			// indexbyte1,
-														// indexbyte2
-	// objectref ? result determines
-	// if an object objectref is of
-	// a given type, identified by
-	// class reference index in
-	// constant pool (indexbyte1 <<
-	// 8 + indexbyte2)
-	final static short	monitorenter	= 0xc2;			// objectref ? enter
-														// monitor for
-	// object ("grab the lock" -
-	// start of synchronized()
-	// section)
-	final static short	monitorexit		= 0xc3;			// objectref ? exit
-														// monitor for
-	// object ("release the lock" -
-	// end of synchronized()
-	// section)
-	final static short	wide			= 0xc4;			// opcode, indexbyte1,
-	// indexbyte2
-	final static short	multianewarray	= 0xc5;			// indexbyte1,
-														// indexbyte2,
-	// dimensions count1,
-	// [count2,...] ? arrayref
-	// create a new array of
-	// dimensions dimensions with
-	// elements of type identified
-	// by class reference in
-	// constant pool index
-	// (indexbyte1 << 8 +
-	// indexbyte2); the sizes of
-	// each dimension is identified
-	// by count1, [count2, etc]
-	final static short	ifnull			= 0xc6;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is null,
-	// branch to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	ifnonnull		= 0xc7;			// branchbyte1,
-														// branchbyte2
-	// value ? if value is not null,
-	// branch to instruction at
-	// branchoffset (signed short
-	// constructed from unsigned
-	// bytes branchbyte1 << 8 +
-	// branchbyte2)
-	final static short	goto_w			= 0xc8;			// branchbyte1,
-														// branchbyte2,
-	// branchbyte3, branchbyte4 [no
-	// change] goes to another
-	// instruction at branchoffset
-	// (signed int constructed from
-	// unsigned bytes branchbyte1 <<
-	// 24 + branchbyte2 << 16 +
-	// branchbyte3 << 8 +
-	// branchbyte4)
-	final static short	jsr_w			= 0xc9;			// branchbyte1,
-														// branchbyte2,
-	// branchbyte3, branchbyte4 ?
-	// address jump to subroutine at
-	// branchoffset (signed int
-	// constructed from unsigned
-	// bytes branchbyte1 << 24 +
-	// branchbyte2 << 16 +
-	// branchbyte3 << 8 +
-	// branchbyte4) and place the
-	// return address on the stack
-	final static short	breakpoint		= 0xca;			// reserved for
-														// breakpoints in
-	// Java debuggers; should not
-	// appear in any class file
-	final static short	impdep1			= 0xfe;			// reserved for
-	// implementation-dependent
-	// operations within debuggers;
-	// should not appear in any
-	// class file
-	final static short	impdep2			= 0xff;			// reserved for
-	// implementation-dependent
-	// operations within debuggers;
-	// should not appear in any
-	// class file
-
-	final static byte	OFFSETS[]		= new byte[256];
-
-	static {
-		OFFSETS[bipush] = 1; // byte ? value pushes a byte onto the
-		// stack as an integer value
-		OFFSETS[sipush] = 2; // byte1, byte2 ? value pushes a signed
-		// integer (byte1 << 8 + byte2) onto the
-		// stack
-		OFFSETS[ldc] = 1; // index ? value pushes a constant
-		// #index from a constant pool (String,
-		// int, float or class type) onto the
-		// stack
-		OFFSETS[ldc_w] = 2; // indexbyte1, indexbyte2 ? value pushes
-		// a constant #index from a constant
-		// pool (String, int, float or class
-		// type) onto the stack (wide index is
-		// constructed as indexbyte1 << 8 +
-		// indexbyte2)
-		OFFSETS[ldc2_w] = 2; // indexbyte1, indexbyte2 ? value pushes
-		// a constant #index from a constant
-		// pool (double or long) onto the stack
-		// (wide index is constructed as
-		// indexbyte1 << 8 + indexbyte2)
-		OFFSETS[iload] = 1; // index ? value loads an int value from
-		// a variable #index
-		OFFSETS[lload] = 1; // index ? value load a long value from
-		// a local variable #index
-		OFFSETS[fload] = 1; // index ? value loads a float value
-		// from a local variable #index
-		OFFSETS[dload] = 1; // index ? value loads a double value
-		// from a local variable #index
-		OFFSETS[aload] = 1; // index ? objectref loads a reference
-		// onto the stack from a local variable
-		// #index
-		OFFSETS[istore] = 1; // index value ? store int value into
-		// variable #index
-		OFFSETS[lstore] = 1; // index value ? store a long value in a
-		// local variable #index
-		OFFSETS[fstore] = 1; // index value ? stores a float value
-		// into a local variable #index
-		OFFSETS[dstore] = 1; // index value ? stores a double value
-		// into a local variable #index
-		OFFSETS[iinc] = 2; // index, const [No change] increment
-		// local variable #index by signed byte
-		// const
-		OFFSETS[ifeq] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is 0, branch to instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[astore] = 1; // index objectref ? stores a reference
-		// into a local variable #index
-		OFFSETS[ifne] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is not 0, branch to instruction
-		// at branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[iflt] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is less than 0, branch to
-		// instruction at branchoffset (signed
-		// short constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[ifge] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is greater than or equal to 0,
-		// branch to instruction at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2)
-		OFFSETS[ifgt] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is greater than 0, branch to
-		// instruction at branchoffset (signed
-		// short constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[ifle] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is less than or equal to 0,
-		// branch to instruction at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2)
-		OFFSETS[if_icmpeq] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if ints are equal,
-		// branch to instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[if_icmpne] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if ints are not equal,
-		// branch to instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[if_icmplt] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if value1 is less than
-		// value2, branch to instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[if_icmpge] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if value1 is greater
-		// than or equal to value2, branch
-		// to instruction at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2)
-		OFFSETS[if_icmpgt] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if value1 is greater
-		// than value2, branch to
-		// instruction at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2)
-		OFFSETS[if_icmple] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if value1 is less than
-		// or equal to value2, branch to
-		// instruction at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2)
-		OFFSETS[if_acmpeq] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if references are equal,
-		// branch to instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[if_acmpne] = 2; // branchbyte1, branchbyte2 value1,
-		// value2 ? if references are not
-		// equal, branch to instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[goto_] = 2; // branchbyte1, branchbyte2 [no change]
-		// goes to another instruction at
-		// branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[jsr] = 2; // branchbyte1, branchbyte2 ? address
-		// jump to subroutine at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2) and place the return
-		// address on the stack
-		OFFSETS[ret] = 1; // index [No change] continue execution
-		// from address taken from a local
-		// variable #index (the asymmetry with
-		// jsr is intentional)
-		OFFSETS[tableswitch] = -1; // [0-3 bytes padding],
-		// defaultbyte1, defaultbyte2,
-		// defaultbyte3, defaultbyte4,
-		// lowbyte1, lowbyte2, lowbyte3,
-		// lowbyte4, highbyte1,
-		// highbyte2, highbyte3,
-		// highbyte4, jump offsets...
-		// index ? continue execution
-		// from an address in the table
-		// at offset index
-		OFFSETS[lookupswitch] = -1; // <0-3 bytes padding>,
-		// defaultbyte1, defaultbyte2,
-		// defaultbyte3, defaultbyte4,
-		// npairs1, npairs2, npairs3,
-		// npairs4, match-offset
-		// pairs... key ? a target
-		// address is looked up from a
-		// table using a key and
-		// execution continues from the
-		// instruction at that address
-		OFFSETS[getstatic] = 2; // index1, index2 ? value gets a
-		// static field value of a class,
-		// where the field is identified by
-		// field reference in the constant
-		// pool index (index1 << 8 + index2)
-		OFFSETS[putstatic] = 2; // indexbyte1, indexbyte2 value ?
-		// set static field to value in a
-		// class, where the field is
-		// identified by a field reference
-		// index in constant pool
-		// (indexbyte1 << 8 + indexbyte2)
-		OFFSETS[getfield] = 2; // index1, index2 objectref ? value
-		// gets a field value of an object
-		// objectref, where the field is
-		// identified by field reference in
-		// the constant pool index (index1
-		// << 8 + index2)
-		OFFSETS[putfield] = 2; // indexbyte1, indexbyte2 objectref,
-		// value ? set field to value in an
-		// object objectref, where the field
-		// is identified by a field
-		// reference index in constant pool
-		// (indexbyte1 << 8 + indexbyte2)
-		OFFSETS[invokevirtual] = 2; // indexbyte1, indexbyte2
-		// objectref, [arg1, arg2, ...]
-		// ? invoke virtual method on
-		// object objectref, where the
-		// method is identified by
-		// method reference index in
-		// constant pool (indexbyte1 <<
-		// 8 + indexbyte2)
-		OFFSETS[invokespecial] = 2; // indexbyte1, indexbyte2
-		// objectref, [arg1, arg2, ...]
-		// ? invoke instance method on
-		// object objectref, where the
-		// method is identified by
-		// method reference index in
-		// constant pool (indexbyte1 <<
-		// 8 + indexbyte2)
-		OFFSETS[invokestatic] = 2; // indexbyte1, indexbyte2 [arg1,
-		// arg2, ...] ? invoke a static
-		// method, where the method is
-		// identified by method
-		// reference index in constant
-		// pool (indexbyte1 << 8 +
-		// indexbyte2)
-		OFFSETS[invokeinterface] = 2; // indexbyte1, indexbyte2,
-		// count, 0 objectref,
-		// [arg1, arg2, ...] ?
-		// invokes an interface
-		// method on object
-		// objectref, where the
-		// interface method is
-		// identified by method
-		// reference index in
-		// constant pool (indexbyte1
-		// << 8 + indexbyte2)
-		OFFSETS[new_] = 2; // indexbyte1, indexbyte2 ? objectref
-		// creates new object of type identified
-		// by class reference in constant pool
-		// index (indexbyte1 << 8 + indexbyte2)
-		OFFSETS[newarray] = 1; // atype count ? arrayref creates
-		// new array with count elements of
-		// primitive type identified by
-		// atype
-		OFFSETS[anewarray] = 2; // indexbyte1, indexbyte2 count ?
-		// arrayref creates a new array of
-		// references of length count and
-		// component type identified by the
-		// class reference index (indexbyte1
-		// << 8 + indexbyte2) in the
-		// constant pool
-		OFFSETS[checkcast] = 2; // indexbyte1, indexbyte2 objectref
-		// ? objectref checks whether an
-		// objectref is of a certain type,
-		// the class reference of which is
-		// in the constant pool at index
-		// (indexbyte1 << 8 + indexbyte2)
-		OFFSETS[instanceof_] = 2; // indexbyte1, indexbyte2 objectref
-		// ? result determines if an object
-		// objectref is of a given type,
-		// identified by class reference
-		// index in constant pool
-		// (indexbyte1 << 8 + indexbyte2)
-		OFFSETS[wide] = 3; // opcode, indexbyte1, indexbyte2
-		OFFSETS[multianewarray] = 3; // indexbyte1, indexbyte2,
-		// dimensions count1,
-		// [count2,...] ? arrayref
-		// create a new array of
-		// dimensions dimensions with
-		// elements of type identified
-		// by class reference in
-		// constant pool index
-		// (indexbyte1 << 8 +
-		// indexbyte2); the sizes of
-		// each dimension is identified
-		// by count1, [count2, etc]
-		OFFSETS[ifnull] = 2; // branchbyte1, branchbyte2 value ? if
-		// value is null, branch to instruction
-		// at branchoffset (signed short
-		// constructed from unsigned bytes
-		// branchbyte1 << 8 + branchbyte2)
-		OFFSETS[ifnonnull] = 2; // branchbyte1, branchbyte2 value ?
-		// if value is not null, branch to
-		// instruction at branchoffset
-		// (signed short constructed from
-		// unsigned bytes branchbyte1 << 8 +
-		// branchbyte2)
-		OFFSETS[goto_w] = 4; // branchbyte1, branchbyte2,
-		// branchbyte3, branchbyte4 [no change]
-		// goes to another instruction at
-		// branchoffset (signed int constructed
-		// from unsigned bytes branchbyte1 << 24
-		// + branchbyte2 << 16 + branchbyte3 <<
-		// 8 + branchbyte4)
-		OFFSETS[jsr_w] = 4; // branchbyte1, branchbyte2,
-		// branchbyte3, branchbyte4 ? address
-		// jump to subroutine at branchoffset
-		// (signed int constructed from unsigned
-		// bytes branchbyte1 << 24 + branchbyte2
-		// << 16 + branchbyte3 << 8 +
-		// branchbyte4) and place the return
-		// address on the stack
-	}
-
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/PreprocessResource.java b/bundleplugin/src/main/java/aQute/lib/osgi/PreprocessResource.java
deleted file mode 100644
index 8299af8..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/PreprocessResource.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package aQute.lib.osgi;
-
-import java.io.*;
-
-public class PreprocessResource extends AbstractResource {
-    final Resource  resource;
-    final Processor processor;
-
-    public PreprocessResource(Processor processor, Resource r) {
-        super(r.lastModified());
-        this.processor = processor;
-        this.resource = r;
-        extra = resource.getExtra();
-    }
-
-    protected byte[] getBytes() throws IOException {
-        ByteArrayOutputStream bout = new ByteArrayOutputStream(2000);
-        OutputStreamWriter osw = new OutputStreamWriter(bout);
-        PrintWriter pw = new PrintWriter(osw);
-        InputStream in = resource.openInputStream();
-        try {
-            BufferedReader rdr = new BufferedReader(new InputStreamReader(in));
-            String line = rdr.readLine();
-            while (line != null) {
-                line = processor.getReplacer().process(line);
-                pw.println(line);
-                line = rdr.readLine();
-            }
-            pw.flush();
-            byte [] data= bout.toByteArray();
-            return data;
-                
-        } finally {
-            in.close();
-        }        
-    }
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Processor.java b/bundleplugin/src/main/java/aQute/lib/osgi/Processor.java
deleted file mode 100644
index 29da425..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Processor.java
+++ /dev/null
@@ -1,1005 +0,0 @@
-/* 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.net.*;
-import java.util.*;
-import java.util.jar.*;
-
-import aQute.bnd.make.*;
-import aQute.bnd.service.*;
-import aQute.libg.header.*;
-import aQute.libg.reporter.*;
-
-public class Processor implements Reporter, Constants, Closeable {
-    // TODO handle include files out of date
-    public static String    DEFAULT_PLUGINS = "";                            // "aQute.lib.spring.SpringComponent";
-    // TODO make splitter skip eagerly whitespace so trim is not necessary
-    public static String    LIST_SPLITTER   = "\\\\?\\s*,\\s*";
-    private List<String>    errors          = new ArrayList<String>();
-    private List<String>    warnings        = new ArrayList<String>();
-    boolean                 pedantic;
-    boolean                 trace;
-    boolean                 exceptions;
-    boolean                 fileMustExist   = true;
-
-    List<Object>            plugins;
-    private File            base            = new File("").getAbsoluteFile();
-    private List<Closeable> toBeClosed      = newList();
-
-    final Properties        properties;
-    private Macro           replacer;
-    private long            lastModified;
-    private File            propertiesFile;
-    private boolean         fixup           = true;
-    long                    modified;
-    Processor               parent;
-    Set<File>               included;
-    CL                      pluginLoader;
-    
-    public Processor() {
-        properties = new Properties();
-    }
-
-    public Processor(Properties parent) {
-        properties = new Properties(parent);
-    }
-
-    public Processor(Processor parent) {
-        this(parent.properties);
-        this.parent = parent;
-    }
-
-    public void setParent(Processor processor) {
-        this.parent = processor;
-    }
-
-    public Processor getParent() {
-        return parent;
-    }
-
-    public void getInfo(Processor processor, String prefix) {
-        if (isFailOk())
-            addAll(warnings, processor.getErrors(), prefix);
-        else
-            addAll(errors, processor.getErrors(), prefix);
-        addAll(warnings, processor.getWarnings(), prefix);
-
-        processor.errors.clear();
-        processor.warnings.clear();
-    }
-
-    public void getInfo(Processor processor) {
-        getInfo(processor, "");
-    }
-
-    private <T> void addAll(List<String> to, List<? extends T> from,
-            String prefix) {
-        for (T x : from) {
-            to.add(prefix + x);
-        }
-    }
-
-    public void warning(String string, Object ...args) {
-        String s = String.format(string,args);
-        if ( ! warnings.contains(s))
-            warnings.add(s);
-    }
-
-    public void error(String string, Object ...args) {
-        if (isFailOk())
-            warning(string, args);
-        else {
-            String s = String.format(string,args);
-            if ( ! errors.contains(s))
-                errors.add(s);
-        }
-    }
-
-    public void error(String string, Throwable t, Object ... args) {
-        if (isFailOk())
-            warning(string + ": " + t, args);
-        else{
-            String s = String.format(string,args);
-            if ( ! errors.contains(s))
-                errors.add(s);
-        }
-        if (exceptions)
-            t.printStackTrace();
-    }
-
-    public List<String> getWarnings() {
-        return warnings;
-    }
-
-    public List<String> getErrors() {
-        return errors;
-    }
-
-    public Map<String, Map<String, String>> parseHeader(String value) {
-        return parseHeader(value, this);
-    }
-
-    /**
-     * Standard OSGi header parser.
-     * 
-     * @param value
-     * @return
-     */
-    @SuppressWarnings("unchecked")
-    static public Map<String, Map<String, String>> parseHeader(String value,
-            Processor logger) {
-        return OSGiHeader.parseHeader(value, logger);
-    }
-
-    Map<String, Map<String, String>> getClauses(String header) {
-        return parseHeader(getProperty(header));
-    }
-
-    public void addClose(Closeable jar) {
-        toBeClosed.add(jar);
-    }
-
-    /**
-     * Remove all entries from a map that start with a specific prefix
-     * 
-     * @param <T>
-     * @param source
-     * @param prefix
-     * @return
-     */
-    static <T> Map<String, T> removeKeys(Map<String, T> source, String prefix) {
-        Map<String, T> temp = new TreeMap<String, T>(source);
-        for (Iterator<String> p = temp.keySet().iterator(); p.hasNext();) {
-            String pack = (String) p.next();
-            if (pack.startsWith(prefix))
-                p.remove();
-        }
-        return temp;
-    }
-
-    public void progress(String s, Object ... args) {
-        // System.out.println(s);
-    }
-
-    public boolean isPedantic() {
-        return pedantic;
-    }
-
-    public void setPedantic(boolean pedantic) { // System.out.println("Set
-        // pedantic: " + pedantic + " "
-        // + this );
-        this.pedantic = pedantic;
-    }
-
-    public static File getFile(File base, String file) {
-        File f = new File(file);
-        if (f.isAbsolute())
-            return f;
-        int n;
-
-        f = base.getAbsoluteFile();
-        while ((n = file.indexOf('/')) > 0) {
-            String first = file.substring(0, n);
-            file = file.substring(n + 1);
-            if (first.equals(".."))
-                f = f.getParentFile();
-            else
-                f = new File(f, first);
-        }
-        return new File(f, file).getAbsoluteFile();
-    }
-
-    public File getFile(String file) {
-        return getFile(base, file);
-    }
-
-    /**
-     * Return a list of plugins that implement the given class.
-     * 
-     * @param clazz
-     *            Each returned plugin implements this class/interface
-     * @return A list of plugins
-     */
-    public <T> List<T> getPlugins(Class<T> clazz) {
-        List<T> l = new ArrayList<T>();
-        List<Object> all = getPlugins();
-        for (Object plugin : all) {
-            if (clazz.isInstance(plugin))
-                l.add(clazz.cast(plugin));
-        }
-        return l;
-    }
-
-    /**
-     * Return a list of plugins. Plugins are defined with the -plugin command.
-     * They are class names, optionally associated with attributes. Plugins can
-     * implement the Plugin interface to see these attributes.
-     * 
-     * Any object can be a plugin.
-     * 
-     * @return
-     */
-    protected List<Object> getPlugins() {
-        if ( parent != null )
-            return parent.getPlugins();
-            
-        if (this.plugins != null)
-            return this.plugins;
-
-        String spe = getProperty(Analyzer.PLUGIN, DEFAULT_PLUGINS);
-        Map<String, Map<String, String>> plugins = parseHeader(spe);
-        List<Object> list = new ArrayList<Object>();
-
-        // Add the default plugins. Only if non is specified
-        // will they be removed.
-        list.add(new MakeBnd());
-        list.add(new MakeCopy());
-
-        for (Map.Entry<String, Map<String, String>> entry : plugins.entrySet()) {
-            String key = (String) entry.getKey();
-            if (key.equals("none"))
-                return this.plugins = newList();
-
-            try {
-                CL loader = getLoader();
-                String path = entry.getValue().get("path:");
-                if ( path != null ) {
-                    File f = getFile(path).getAbsoluteFile();
-                    loader.add(f.toURL());
-                }
-                
-                trace("Using plugin %s", key);
-
-                // Plugins could use the same class with different
-                // parameters so we could have duplicate names Remove
-                // the ! added by the parser to make each name unique.
-                key = removeDuplicateMarker(key);
-
-                Class<?> c = (Class<?>) loader.loadClass(
-                        key);
-                Object plugin = c.newInstance();
-                if (plugin instanceof Plugin) {
-                    ((Plugin) plugin).setProperties(entry.getValue());
-                    ((Plugin) plugin).setReporter(this);
-                }
-                list.add(plugin);
-            } catch (Exception e) {
-                error("Problem loading the plugin: " + key + " exception: " + e);
-            }
-        }
-        return this.plugins = list;
-    }
-
-    public boolean isFailOk() {
-        String v = getProperty(Analyzer.FAIL_OK, null);
-        return v != null && v.equalsIgnoreCase("true");
-    }
-
-    public File getBase() {
-        return base;
-    }
-
-    public void setBase(File base) {
-        this.base = base;
-    }
-
-    public void clear() {
-        errors.clear();
-        warnings.clear();
-    }
-
-    public void trace(String msg, Object... parms) {
-        if (trace) {
-            System.out.printf("# " + msg + "\n", parms);
-        }
-    }
-
-    public <T> List<T> newList() {
-        return new ArrayList<T>();
-    }
-
-    public <T> Set<T> newSet() {
-        return new TreeSet<T>();
-    }
-
-    public static <K, V> Map<K, V> newMap() {
-        return new LinkedHashMap<K, V>();
-    }
-
-    public static <K, V> Map<K, V> newHashMap() {
-        return new HashMap<K, V>();
-    }
-
-    public <T> List<T> newList(Collection<T> t) {
-        return new ArrayList<T>(t);
-    }
-
-    public <T> Set<T> newSet(Collection<T> t) {
-        return new TreeSet<T>(t);
-    }
-
-    public <K, V> Map<K, V> newMap(Map<K, V> t) {
-        return new LinkedHashMap<K, V>(t);
-    }
-
-    public void close() {
-        for (Closeable c : toBeClosed) {
-            try {
-                c.close();
-            } catch (IOException e) {
-                // Who cares?
-            }
-        }
-        toBeClosed = null;
-    }
-
-    public String _basedir(String args[]) {
-        if (base == null)
-            throw new IllegalArgumentException("No base dir set");
-
-        return base.getAbsolutePath();
-    }
-
-    /**
-     * Property handling ...
-     * 
-     * @return
-     */
-
-    public Properties getProperties() {
-        if (fixup) {
-            fixup = false;
-            begin();
-        }
-
-        return properties;
-    }
-
-    public String getProperty(String key) {
-        return getProperty(key, null);
-    }
-
-    public void mergeProperties(File file, boolean override) {
-        if (file.isFile()) {
-            try {
-                Properties properties = loadProperties(file);
-                mergeProperties(properties, override);
-            } catch (Exception e) {
-                error("Error loading properties file: " + file);
-            }
-        } else {
-            if (!file.exists())
-                error("Properties file does not exist: " + file);
-            else
-                error("Properties file must a file, not a directory: " + file);
-        }
-    }
-
-    public void mergeProperties(Properties properties, boolean override) {
-        for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements();) {
-            String key = (String) e.nextElement();
-            String value = properties.getProperty(key);
-            if (override || !getProperties().containsKey(key))
-                setProperty(key, value);
-        }
-    }
-
-    public void setProperties(Properties properties) {
-        doIncludes(getBase(), properties, new HashSet<String>());
-        this.properties.putAll(properties);
-    }
-
-    public void addProperties(File file) throws Exception {
-        addIncluded(file);
-        Properties p = loadProperties(file);
-        setProperties(p);
-    }
-
-    public synchronized void addIncluded(File file) {
-        if (included == null)
-            included = new HashSet<File>();
-        included.add(file);
-    }
-
-    /**
-     * Inspect the properties and if you find -includes parse the line included
-     * manifest files or properties files. The files are relative from the given
-     * base, this is normally the base for the analyzer.
-     * 
-     * @param ubase
-     * @param p
-     * @param done
-     * @throws IOException
-     */
-    private void doIncludes(File ubase, Properties p, Set<String> done) {
-        String includes = p.getProperty(INCLUDE);
-        if (includes != null) {
-            includes = getReplacer().process(includes);
-            p.remove(INCLUDE);
-            Collection<String> clauses = parseHeader(includes).keySet();
-
-            for (String value : clauses) {
-                boolean fileMustExist = true;
-                boolean overwrite = true;
-                while (true) {
-                    if (value.startsWith("-")) {
-                        fileMustExist = false;
-                        value = value.substring(1).trim();
-                    } else if (value.startsWith("~")) {
-                        // Overwrite properties!
-                        overwrite = false;
-                        value = value.substring(1).trim();
-                    } else
-                        break;
-                }
-                try {
-                    File file = getFile(ubase, value).getAbsoluteFile();
-                    if (file.isFile()) {
-                        if (included != null && included.contains(file)) {
-                            error("Cyclic include of " + file);
-                        } else {
-                            addIncluded(file);
-                            updateModified(file.lastModified(), "Include "
-                                    + value);
-                            InputStream in = new FileInputStream(file);
-                            Properties sub;
-                            if (file.getName().toLowerCase().endsWith(".mf")) {
-                                sub = getManifestAsProperties(in);
-                            } else
-                                sub = loadProperties(in, file.getAbsolutePath());
-                            in.close();
-
-                            doIncludes(file.getParentFile(), sub, done);
-                            // make sure we do not override properties
-                            if (!overwrite)
-                                sub.keySet().removeAll(p.keySet());
-                            p.putAll(sub);
-                        }
-                    } else {
-                        if (fileMustExist)
-                            error("Included file "
-                                    + file
-                                    + (file.exists() ? " does not exist"
-                                            : " is directory"));
-                    }
-                } catch (IOException e) {
-                    if (fileMustExist)
-                        error("Error in processing included file: " + value, e);
-                }
-            }
-        }
-    }
-
-    public void unsetProperty(String string) {
-        getProperties().remove(string);
-
-    }
-
-    public boolean refresh() {
-        if (propertiesFile == null)
-            return false;
-
-        boolean changed = false;
-        if (included != null) {
-            for (File file : included) {
-
-                if (file.lastModified() > modified) {
-                    changed = true;
-                    break;
-                }
-            }
-        }
-
-        // System.out.println("Modified " + modified + " file: "
-        // + propertiesFile.lastModified() + " diff "
-        // + (modified - propertiesFile.lastModified()));
-
-        //Date last = new Date(propertiesFile.lastModified());
-        //Date current = new Date(modified);
-        changed |= modified < propertiesFile.lastModified();
-        if (changed) {
-            included = null;
-            properties.clear();
-            plugins = null;
-            setProperties(propertiesFile, base);
-            propertiesChanged();
-            return true;
-        }
-        return false;
-    }
-
-    public void propertiesChanged() {
-    }
-
-    /**
-     * Set the properties by file. Setting the properties this way will also set
-     * the base for this analyzer. After reading the properties, this will call
-     * setProperties(Properties) which will handle the includes.
-     * 
-     * @param propertiesFile
-     * @throws FileNotFoundException
-     * @throws IOException
-     */
-    public void setProperties(File propertiesFile) throws IOException {
-        propertiesFile = propertiesFile.getAbsoluteFile();
-        setProperties(propertiesFile, propertiesFile.getParentFile());
-    }
-
-    public void setProperties(File propertiesFile, File base) {
-        this.propertiesFile = propertiesFile.getAbsoluteFile();
-        setBase(base);
-        try {
-            if (propertiesFile.isFile()) {
-                // System.out.println("Loading properties " + propertiesFile);
-                long modified = propertiesFile.lastModified();
-                if ( modified > System.currentTimeMillis() +100) {
-                    System.out.println("Huh? This is in the future " + propertiesFile );
-                    this.modified = System.currentTimeMillis();
-                } else
-                    this.modified = modified;
-                
-                included = null;
-                Properties p = loadProperties(propertiesFile);
-                setProperties(p);
-            } else {
-                if (fileMustExist) {
-                    error("No such properties file: " + propertiesFile);
-                }
-            }
-        } catch (IOException e) {
-            error("Could not load properties " + propertiesFile);
-        }
-    }
-
-    protected void begin() {
-        if (isTrue(getProperty(PEDANTIC)))
-            setPedantic(true);
-    }
-
-    public static boolean isTrue(String value) {
-        return "true".equalsIgnoreCase(value);
-    }
-
-    /**
-     * Get a property with a proper default
-     * 
-     * @param headerName
-     * @param deflt
-     * @return
-     */
-    public String getProperty(String key, String deflt) {
-        String value = getProperties().getProperty(key);
-        if (value != null)
-            return getReplacer().process(value);
-        else if (deflt != null)
-            return getReplacer().process(deflt);
-        else
-            return null;
-    }
-
-    /**
-     * Helper to load a properties file from disk.
-     * 
-     * @param file
-     * @return
-     * @throws IOException
-     */
-    public Properties loadProperties(File file) throws IOException {
-        updateModified(file.lastModified(), "Properties file: " + file);
-        InputStream in = new FileInputStream(file);
-        Properties p = loadProperties(in, file.getAbsolutePath());
-        in.close();
-        return p;
-    }
-
-    Properties loadProperties(InputStream in, String name) throws IOException {
-        int n = name.lastIndexOf('/');
-        if (n > 0)
-            name = name.substring(0, n);
-        if (name.length() == 0)
-            name = ".";
-
-        try {
-            Properties p = new Properties();
-            p.load(in);
-            return replaceAll(p, "\\$\\{\\.\\}", name);
-        } catch (Exception e) {
-            error("Error during loading properties file: " + name + ", error:"
-                    + e);
-            return new Properties();
-        }
-    }
-
-    /**
-     * Replace a string in all the values of the map. This can be used to
-     * preassign variables that change. I.e. the base directory ${.} for a
-     * loaded properties
-     */
-
-    public static Properties replaceAll(Properties p, String pattern,
-            String replacement) {
-        Properties result = new Properties();
-        for (Iterator<Map.Entry<Object, Object>> i = p.entrySet().iterator(); i
-                .hasNext();) {
-            Map.Entry<Object, Object> entry = i.next();
-            String key = (String) entry.getKey();
-            String value = (String) entry.getValue();
-            value = value.replaceAll(pattern, replacement);
-            result.put(key, value);
-        }
-        return result;
-    }
-
-    /**
-     * Merge the attributes of two maps, where the first map can contain
-     * wildcarded names. The idea is that the first map contains patterns (for
-     * example *) with a set of attributes. These patterns are matched against
-     * the found packages in actual. If they match, the result is set with the
-     * merged set of attributes. It is expected that the instructions are
-     * ordered so that the instructor can define which pattern matches first.
-     * Attributes in the instructions override any attributes from the actual.<br/>
-     * 
-     * A pattern is a modified regexp so it looks like globbing. The * becomes a .*
-     * just like the ? becomes a .?. '.' are replaced with \\. Additionally, if
-     * the pattern starts with an exclamation mark, it will remove that matches
-     * for that pattern (- the !) from the working set. So the following
-     * patterns should work:
-     * <ul>
-     * <li>com.foo.bar</li>
-     * <li>com.foo.*</li>
-     * <li>com.foo.???</li>
-     * <li>com.*.[^b][^a][^r]</li>
-     * <li>!com.foo.* (throws away any match for com.foo.*)</li>
-     * </ul>
-     * Enough rope to hang the average developer I would say.
-     * 
-     * 
-     * @param instructions
-     *            the instructions with patterns. A
-     * @param actual
-     *            the actual found packages
-     */
-
-    public static Map<String, Map<String, String>> merge(String type,
-            Map<String, Map<String, String>> instructions,
-            Map<String, Map<String, String>> actual,
-            Set<String> superfluous,
-            Map<String, Map<String,String>> ignored) {
-        Map<String, Map<String, String>> toVisit = new HashMap<String, Map<String, String>>(
-                actual); // we do not want to ruin our
-        // original
-        Map<String, Map<String, String>> result = newMap();
-        for (Iterator<String> i = instructions.keySet().iterator(); i.hasNext();) {
-            String instruction = i.next();
-            String originalInstruction = instruction;
-
-            Map<String, String> instructedAttributes = instructions
-                    .get(instruction);
-
-            // Check if we have a fixed (starts with '=') or a
-            // duplicate name. A fixed name is added to the output without
-            // checking against the contents. Duplicates are marked
-            // at the end. In that case we do not pick up any contained
-            // information but just add them to the output including the
-            // marker.
-            if (instruction.startsWith("=")) {
-                result.put(instruction.substring(1), instructedAttributes);
-                superfluous.remove(originalInstruction);
-                continue;
-            }
-            if (isDuplicate(instruction)) {
-                result.put(instruction, instructedAttributes);
-                superfluous.remove(originalInstruction);
-                continue;
-            }
-
-            Instruction instr = Instruction.getPattern(instruction);
-
-            for (Iterator<String> p = toVisit.keySet().iterator(); p.hasNext();) {
-                String packageName = p.next();
-
-                if (instr.matches(packageName)) {
-                    superfluous.remove(originalInstruction);
-                    if (!instr.isNegated()) {
-                        Map<String, String> newAttributes = new HashMap<String, String>();
-                        newAttributes.putAll(actual.get(packageName));
-                        newAttributes.putAll(instructedAttributes);
-                        result.put(packageName, newAttributes);
-                    } else if (ignored != null) {
-                        ignored.put(packageName, new HashMap<String, String>());
-                    }
-                    p.remove(); // Can never match again for another pattern
-                }
-            }
-
-        }
-        return result;
-    }
-
-    /**
-     * Print a standard Map based OSGi header.
-     * 
-     * @param exports
-     *            map { name => Map { attribute|directive => value } }
-     * @return the clauses
-     */
-    public static String printClauses(Map<String, Map<String, String>> exports,
-            String allowedDirectives) {
-        return printClauses(exports, allowedDirectives, false);
-    }
-
-    public static String printClauses(Map<String, Map<String, String>> exports,
-            String allowedDirectives, boolean checkMultipleVersions) {
-        StringBuffer sb = new StringBuffer();
-        String del = "";
-        for (Iterator<String> i = exports.keySet().iterator(); i.hasNext();) {
-            String name = i.next();
-            Map<String, String> clause = exports.get(name);
-
-            // We allow names to be duplicated in the input
-            // by ending them with '~'. This is necessary to use
-            // the package names as keys. However, we remove these
-            // suffixes in the output so that you can set multiple
-            // exports with different attributes.
-            String outname = removeDuplicateMarker(name);
-            sb.append(del);
-            sb.append(outname);
-            printClause(clause, allowedDirectives, sb);
-            del = ",";
-        }
-        return sb.toString();
-    }
-
-    public static void printClause(Map<String, String> map,
-            String allowedDirectives, StringBuffer sb) {
-
-        for (Iterator<String> j = map.keySet().iterator(); j.hasNext();) {
-            String key = j.next();
-
-            // Skip directives we do not recognize
-            if (!key.startsWith("x-")
-                    && key.endsWith(":")
-                    && (allowedDirectives == null || allowedDirectives
-                            .indexOf(key) < 0))
-                continue;
-
-            String value = ((String) map.get(key)).trim();
-            sb.append(";");
-            sb.append(key);
-            sb.append("=");
-
-            boolean clean = (value.length() >= 2 && value.charAt(0) == '"' && value
-                    .charAt(value.length() - 1) == '"')
-                    || Verifier.TOKEN.matcher(value).matches();
-            if (!clean)
-                sb.append("\"");
-            sb.append(value);
-            if (!clean)
-                sb.append("\"");
-        }
-    }
-
-    public Macro getReplacer() {
-        if (replacer == null)
-            return replacer = new Macro(getProperties(), this,
-                    getMacroDomains());
-        else
-            return replacer;
-    }
-
-    /**
-     * This should be overridden by subclasses to add extra macro command
-     * domains on the search list.
-     * 
-     * @return
-     */
-    protected Object[] getMacroDomains() {
-        return new Object[] {};
-    }
-
-    /**
-     * Return the properties but expand all macros. This always returns a new
-     * Properties object that can be used in any way.
-     * 
-     * @return
-     */
-    public Properties getFlattenedProperties() {
-        return getReplacer().getFlattenedProperties();
-
-    }
-
-    public void updateModified(long time, String reason) {
-        if (time > lastModified) {
-            lastModified = time;
-        }
-    }
-
-    public long lastModified() {
-        return lastModified;
-    }
-
-    /**
-     * Add or override a new property.
-     * 
-     * @param key
-     * @param value
-     */
-    public void setProperty(String key, String value) {
-        checkheader: for (int i = 0; i < headers.length; i++) {
-            if (headers[i].equalsIgnoreCase(value)) {
-                value = headers[i];
-                break checkheader;
-            }
-        }
-        getProperties().put(key, value);
-    }
-
-    /**
-     * Read a manifest but return a properties object.
-     * 
-     * @param in
-     * @return
-     * @throws IOException
-     */
-    public static Properties getManifestAsProperties(InputStream in)
-            throws IOException {
-        Properties p = new Properties();
-        Manifest manifest = new Manifest(in);
-        for (Iterator<Object> it = manifest.getMainAttributes().keySet()
-                .iterator(); it.hasNext();) {
-            Attributes.Name key = (Attributes.Name) it.next();
-            String value = manifest.getMainAttributes().getValue(key);
-            p.put(key.toString(), value);
-        }
-        return p;
-    }
-
-    public File getPropertiesFile() {
-        return propertiesFile;
-    }
-
-    public void setFileMustExist(boolean mustexist) {
-        fileMustExist = mustexist;
-    }
-
-    static public String read(InputStream in) throws Exception {
-        InputStreamReader ir = new InputStreamReader(in);
-        StringBuilder sb = new StringBuilder();
-
-        try {
-            char chars[] = new char[1000];
-            int size = ir.read(chars);
-            while (size > 0) {
-                sb.append(chars, 0, size);
-                size = ir.read(chars);
-            }
-        } finally {
-            ir.close();
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Join a list.
-     * 
-     * @param args
-     * @return
-     */
-    public static String join(Collection<?> list, String delimeter) {
-        if ( list == null )
-            return "";
-        StringBuilder sb = new StringBuilder();
-        String del = "";
-        for (Object item : list) {
-            sb.append(del);
-            sb.append(item);
-            del = delimeter;
-        }
-        return sb.toString();
-    }
-
-    public static String join(Collection<?> list) {
-        return join(list, ",");
-    }
-
-    public static void split(String s, Collection<String> set) {
-
-        String elements[] = s.trim().split(LIST_SPLITTER);
-        for (String element : elements) {
-            if (element.length() > 0)
-                set.add(element);
-        }
-    }
-
-    public static Collection<String> split(String s) {
-        return split(s, LIST_SPLITTER);
-    }
-
-    public static Collection<String> split(String s, String splitter) {
-        if (s == null || s.trim().length() == 0)
-            return Collections.emptyList();
-
-        return Arrays.asList(s.split(splitter));
-    }
-
-    public boolean isExceptions() {
-        return exceptions;
-    }
-
-    public void setExceptions(boolean exceptions) {
-        this.exceptions = exceptions;
-    }
-
-    /**
-     * Make the file short if it is inside our base directory, otherwise long.
-     * 
-     * @param f
-     * @return
-     */
-    public String normalize(String f) {
-        if (f.startsWith(base.getAbsolutePath() + "/"))
-            return f.substring(base.getAbsolutePath().length() + 1);
-        else
-            return f;
-    }
-
-    public String normalize(File f) {
-        return normalize(f.getAbsolutePath());
-    }
-
-    public static String removeDuplicateMarker(String key) {
-        int i = key.length() - 1;
-        while (i >= 0 && key.charAt(i) == DUPLICATE_MARKER)
-            --i;
-
-        return key.substring(0, i + 1);
-    }
-
-    public static boolean isDuplicate(String name) {
-        return name.length() > 0
-                && name.charAt(name.length() - 1) == DUPLICATE_MARKER;
-    }
-    
-    public void setTrace(boolean x ) {
-        trace = x;
-    }
-
-
-    static class CL extends URLClassLoader {
-        
-        CL() {
-            super( new URL[0], Processor.class.getClassLoader() );
-        }
-        
-        void add(URL url) {
-            URL urls[] = getURLs();
-            for ( URL u : urls ) {
-                if ( u.equals(url))
-                    return;
-            }
-            super.addURL(url);
-        }
-        
-    }
-    
-    private CL getLoader() {
-        if ( pluginLoader == null )
-            pluginLoader = new CL();
-        return pluginLoader;
-    }
-
-    public boolean exists() {
-        return base != null && base.exists();
-    }
-    
-    public boolean isOk() {
-        return isFailOk() || (getErrors().size()==0);
-    }
-    public boolean isPerfect() {
-        return getErrors().size()==0 && getWarnings().size()==0;
-    }
-}
-
-
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Resource.java b/bundleplugin/src/main/java/aQute/lib/osgi/Resource.java
deleted file mode 100644
index d619f47..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Resource.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/* 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.*;
-
-public interface Resource {
-	InputStream openInputStream() throws IOException ;
-	void write(OutputStream out) throws IOException;
-	long lastModified();
-	void setExtra(String extra);
-	String getExtra();	
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/URLResource.java b/bundleplugin/src/main/java/aQute/lib/osgi/URLResource.java
deleted file mode 100644
index f43ac91..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/URLResource.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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.net.*;
-
-public class URLResource implements Resource {
-	URL	url;
-	String	extra;
-	
-	public URLResource(URL url) {
-		this.url = url;
-	}
-
-	public InputStream openInputStream() throws IOException {
-		return url.openStream();
-	}
-
-	public String toString() {
-		return ":" + url.getPath() + ":";
-	}
-
-	public void write(OutputStream out) throws IOException {
-		FileResource.copy(this, out);
-	}
-
-	public long lastModified() {
-		return -1;
-	}
-
-	public String getExtra() {
-		return extra;
-	}
-
-	public void setExtra(String extra) {
-		this.extra = extra;
-	}
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Verifier.java b/bundleplugin/src/main/java/aQute/lib/osgi/Verifier.java
deleted file mode 100644
index a990f51..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Verifier.java
+++ /dev/null
@@ -1,687 +0,0 @@
-/* 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 aQute.libg.qtokens.*;
-
-public class Verifier extends Analyzer {
-
-    Jar                              dot;
-    Manifest                         manifest;
-    Map<String, Map<String, String>> referred              = newHashMap();
-    Map<String, Map<String, String>> contained             = newHashMap();
-    Map<String, Set<String>>         uses                  = newHashMap();
-    Map<String, Map<String, String>> mimports;
-    Map<String, Map<String, String>> mdynimports;
-    Map<String, Map<String, String>> mexports;
-    List<Jar> bundleClasspath;
-    Map<String, Map<String, String>> ignore                = newHashMap();                                                             // Packages
-    // to
-    // ignore
-
-    Map<String, Clazz>               classSpace;
-    boolean                          r3;
-    boolean                          usesRequire;
-    boolean                          fragment;
-    Attributes                       main;
-
-    final static Pattern             EENAME                = Pattern
-                                                                   .compile("CDC-1\\.0/Foundation-1\\.0"
-                                                                           + "|CDC-1\\.1/Foundation-1\\.1"
-                                                                           + "|OSGi/Minimum-1\\.[1-9]"
-                                                                           + "|JRE-1\\.1"
-                                                                           + "|J2SE-1\\.2"
-                                                                           + "|J2SE-1\\.3"
-                                                                           + "|J2SE-1\\.4"
-                                                                           + "|J2SE-1\\.5"
-                                                                           + "|JavaSE-1\\.6"
-                                                                           + "|PersonalJava-1\\.1"
-                                                                           + "|PersonalJava-1\\.2"
-                                                                           + "|CDC-1\\.0/PersonalBasis-1\\.0"
-                                                                           + "|CDC-1\\.0/PersonalJava-1\\.0");
-
-    final static Pattern             BUNDLEMANIFESTVERSION = Pattern
-                                                                   .compile("2");
-    public final static String       SYMBOLICNAME_STRING   = "[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)*";
-    public final static Pattern      SYMBOLICNAME          = Pattern
-                                                                   .compile(SYMBOLICNAME_STRING);
-
-    public final static String       VERSION_STRING        = "[0-9]+(\\.[0-9]+(\\.[0-9]+(\\.[0-9A-Za-z_-]+)?)?)?";
-    public final static Pattern      VERSION               = Pattern
-                                                                   .compile(VERSION_STRING);
-    final static Pattern             FILTEROP              = Pattern
-                                                                   .compile("=|<=|>=|~=");
-    final static Pattern             VERSIONRANGE          = Pattern
-                                                                   .compile("((\\(|\\[)"
-                                                                           + VERSION_STRING
-                                                                           + ","
-                                                                           + VERSION_STRING
-                                                                           + "(\\]|\\)))|"
-                                                                           + VERSION_STRING);
-    final static Pattern             FILE                  = Pattern
-                                                                   .compile("/?[^/\"\n\r\u0000]+(/[^/\"\n\r\u0000]+)*");
-    final static Pattern             WILDCARDPACKAGE       = Pattern
-                                                                   .compile("((\\p{Alnum}|_)+(\\.(\\p{Alnum}|_)+)*(\\.\\*)?)|\\*");
-    final static Pattern             ISO639                = Pattern
-                                                                   .compile("[A-Z][A-Z]");
-    public static Pattern            HEADER_PATTERN        = Pattern
-                                                                   .compile("[A-Za-z0-9][-a-zA-Z0-9_]+");
-    public static Pattern            TOKEN                 = Pattern
-                                                                   .compile("[-a-zA-Z0-9_]+");
-
-    Properties                       properties;
-
-    public Verifier(Jar jar) throws Exception {
-        this(jar, null);
-    }
-
-    public Verifier(Jar jar, Properties properties) throws Exception {
-        this.dot = jar;
-        this.properties = properties;
-        this.manifest = jar.getManifest();
-        if (manifest == null) {
-            manifest = new Manifest();
-            error("This file contains no manifest and is therefore not a bundle");
-        }
-        main = this.manifest.getMainAttributes();
-        verifyHeaders(main);
-        r3 = getHeader(Analyzer.BUNDLE_MANIFESTVERSION) == null;
-        usesRequire = getHeader(Analyzer.REQUIRE_BUNDLE) != null;
-        fragment = getHeader(Analyzer.FRAGMENT_HOST) != null;
-
-        bundleClasspath = getBundleClassPath();
-        mimports = parseHeader(manifest.getMainAttributes().getValue(
-                Analyzer.IMPORT_PACKAGE));
-        mdynimports = parseHeader(manifest.getMainAttributes().getValue(
-                Analyzer.DYNAMICIMPORT_PACKAGE));
-        mexports = parseHeader(manifest.getMainAttributes().getValue(
-                Analyzer.EXPORT_PACKAGE));
-
-        ignore = parseHeader(manifest.getMainAttributes().getValue(
-                Analyzer.IGNORE_PACKAGE));
-    }
-
-    public Verifier() {
-        // TODO Auto-generated constructor stub
-    }
-
-    private void verifyHeaders(Attributes main) {
-        for (Object element : main.keySet()) {
-            Attributes.Name header = (Attributes.Name) element;
-            String h = header.toString();
-            if (!HEADER_PATTERN.matcher(h).matches())
-                error("Invalid Manifest header: " + h + ", pattern="
-                        + HEADER_PATTERN);
-        }
-    }
-
-    private List<Jar> getBundleClassPath() {
-        List<Jar> list = newList();
-        String bcp = getHeader(Analyzer.BUNDLE_CLASSPATH);
-        if (bcp == null) {
-            list.add(dot);
-        } else {
-            Map<String,Map<String,String>> entries = parseHeader(bcp);
-            for (String jarOrDir : entries.keySet()) {
-                if (jarOrDir.equals(".")) {
-                    list.add(dot);
-                } else {
-                    if (jarOrDir.equals("/"))
-                        jarOrDir = "";
-                    if (jarOrDir.endsWith("/")) {
-                        error("Bundle-Classpath directory must not end with a slash: "
-                                + jarOrDir);
-                        jarOrDir = jarOrDir.substring(0, jarOrDir.length() - 1);
-                    }
-
-                    Resource resource = dot.getResource(jarOrDir);
-                    if (resource != null) {
-                        try {
-                            Jar sub = new Jar(jarOrDir);
-                            addClose(sub);
-                            EmbeddedResource.build(sub, resource);
-                            if (!jarOrDir.endsWith(".jar"))
-                                warning("Valid JAR file on Bundle-Classpath does not have .jar extension: "
-                                        + jarOrDir);
-                            list.add(sub);
-                        } catch (Exception e) {
-                            error("Invalid embedded JAR file on Bundle-Classpath: "
-                                    + jarOrDir + ", " + e);
-                        }
-                    } else if (dot.getDirectories().containsKey(jarOrDir)) {
-                        if (r3)
-                            error("R3 bundles do not support directories on the Bundle-ClassPath: "
-                                    + jarOrDir);
-
-                        try {
-                            Jar sub = new Jar(jarOrDir);
-                            addClose(sub);
-                            for ( Map.Entry<String, Resource> entry : dot.getResources().entrySet()) {
-                                if ( entry.getKey().startsWith(jarOrDir)) 
-                                    sub.putResource( entry.getKey().substring(jarOrDir.length()+1), entry.getValue());
-                            }
-                            list.add(sub);
-                        } catch (Exception e) {
-                            error("Invalid embedded directory file on Bundle-Classpath: "
-                                    + jarOrDir + ", " + e);
-                        }
-                    } else {
-                        error("Cannot find a file or directory for Bundle-Classpath entry: "
-                                + jarOrDir);
-                    }
-                }
-            }
-        }
-        return list;
-    }
-
-    /*
-     * Bundle-NativeCode ::= nativecode ( ',' nativecode )* ( ’,’ optional) ?
-     * nativecode ::= path ( ';' path )* // See 1.4.2 ( ';' parameter )+
-     * optional ::= ’*’
-     */
-    public void verifyNative() {
-        String nc = getHeader("Bundle-NativeCode");
-        doNative(nc);
-    }
-
-    public void doNative(String nc) {
-        if (nc != null) {
-            QuotedTokenizer qt = new QuotedTokenizer(nc, ",;=", false);
-            char del;
-            do {
-                do {
-                    String name = qt.nextToken();
-                    if (name == null) {
-                        error("Can not parse name from bundle native code header: "
-                                + nc);
-                        return;
-                    }
-                    del = qt.getSeparator();
-                    if (del == ';') {
-                        if (dot != null && !dot.exists(name)) {
-                            error("Native library not found in JAR: " + name);
-                        }
-                    } else {
-                        String value = null;
-                        if (del == '=')
-                            value = qt.nextToken();
-
-                        String key = name.toLowerCase();
-                        if (key.equals("osname")) {
-                            // ...
-                        } else if (key.equals("osversion")) {
-                            // verify version range
-                            verify(value, VERSIONRANGE);
-                        } else if (key.equals("language")) {
-                            verify(value, ISO639);
-                        } else if (key.equals("processor")) {
-                            // verify(value, PROCESSORS);
-                        } else if (key.equals("selection-filter")) {
-                            // verify syntax filter
-                            verifyFilter(value);
-                        } else if (name.equals("*") && value == null) {
-                            // Wildcard must be at end.
-                            if (qt.nextToken() != null)
-                                error("Bundle-Native code header may only END in wildcard: nc");
-                        } else {
-                            warning("Unknown attribute in native code: " + name
-                                    + "=" + value);
-                        }
-                        del = qt.getSeparator();
-                    }
-                } while (del == ';');
-            } while (del == ',');
-        }
-    }
-
-    public void verifyFilter(String value) {
-        try {
-            verifyFilter(value, 0);
-        } catch (Exception e) {
-            error("Not a valid filter: " + value + e.getMessage());
-        }
-    }
-
-    private void verifyActivator() {
-        String bactivator = getHeader("Bundle-Activator");
-        if (bactivator != null) {
-            Clazz cl = loadClass(bactivator);
-            if (cl == null) {
-                int n = bactivator.lastIndexOf('.');
-                if (n > 0) {
-                    String pack = bactivator.substring(0, n);
-                    if (mimports.containsKey(pack))
-                        return;
-                    error("Bundle-Activator not found on the bundle class path nor in imports: "
-                            + bactivator);
-                } else
-                    error("Activator uses default package and is not local (default package can not be imported): "
-                            + bactivator);
-            }
-        }
-    }
-
-    private Clazz loadClass(String className) {
-        String path = className.replace('.', '/') + ".class";
-        return (Clazz) classSpace.get(path);
-    }
-
-    private void verifyComponent() {
-        String serviceComponent = getHeader("Service-Component");
-        if (serviceComponent != null) {
-            Map<String,Map<String,String>> map = parseHeader(serviceComponent);
-            for (String component : map.keySet()) {
-                if (!dot.exists(component)) {
-                    error("Service-Component entry can not be located in JAR: "
-                            + component);
-                } else {
-                    // validate component ...
-                }
-            }
-        }
-    }
-
-    public void info() {
-        System.out.println("Refers                           : " + referred);
-        System.out.println("Contains                         : " + contained);
-        System.out.println("Manifest Imports                 : " + mimports);
-        System.out.println("Manifest Exports                 : " + mexports);
-    }
-
-    /**
-     * Invalid exports are exports mentioned in the manifest but not found on
-     * the classpath. This can be calculated with: exports - contains.
-     * 
-     * Unfortunately, we also must take duplicate names into account. These
-     * duplicates are of course no erroneous.
-     */
-    private void verifyInvalidExports() {
-        Set<String> invalidExport = newSet(mexports.keySet());
-        invalidExport.removeAll(contained.keySet());
-
-        // We might have duplicate names that are marked for it. These
-        // should not be counted. Should we test them against the contained
-        // set? Hmm. If someone wants to hang himself by using duplicates than
-        // I guess he can go ahead ... This is not a recommended practice
-        for (Iterator<String> i = invalidExport.iterator(); i.hasNext();) {
-            String pack = i.next();
-            if (isDuplicate(pack))
-                i.remove();
-        }
-
-        if (!invalidExport.isEmpty())
-            error("Exporting packages that are not on the Bundle-Classpath"
-                    + bundleClasspath + ": " + invalidExport);
-    }
-
-    /**
-     * Invalid imports are imports that we never refer to. They can be
-     * calculated by removing the refered packages from the imported packages.
-     * This leaves packages that the manifest imported but that we never use.
-     */
-    private void verifyInvalidImports() {
-        Set<String> invalidImport = newSet(mimports.keySet());
-        invalidImport.removeAll(referred.keySet());
-        // TODO Added this line but not sure why it worked before ...
-        invalidImport.removeAll(contained.keySet());
-        String bactivator = getHeader(Analyzer.BUNDLE_ACTIVATOR);
-        if (bactivator != null) {
-            int n = bactivator.lastIndexOf('.');
-            if (n > 0) {
-                invalidImport.remove(bactivator.substring(0, n));
-            }
-        }
-        if (isPedantic() && !invalidImport.isEmpty())
-            warning("Importing packages that are never refered to by any class on the Bundle-Classpath"
-                    + bundleClasspath + ": " + invalidImport);
-    }
-
-    /**
-     * Check for unresolved imports. These are referals that are not imported by
-     * the manifest and that are not part of our bundle classpath. The are
-     * calculated by removing all the imported packages and contained from the
-     * refered packages.
-     */
-    private void verifyUnresolvedReferences() {
-        Set<String> unresolvedReferences = new TreeSet<String>(referred
-                .keySet());
-        unresolvedReferences.removeAll(mimports.keySet());
-        unresolvedReferences.removeAll(contained.keySet());
-
-        // Remove any java.** packages.
-        for (Iterator<String> p = unresolvedReferences.iterator(); p.hasNext();) {
-            String pack = p.next();
-            if (pack.startsWith("java.") || ignore.containsKey(pack))
-                p.remove();
-            else {
-                // Remove any dynamic imports
-                if (isDynamicImport(pack))
-                    p.remove();
-            }
-        }
-
-        if (!unresolvedReferences.isEmpty()) {
-            // Now we want to know the
-            // classes that are the culprits
-            Set<String> culprits = new HashSet<String>();
-            for (Clazz clazz : classSpace.values()) {
-                if (hasOverlap(unresolvedReferences, clazz.imports.keySet()))
-                    culprits.add(clazz.getPath());
-            }
-
-            error("Unresolved references to " + unresolvedReferences
-                    + " by class(es) on the Bundle-Classpath" + bundleClasspath
-                    + ": " + culprits);
-        }
-    }
-
-    /**
-     * @param p
-     * @param pack
-     */
-    private boolean isDynamicImport(String pack) {
-        for (String pattern : mdynimports.keySet()) {
-            // Wildcard?
-            if (pattern.equals("*"))
-                return true; // All packages can be dynamically imported
-
-            if (pattern.endsWith(".*")) {
-                pattern = pattern.substring(0, pattern.length() - 2);
-                if (pack.startsWith(pattern)
-                        && (pack.length() == pattern.length() || pack
-                                .charAt(pattern.length()) == '.'))
-                    return true;
-            } else {
-                if (pack.equals(pattern))
-                    return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean hasOverlap(Set<?> a, Set<?> b) {
-        for (Iterator<?> i = a.iterator(); i.hasNext();) {
-            if (b.contains(i.next()))
-                return true;
-        }
-        return false;
-    }
-
-    public void verify() throws IOException {
-        if (classSpace == null)
-            classSpace = analyzeBundleClasspath(dot,
-                    parseHeader(getHeader(Analyzer.BUNDLE_CLASSPATH)),
-                    contained, referred, uses);
-        verifyManifestFirst();
-        verifyActivator();
-        verifyComponent();
-        verifyNative();
-        verifyInvalidExports();
-        verifyInvalidImports();
-        verifyUnresolvedReferences();
-        verifySymbolicName();
-        verifyListHeader("Bundle-RequiredExecutionEnvironment", EENAME, false);
-        verifyHeader("Bundle-ManifestVersion", BUNDLEMANIFESTVERSION, false);
-        verifyHeader("Bundle-Version", VERSION, true);
-        verifyListHeader("Bundle-Classpath", FILE, false);
-        verifyDynamicImportPackage();
-        verifyBundleClasspath();
-        if (usesRequire) {
-            if (!getErrors().isEmpty()) {
-                getWarnings()
-                        .add(
-                                0,
-                                "Bundle uses Require Bundle, this can generate false errors because then not enough information is available without the required bundles");
-            }
-        }
-    }
-
-    public void verifyBundleClasspath() {
-        Map<String,Map<String,String>> bcp = parseHeader(getHeader(Analyzer.BUNDLE_CLASSPATH));
-        if ( bcp.isEmpty() || bcp.containsKey("."))
-            return;
-        
-        for ( String path : dot.getResources().keySet()) {
-            if ( path.endsWith(".class")) {
-                warning("The Bundle-Classpath does not contain the actual bundle JAR (as specified with '.' in the Bundle-Classpath) but the JAR does contain classes. Is this intentional?");
-                return;
-            }
-        }
-    }
-
-    /**
-     * <pre>
-     *          DynamicImport-Package ::= dynamic-description
-     *              ( ',' dynamic-description )*
-     *              
-     *          dynamic-description::= wildcard-names ( ';' parameter )*
-     *          wildcard-names ::= wildcard-name ( ';' wildcard-name )*
-     *          wildcard-name ::= package-name 
-     *                         | ( package-name '.*' ) // See 1.4.2
-     *                         | '*'
-     * </pre>
-     */
-    private void verifyDynamicImportPackage() {
-        verifyListHeader("DynamicImport-Package", WILDCARDPACKAGE, true);
-        String dynamicImportPackage = getHeader("DynamicImport-Package");
-        if (dynamicImportPackage == null)
-            return;
-
-        Map<String, Map<String,String>> map = parseHeader(dynamicImportPackage);
-        for (String name : map.keySet()) {
-            name = name.trim();
-            if (!verify(name, WILDCARDPACKAGE))
-                error("DynamicImport-Package header contains an invalid package name: "
-                        + name);
-
-            Map<String,String> sub = map.get(name);
-            if (r3 && sub.size() != 0) {
-                error("DynamicPackage-Import has attributes on import: "
-                        + name
-                        + ". This is however, an <=R3 bundle and attributes on this header were introduced in R4. ");
-            }
-        }
-    }
-
-    private void verifyManifestFirst() {
-        if (!dot.manifestFirst) {
-            error("Invalid JAR stream: Manifest should come first to be compatible with JarInputStream, it was not");
-        }
-    }
-
-    private void verifySymbolicName() {
-        Map<String,Map<String,String>> bsn = parseHeader(getHeader(Analyzer.BUNDLE_SYMBOLICNAME));
-        if (!bsn.isEmpty()) {
-            if (bsn.size() > 1)
-                error("More than one BSN specified " + bsn);
-
-            String name = (String) bsn.keySet().iterator().next();
-            if (!SYMBOLICNAME.matcher(name).matches()) {
-                error("Symbolic Name has invalid format: " + name);
-            }
-        }
-    }
-
-    /**
-     * <pre>
-     *         filter ::= ’(’ filter-comp ’)’
-     *         filter-comp ::= and | or | not | operation
-     *         and ::= ’&amp;’ filter-list
-     *         or ::= ’|’ filter-list
-     *         not ::= ’!’ filter
-     *         filter-list ::= filter | filter filter-list
-     *         operation ::= simple | present | substring
-     *         simple ::= attr filter-type value
-     *         filter-type ::= equal | approx | greater | less
-     *         equal ::= ’=’
-     *         approx ::= ’&tilde;=’
-     *         greater ::= ’&gt;=’
-     *         less ::= ’&lt;=’
-     *         present ::= attr ’=*’
-     *         substring ::= attr ’=’ initial any final
-     *         inital ::= () | value
-     *         any ::= ’*’ star-value
-     *         star-value ::= () | value ’*’ star-value
-     *         final ::= () | value
-     *         value ::= &lt;see text&gt;
-     * </pre>
-     * 
-     * @param expr
-     * @param index
-     * @return
-     */
-
-    int verifyFilter(String expr, int index) {
-        try {
-            while (Character.isWhitespace(expr.charAt(index)))
-                index++;
-
-            if (expr.charAt(index) != '(')
-                throw new IllegalArgumentException(
-                        "Filter mismatch: expected ( at position " + index
-                                + " : " + expr);
-
-            index++;
-            while (Character.isWhitespace(expr.charAt(index)))
-                index++;
-
-            switch (expr.charAt(index)) {
-            case '!':
-            case '&':
-            case '|':
-                return verifyFilterSubExpression(expr, index) + 1;
-
-            default:
-                return verifyFilterOperation(expr, index) + 1;
-            }
-        } catch (IndexOutOfBoundsException e) {
-            throw new IllegalArgumentException(
-                    "Filter mismatch: early EOF from " + index);
-        }
-    }
-
-    private int verifyFilterOperation(String expr, int index) {
-        StringBuffer sb = new StringBuffer();
-        while ("=><~()".indexOf(expr.charAt(index)) < 0) {
-            sb.append(expr.charAt(index++));
-        }
-        String attr = sb.toString().trim();
-        if (attr.length() == 0)
-            throw new IllegalArgumentException(
-                    "Filter mismatch: attr at index " + index + " is 0");
-        sb = new StringBuffer();
-        while ("=><~".indexOf(expr.charAt(index)) >= 0) {
-            sb.append(expr.charAt(index++));
-        }
-        String operator = sb.toString();
-        if (!verify(operator, FILTEROP))
-            throw new IllegalArgumentException(
-                    "Filter error, illegal operator " + operator + " at index "
-                            + index);
-
-        sb = new StringBuffer();
-        while (")".indexOf(expr.charAt(index)) < 0) {
-            switch (expr.charAt(index)) {
-            case '\\':
-                if (expr.charAt(index + 1) == '*'
-                        || expr.charAt(index + 1) == ')')
-                    index++;
-                else
-                    throw new IllegalArgumentException(
-                            "Filter error, illegal use of backslash at index "
-                                    + index
-                                    + ". Backslash may only be used before * or (");
-            }
-            sb.append(expr.charAt(index++));
-        }
-        return index;
-    }
-
-    private int verifyFilterSubExpression(String expr, int index) {
-        do {
-            index = verifyFilter(expr, index + 1);
-            while (Character.isWhitespace(expr.charAt(index)))
-                index++;
-            if (expr.charAt(index) != ')')
-                throw new IllegalArgumentException(
-                        "Filter mismatch: expected ) at position " + index
-                                + " : " + expr);
-            index++;
-        } while (expr.charAt(index) == '(');
-        return index;
-    }
-
-    private String getHeader(String string) {
-        return main.getValue(string);
-    }
-
-    @SuppressWarnings("unchecked")
-    private boolean verifyHeader(String name, Pattern regex, boolean error) {
-        String value = manifest.getMainAttributes().getValue(name);
-        if (value == null)
-            return false;
-
-        QuotedTokenizer st = new QuotedTokenizer(value.trim(), ",");
-        for (Iterator<String> i = st.getTokenSet().iterator(); i.hasNext();) {
-            if (!verify((String) i.next(), regex)) {
-                String msg = "Invalid value for " + name + ", " + value
-                        + " does not match " + regex.pattern();
-                if (error)
-                    error(msg);
-                else
-                    warning(msg);
-            }
-        }
-        return true;
-    }
-
-    private boolean verify(String value, Pattern regex) {
-        return regex.matcher(value).matches();
-    }
-
-    private boolean verifyListHeader(String name, Pattern regex, boolean error) {
-        String value = manifest.getMainAttributes().getValue(name);
-        if (value == null)
-            return false;
-
-        Map<String,Map<String,String>> map = parseHeader(value);
-        for (String header : map.keySet()) {
-            if (!regex.matcher(header).matches()) {
-                String msg = "Invalid value for " + name + ", " + value
-                        + " does not match " + regex.pattern();
-                if (error)
-                    error(msg);
-                else
-                    warning(msg);
-            }
-        }
-        return true;
-    }
-
-    public String getProperty(String key, String deflt) {
-        if (properties == null)
-            return deflt;
-        return properties.getProperty(key, deflt);
-    }
-
-    public void setClassSpace(Map<String,Clazz> classspace,
-            Map<String, Map<String, String>> contained,
-            Map<String, Map<String, String>> referred,
-            Map<String, Set<String>> uses) {
-        this.classSpace = classspace;
-        this.contained = contained;
-        this.referred = referred;
-        this.uses = uses;
-    }
-
-    public static boolean isVersion(String version) {
-        return VERSION.matcher(version).matches();
-    }
-
-}
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/ZipResource.java b/bundleplugin/src/main/java/aQute/lib/osgi/ZipResource.java
deleted file mode 100644
index 38b744f..0000000
--- a/bundleplugin/src/main/java/aQute/lib/osgi/ZipResource.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/* 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.regex.*;
-import java.util.zip.*;
-
-public class ZipResource implements Resource {
-	ZipFile		zip;
-	ZipEntry	entry;
-	long		lastModified;
-	String		extra;
-	
-	ZipResource(ZipFile zip, ZipEntry entry, long lastModified) {
-		this.zip = zip;
-		this.entry = entry;
-		this.lastModified = lastModified;
-	}
-
-	public InputStream openInputStream() throws IOException {
-		return zip.getInputStream(entry);
-	}
-
-	public String toString() {
-		return ":" + entry.getName() + ":";
-	}
-
-	public static ZipFile build(Jar jar, File file) throws ZipException,
-			IOException {
-		return build(jar, file, null);
-	}
-
-	public static ZipFile build(Jar jar, File file, Pattern pattern)
-			throws ZipException, IOException {
-
-		try {
-			ZipFile zip = new ZipFile(file);
-			nextEntry: for (Enumeration<? extends ZipEntry> e = zip.entries(); e.hasMoreElements();) {
-				ZipEntry entry = e.nextElement();
-				if (pattern != null) {
-					Matcher m = pattern.matcher(entry.getName());
-					if (!m.matches())
-						continue nextEntry;
-				}
-				if (!entry.isDirectory()) {
-					long time = entry.getTime();
-					if ( time <= 0 )
-						time = file.lastModified();
-					jar.putResource(entry.getName(), new ZipResource(zip,
-							entry, time), true);
-				}
-			}
-			return zip;
-		} catch (FileNotFoundException e) {
-			throw new IllegalArgumentException("Problem opening JAR: "
-					+ file.getAbsolutePath());
-		}
-	}
-
-	public void write(OutputStream out) throws IOException {
-		FileResource.copy(this, out);
-	}
-
-	public long lastModified() {
-		return lastModified;
-	}
-
-	public String getExtra() {
-		return extra;
-	}
-
-	public void setExtra(String extra) {
-		this.extra = extra;
-	}
-
-}
