FELIX-899: update to latest editions of Bnd and Bindex

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@738785 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Analyzer.java b/bundleplugin/src/main/java/aQute/lib/osgi/Analyzer.java
index 5d6f0f7..85712b2 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Analyzer.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Analyzer.java
@@ -164,7 +164,7 @@
             }
 
             exports = merge("export-package", exportInstructions, contained,
-                    superfluous.keySet(), null);
+                    superfluous.keySet());
 
             for (Iterator<Map.Entry<String, Map<String, String>>> i = superfluous
                     .entrySet().iterator(); i.hasNext();) {
@@ -196,7 +196,7 @@
             // merge the info for matching packages
             Set<String> extra = new TreeSet<String>(importInstructions.keySet());
             imports = merge("import-package", importInstructions,
-                    referredAndExported, extra, ignored);
+                    referredAndExported, extra);
 
             // Instructions that have not been used could be superfluous
             // or if they do not contain wildcards, should be added
@@ -354,6 +354,11 @@
                     || 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);
@@ -621,13 +626,13 @@
         if (bndInfo == null) {
             bndInfo = new Properties();
             try {
-                InputStream in = Analyzer.class.getResourceAsStream("bnd.info");
+                InputStream in = getClass().getResourceAsStream("bnd.info");
                 if (in != null) {
                     bndInfo.load(in);
                     in.close();
                 }
             } catch (IOException ioe) {
-                warning("Could not read bnd.info in " + Analyzer.class.getPackage()
+                warning("Could not read bnd.info in " + getClass().getPackage()
                         + ioe);
             }
         }
@@ -1580,7 +1585,7 @@
                     }
                 } else {
                     if (dot.getDirectories().containsKey(path)) {
-                        analyzeJar(dot, path + '/', classSpace, contained, referred,
+                        analyzeJar(dot, path, classSpace, contained, referred,
                                 uses);
                     } else {
                         warning("No sub JAR or directory " + path);
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java b/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
index 41e387b..393e7ee 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Builder.java
@@ -266,7 +266,7 @@
             // Private-Package
             Map<String, Map<String, String>> filtered = merge(
                     CONDITIONAL_PACKAGE, conditionals, imports,
-                    new HashSet<String>(), null);
+                    new HashSet<String>());
 
             // Imports can also specify a private import. These
             // packages must also be copied to the bundle
@@ -647,10 +647,13 @@
      */
     private void doIncludeResources(Jar jar) throws Exception {
         String includes = getProperty("Bundle-Includes");
-        if (includes == null)
-            includes = getProperty("Include-Resource");
+        if (includes == null) {
+            includes = getProperty(INCLUDERESOURCE);
+            if ( includes == null )
+                includes = getProperty("Include-Resource");
+        }
         else
-            warning("Please use Include-Resource instead of Bundle-Includes");
+            warning("Please use -includeresource instead of Bundle-Includes");
 
         if (includes == null)
             return;
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/ClassDataCollector.java b/bundleplugin/src/main/java/aQute/lib/osgi/ClassDataCollector.java
new file mode 100644
index 0000000..e09e00f
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/ClassDataCollector.java
@@ -0,0 +1,11 @@
+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
index f383915..ce709df 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Clazz.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Clazz.java
@@ -59,6 +59,37 @@
     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;
@@ -72,6 +103,7 @@
     }
 
     Set<String> parseClassFile(DataInputStream in) throws IOException {
+
         xref = new HashSet<String>();
         classes = new HashSet<Integer>();
         descriptors = new HashSet<Integer>();
@@ -143,100 +175,111 @@
          * Falkenberg
          */
 
-        /* int access_flags = */in.readUnsignedShort(); // access
+        int access_flags = in.readUnsignedShort(); // access
         int this_class = in.readUnsignedShort();
-        int super_class = in.readUnsignedShort();
-        zuper = (String) pool[intPool[super_class]];
-        if (zuper != null) {
-            addReference(zuper);
-        }
         className = (String) pool[intPool[this_class]];
+        cd.classBegin(access_flags, className);
 
-        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()]];
-        }
-        
-        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();
+        try {
 
-            // 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;
+            int super_class = in.readUnsignedShort();
+            zuper = (String) pool[intPool[super_class]];
+            if (zuper != null) {
+                addReference(zuper);
+                cd.extendsClass(zuper);
             }
 
-            descriptors.add(new Integer(descriptor_index));
+            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();
         }
-
-        //
-        // 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));
-            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;
     }
 
     protected void pool(Object[] pool, int[] intPool) {
@@ -365,6 +408,7 @@
         if (next != null) {
             String normalized = normalize(next);
             if (normalized != null) {
+                cd.addReference(next);
                 String pack = getPackage(normalized);
                 packageReference(pack);
             }
@@ -601,23 +645,32 @@
             imports.put(pack, new LinkedHashMap<String, String>());
     }
 
-    void parseDescriptor(String prototype) {
-        addReference(prototype);
-        StringTokenizer st = new StringTokenizer(prototype, "(;)", true);
-        while (st.hasMoreTokens()) {
-            if (st.nextToken().equals("(")) {
-                String token = st.nextToken();
-                while (!token.equals(")")) {
-                    addReference(token);
-                    token = st.nextToken();
-                }
-                token = st.nextToken();
-                addReference(token);
+    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);
 
@@ -697,45 +750,45 @@
         descriptors = null;
     }
 
-    public boolean is(QUERY query, Instruction instr, Map<String, Clazz> classspace) {
+    public boolean is(QUERY query, Instruction instr,
+            Map<String, Clazz> classspace) {
         switch (query) {
         case ANY:
             return true;
 
         case NAMED:
-            if ( instr.matches(getClassName()))
+            if (instr.matches(getClassName()))
                 return !instr.isNegated();
             return false;
-            
+
         case VERSION:
             String v = major + "/" + minor;
-            if ( instr.matches(v))
+            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]))
+            for (int i = 0; interfaces != null && i < interfaces.length; i++) {
+                if (instr.matches(interfaces[i]))
                     return !instr.isNegated();
             }
             break;
         case EXTENDS:
-            if ( zuper == null )
+            if (zuper == null)
                 return false;
-            
-            if ( instr.matches(zuper))
+
+            if (instr.matches(zuper))
                 return !instr.isNegated();
             break;
-            
+
         case IMPORTS:
-            for ( String imp : imports.keySet() ) {
-                if ( instr.matches(imp.replace('.', '/')))
-                    return !instr.isNegated();                    
+            for (String imp : imports.keySet()) {
+                if (instr.matches(imp.replace('.', '/')))
+                    return !instr.isNegated();
             }
         }
-        
-        if ( zuper == null || classspace == null)
+
+        if (zuper == null || classspace == null)
             return false;
 
         Clazz clazz = classspace.get(zuper);
@@ -752,4 +805,8 @@
     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
index 7ec0a94..9535bac 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java
@@ -4,38 +4,38 @@
 import java.util.regex.*;
 
 public interface Constants {
-    public final static String   BUNDLE_CLASSPATH                    = "Bundle-ClassPath";
-    public final static String   BUNDLE_COPYRIGHT                    = "Bundle-Copyright";
-    public final static String   BUNDLE_DESCRIPTION                  = "Bundle-Description";
-    public final static String   BUNDLE_NAME                         = "Bundle-Name";
-    public final static String   BUNDLE_NATIVECODE                   = "Bundle-NativeCode";
-    public final static String   EXPORT_PACKAGE                      = "Export-Package";
-    public final static String   EXPORT_SERVICE                      = "Export-Service";
-    public final static String   IMPORT_PACKAGE                      = "Import-Package";
-    public final static String   DYNAMICIMPORT_PACKAGE               = "DynamicImport-Package";
-    public final static String   IMPORT_SERVICE                      = "Import-Service";
-    public final static String   BUNDLE_VENDOR                       = "Bundle-Vendor";
-    public final static String   BUNDLE_VERSION                      = "Bundle-Version";
-    public final static String   BUNDLE_DOCURL                       = "Bundle-DocURL";
-    public final static String   BUNDLE_CONTACTADDRESS               = "Bundle-ContactAddress";
-    public final static String   BUNDLE_ACTIVATOR                    = "Bundle-Activator";
-    public final static String   BUNDLE_REQUIREDEXECUTIONENVIRONMENT = "Bundle-RequiredExecutionEnvironment";
-    public final static String   BUNDLE_SYMBOLICNAME                 = "Bundle-SymbolicName";
-    public final static String   BUNDLE_LOCALIZATION                 = "Bundle-Localization";
-    public final static String   REQUIRE_BUNDLE                      = "Require-Bundle";
-    public final static String   FRAGMENT_HOST                       = "Fragment-Host";
-    public final static String   BUNDLE_MANIFESTVERSION              = "Bundle-ManifestVersion";
-    public final static String   SERVICE_COMPONENT                   = "Service-Component";
-    public final static String   BUNDLE_LICENSE                      = "Bundle-License";
-    public static final String   PRIVATE_PACKAGE                     = "Private-Package";
-    public static final String   IGNORE_PACKAGE                      = "Ignore-Package";
-    public static final String   INCLUDE_RESOURCE                    = "Include-Resource";
-    public static final String   CONDITIONAL_PACKAGE                 = "Conditional-Package";
-    public static final String   BND_LASTMODIFIED                    = "Bnd-LastModified";
-    public static final String   CREATED_BY                          = "Created-By";
-    public static final String   TOOL                                = "Tool";
+    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";
 
-    public final static String   headers[]                           = {
+    String               headers[]                           = {
             BUNDLE_ACTIVATOR, BUNDLE_CONTACTADDRESS, BUNDLE_COPYRIGHT,
             BUNDLE_DESCRIPTION, BUNDLE_DOCURL, BUNDLE_LOCALIZATION,
             BUNDLE_NATIVECODE, BUNDLE_VENDOR, BUNDLE_VERSION, BUNDLE_LICENSE,
@@ -45,113 +45,116 @@
             BUNDLE_REQUIREDEXECUTIONENVIRONMENT, BUNDLE_SYMBOLICNAME,
             BUNDLE_VERSION, FRAGMENT_HOST, PRIVATE_PACKAGE, IGNORE_PACKAGE,
             INCLUDE_RESOURCE, REQUIRE_BUNDLE, IMPORT_SERVICE, EXPORT_SERVICE,
-            CONDITIONAL_PACKAGE, BND_LASTMODIFIED                   };
+            CONDITIONAL_PACKAGE, BND_LASTMODIFIED           };
 
-    public static final String   BUILDPATH                           = "-buildpath";
-    public static final String   CONDUIT                             = "-conduit";
-    public static final String   CLASSPATH                           = "-classpath";
-    public static final String   DEPENDSON                           = "-dependson";
-    public static final String   DONOTCOPY                           = "-donotcopy";
-    public static final String   EXPORT_CONTENTS                     = "-exportcontents";
-    public static final String   FAIL_OK                             = "-failok";
-    public static final String   INCLUDE                             = "-include";
-    public static final String   MAKE                                = "-make";
-    public static final String   MANIFEST                            = "-manifest";
-    public static final String   NOEXTRAHEADERS                      = "-noextraheaders";
-    public static final String   NOUSES                              = "-nouses";
-    public static final String   NOPE                                = "-nope";
-    public static final String   PEDANTIC                            = "-pedantic";
-    public static final String   PLUGIN                              = "-plugin";
-    public static final String   POM                                 = "-pom";
-    public static final String   REMOVE_HEADERS                      = "-removeheaders";
-    public static final String   RESOURCEONLY                        = "-resourceonly";
-    public static final String   SOURCES                             = "-sources";
-    public static final String   SOURCEPATH                          = "-sourcepath";
-    public static final String   SUB                                 = "-sub";
-    public static final String   RUNPROPERTIES                       = "-runproperties";
-    public static final String   RUNSYSTEMPACKAGES                   = "-runsystempackages";
-    public static final String   RUNBUNDLES                          = "-runbundles";
-    public static final String   RUNPATH                             = "-runpath";
-    public static final String   RUNVM                               = "-runvm";
+    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";
 
-    public static final String   REPORTNEWER                         = "-reportnewer";
-    public static final String   TESTPACKAGES                        = "-testpackages";
-    public static final String   TESTREPORT                          = "-testreport";
-    public static final String   UNDERTEST                           = "-undertest";
-    public static final String   VERBOSE                             = "-verbose";
-    public static final String   VERSIONPOLICY                       = "-versionpolicy";
-    public static final String   SIGN                                = "-sign";
+    String               REPORTNEWER                         = "-reportnewer";
+    String               SIGN                                = "-sign";
+    String               TESTPACKAGES                        = "-testpackages";
+    String               TESTREPORT                          = "-testreport";
+    String               UNDERTEST                           = "-undertest";
+    String               VERBOSE                             = "-verbose";
+    String               VERSIONPOLICY                       = "-versionpolicy";
 
-    public static final String   options[]                           = {
-            BUILDPATH, CONDUIT, CLASSPATH, DEPENDSON, DONOTCOPY,
-            EXPORT_CONTENTS, FAIL_OK, INCLUDE, MAKE, MANIFEST, NOEXTRAHEADERS,
+    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                       };
+            TESTPACKAGES, TESTREPORT, VERBOSE               };
 
-    public static final char     DUPLICATE_MARKER                    = '~';
+    char                 DUPLICATE_MARKER                    = '~';
 
-    public static final String   SPLIT_PACKAGE_DIRECTIVE             = "-split-package:";
-    public static final String   IMPORT_DIRECTIVE                    = "-import:";
-    public static final String   NO_IMPORT_DIRECTIVE                 = "-noimport:";
-    public static final String   REMOVE_ATTRIBUTE_DIRECTIVE          = "-remove-attribute:";
-    public static final String   USES_DIRECTIVE                      = "uses:";
-    public static final String   PRESENCE_DIRECTIVE                  = "presence:";
+    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:";
 
-    public static final String   KEYSTORE_LOCATION_DIRECTIVE         = "keystore:";
-    public static final String   KEYSTORE_PROVIDER_DIRECTIVE         = "provider:";
-    public static final String   KEYSTORE_PASSWORD_DIRECTIVE         = "password:";
-    public static final String   SIGN_PASSWORD_DIRECTIVE             = "sign-password:";
+    String               KEYSTORE_LOCATION_DIRECTIVE         = "keystore:";
+    String               KEYSTORE_PROVIDER_DIRECTIVE         = "provider:";
+    String               KEYSTORE_PASSWORD_DIRECTIVE         = "password:";
+    String               SIGN_PASSWORD_DIRECTIVE             = "sign-password:";
 
-    public static final String   directives[]                        = {
+    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
-                                                                     };
+                                                             // TODO
+                                                             };
 
-    public static final String   USES_USES                           = "<<USES>>";
-    public static final String   CURRENT_USES                        = "@uses";
-    public static final String   IMPORT_REFERENCE                    = "reference";
-    public static final String   IMPORT_PRIVATE                      = "private";
-    public static final String[] importDirectives                    = {
-            IMPORT_REFERENCE, IMPORT_PRIVATE                        };
+    String               USES_USES                           = "<<USES>>";
+    String               CURRENT_USES                        = "@uses";
+    String               IMPORT_REFERENCE                    = "reference";
+    String               IMPORT_PRIVATE                      = "private";
+    String[]             importDirectives                    = {
+            IMPORT_REFERENCE, IMPORT_PRIVATE                };
 
-    public static final String   COMPONENT_FACTORY                   = "factory:";
-    public static final String   COMPONENT_SERVICEFACTORY            = "servicefactory:";
-    public static final String   COMPONENT_IMMEDIATE                 = "immediate:";
-    public static final String   COMPONENT_ENABLED                   = "enabled:";
-    public static final String   COMPONENT_DYNAMIC                   = "dynamic:";
-    public static final String   COMPONENT_MULTIPLE                  = "multiple:";
-    public static final String   COMPONENT_PROVIDE                   = "provide:";
-    public static final String   COMPONENT_OPTIONAL                  = "optional:";
-    public static final String   COMPONENT_PROPERTIES                = "properties:";
-    public static final String   COMPONENT_IMPLEMENTATION            = "implementation:";
-    public static final String[] componentDirectives                 = new String[] {
+    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 };
+            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 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)");
+    static final Pattern VALID_PROPERTY_TYPES                = Pattern
+                                                                     .compile("(String|Long|Double|Float|Integer|Byte|Character|Boolean|Short)");
 
-    public final static String   DEFAULT_BND_EXTENSION               = ".bnd";
-    public final static String   DEFAULT_JAR_EXTENSION               = ".jar";
-    public final static String   DEFAULT_BAR_EXTENSION               = ".bar";
-    String[]                     METAPACKAGES                        = {
-            "META-INF", "OSGI-INF", "OSGI-OPT"                      };
+    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;
+    int                  STRATEGY_HIGHEST                    = 1;
+    int                  STRATEGY_LOWEST                     = -1;
 
-    final static String          CURRENT_VERSION                     = "@";
-    final static String          CURRENT_PACKAGE                     = "@package";
+    String               CURRENT_VERSION                     = "@";
+    String               CURRENT_PACKAGE                     = "@package";
 }
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java b/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java
index 6510f63..22748ae 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java
@@ -9,6 +9,7 @@
 import java.util.*;
 import java.util.regex.*;
 
+import aQute.libg.sed.*;
 import aQute.libg.version.*;
 
 /**
@@ -19,7 +20,7 @@
  * depth but may not contain loops.
  * 
  */
-public class Macro {
+public class Macro implements Replacer {
     Properties properties;
     Processor  domain;
     Object     targets[];
@@ -29,6 +30,11 @@
         this.properties = properties;
         this.domain = domain;
         this.targets = targets;
+        if (targets != null) {
+            for (Object o : targets) {
+                assert o != null;
+            }
+        }
     }
 
     public Macro(Processor processor) {
@@ -169,7 +175,8 @@
 
     private String doCommand(Object target, String method, String[] args) {
         if (target == null)
-            System.out.println("Huh? Target should never be null " + domain);
+            ; // System.out.println("Huh? Target should never be null " +
+                // domain);
         else {
             String cname = "_" + method.replaceAll("-", "_");
             try {
@@ -382,6 +389,10 @@
                 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, "
@@ -698,13 +709,13 @@
             InputStream in = new FileInputStream(f);
             return getString(in);
         } else if (f.isDirectory()) {
-            return Arrays.toString( f.list());
+            return Arrays.toString(f.list());
         } else {
             try {
                 URL url = new URL(args[1]);
                 InputStream in = url.openStream();
                 return getString(in);
-            } catch( MalformedURLException mfue ) {
+            } catch (MalformedURLException mfue) {
                 // Ignore here
             }
             return null;
@@ -809,7 +820,7 @@
             for (Enumeration<?> e = properties.propertyNames(); e
                     .hasMoreElements();) {
                 String key = (String) e.nextElement();
-                if ( ! key.startsWith("_"))
+                if (!key.startsWith("_"))
                     flattened.put(key, process(properties.getProperty(key)));
             }
             return flattened;
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Processor.java b/bundleplugin/src/main/java/aQute/lib/osgi/Processor.java
index c2dc276..548495c 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Processor.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Processor.java
@@ -221,7 +221,10 @@
      * 
      * @return
      */
-    public List<Object> getPlugins() {
+    protected List<Object> getPlugins() {
+        if ( parent != null )
+            return parent.getPlugins();
+            
         if (this.plugins != null)
             return this.plugins;
 
@@ -493,10 +496,13 @@
         // + 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;
@@ -505,7 +511,6 @@
     }
 
     public void propertiesChanged() {
-        plugins = null;
     }
 
     /**
@@ -528,7 +533,13 @@
         try {
             if (propertiesFile.isFile()) {
                 // System.out.println("Loading properties " + propertiesFile);
-                modified = propertiesFile.lastModified();
+                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);
@@ -653,9 +664,8 @@
 
     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>> actual, Set<String> superfluous) {
+        Map<String, Map<String, String>> ignored = newMap();
         Map<String, Map<String, String>> toVisit = new HashMap<String, Map<String, String>>(
                 actual); // we do not want to ruin our
         // original
@@ -696,7 +706,7 @@
                         newAttributes.putAll(actual.get(packageName));
                         newAttributes.putAll(instructedAttributes);
                         result.put(packageName, newAttributes);
-                    } else if (ignored != null) {
+                    } else {
                         ignored.put(packageName, new HashMap<String, String>());
                     }
                     p.remove(); // Can never match again for another pattern
diff --git a/bundleplugin/src/main/java/aQute/lib/osgi/Verifier.java b/bundleplugin/src/main/java/aQute/lib/osgi/Verifier.java
index 73d14c3..a990f51 100644
--- a/bundleplugin/src/main/java/aQute/lib/osgi/Verifier.java
+++ b/bundleplugin/src/main/java/aQute/lib/osgi/Verifier.java
@@ -33,12 +33,13 @@
     final static Pattern             EENAME                = Pattern
                                                                    .compile("CDC-1\\.0/Foundation-1\\.0"
                                                                            + "|CDC-1\\.1/Foundation-1\\.1"
-                                                                           + "|OSGi/Minimum-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"
@@ -160,8 +161,10 @@
                         try {
                             Jar sub = new Jar(jarOrDir);
                             addClose(sub);
-                            // TODO verify if directory exists and see how to 
-                            // get it in a JAR ...
+                            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: "
@@ -428,6 +431,7 @@
         verifyHeader("Bundle-Version", VERSION, true);
         verifyListHeader("Bundle-Classpath", FILE, false);
         verifyDynamicImportPackage();
+        verifyBundleClasspath();
         if (usesRequire) {
             if (!getErrors().isEmpty()) {
                 getWarnings()
@@ -438,6 +442,19 @@
         }
     }
 
+    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
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
index 4eb239e..64f3af5 100644
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
+++ b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
@@ -1,5 +1,5 @@
 /*
- * $Id: BundleInfo.java 94 2008-12-03 13:31:50Z peter.kriens@aqute.biz $
+ * $Id: BundleInfo.java 95 2009-01-19 13:21:52Z peter.kriens@aqute.biz $
  * 
  * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
  * 
@@ -28,7 +28,7 @@
  * Convert a bundle to a generic resource description and store its local
  * dependencies (like for example a license file in the JAR) in a zip file.
  * 
- * @version $Revision: 94 $
+ * @version $Revision: 95 $
  */
 public class BundleInfo {
 	Manifest manifest;
@@ -402,7 +402,7 @@
 				else {
 					filter.append("(!(version");
 					filter.append(">=");
-					filter.append(version.low);
+					filter.append(version.high);
 					filter.append("))");
 				}
 			} else {