Apply patch for bugs 2030388 and 3134533: FileProtocolIteratorFactory creates File...
[scannotation] / src / main / java / org / scannotation / AnnotationDB.java
index 6eb4afe..bf27515 100644 (file)
@@ -49,6 +49,8 @@ public class AnnotationDB implements Serializable
    protected transient boolean scanParameterAnnotations = true;
    protected transient boolean scanFieldAnnotations = true;
    protected transient String[] ignoredPackages = {"javax", "java", "sun", "com.sun", "javassist"};
+   protected transient String[] scanPackages = null;
+   protected transient boolean ignoreBadURLs = false;
 
    public class CrossReferenceException extends Exception
    {
@@ -65,6 +67,22 @@ public class AnnotationDB implements Serializable
       }
    }
 
+   public String[] getScanPackages()
+   {
+      return scanPackages;
+   }
+
+   /**
+    * Set explicit packages to scan.
+    * Set to null to enable ignore list.
+    *
+    * @param scanPackages packages to scan or null
+    */
+   public void setScanPackages(String[] scanPackages)
+   {
+      this.scanPackages = scanPackages;
+   }
+
    public String[] getIgnoredPackages()
    {
       return ignoredPackages;
@@ -86,13 +104,16 @@ public class AnnotationDB implements Serializable
       int i = 0;
       for (String ign : ignoredPackages) tmp[i++] = ign;
       for (String ign : ignored) tmp[i++] = ign;
+      this.ignoredPackages = tmp;
    }
 
    /**
     * This method will cross reference annotations in the annotation index with any meta-annotations that they have
     * and create additional entries as needed.  For example:
     *
-    * @HttpMethod("GET") public @interface GET {}
+    * <pre>
+    * @ HttpMethod("GET") public @interface GET {}
+    * </pre>
     * <p/>
     * The HttpMethod index will have additional classes added to it for any classes annotated with annotations that
     * have the HttpMethod meta-annotation.
@@ -150,7 +171,6 @@ public class AnnotationDB implements Serializable
     * a class's implemented interfaces.  The cross references will be added to the annotationIndex and
     * classIndex indexes
     *
-    * @param ignoredPackages var arg list of packages to ignore
     * @throws CrossReferenceException an Exception thrown if referenced interfaces haven't been scanned
     */
    public void crossReferenceImplementedInterfaces() throws CrossReferenceException
@@ -190,6 +210,18 @@ public class AnnotationDB implements Serializable
 
    private boolean ignoreScan(String intf)
    {
+         if (scanPackages != null)
+         {
+             for (String scan : scanPackages)
+             {
+                // do not ignore if on packages to scan list
+                if (intf.startsWith(scan + "."))
+                {
+                   return false;
+                }
+             }
+          return true; // didn't match whitelist, ignore
+         }
       for (String ignored : ignoredPackages)
       {
          if (intf.startsWith(ignored + "."))
@@ -263,8 +295,18 @@ public class AnnotationDB implements Serializable
       this.scanFieldAnnotations = scanFieldAnnotations;
    }
 
-
-   /**
+    /**
+     * Whether or not you want AnnotationDB to ignore bad URLs passed to scanArchives.
+     * Default is to throw an IOException.
+     *
+     * @param ignoreBadURLs
+     */
+    public void setIgnoreBadURLs(boolean ignoreBadURLs)
+    {
+        this.ignoreBadURLs = ignoreBadURLs;
+    }
+
+    /**
     * Scan a url that represents an "archive"  this is a classpath directory or jar file
     *
     * @param urls variable list of URLs to scan as archives
@@ -280,18 +322,30 @@ public class AnnotationDB implements Serializable
             {
                if (filename.endsWith(".class"))
                {
-                  if (filename.startsWith("/")) filename = filename.substring(1);
-                  if (!ignoreScan(filename.replace('/', '.'))) return true;
+                  if (filename.startsWith("/") || filename.startsWith("\\"))
+                      filename = filename.substring(1);
+                  if (!ignoreScan(filename.replace('/', '.')))
+                      return true;
                   //System.out.println("IGNORED: " + filename);
                }
                return false;
             }
          };
 
-         StreamIterator it = IteratorFactory.create(url, filter);
-
-         InputStream stream;
-         while ((stream = it.next()) != null) scanClass(stream);
+          try
+          {
+              StreamIterator it = IteratorFactory.create(url, filter);
+
+              InputStream stream;
+              while ((stream = it.next()) != null) scanClass(stream);
+          }
+          catch (IOException e)
+          {
+              if (ignoreBadURLs)
+                  continue;
+              else
+                  throw e;
+          }
       }
 
    }
@@ -310,8 +364,8 @@ public class AnnotationDB implements Serializable
       {
          cf = new ClassFile(dstream);
          classIndex.put(cf.getName(), new HashSet<String>());
-         if (scanClassAnnotations) ;
-         scanClass(cf);
+         if (scanClassAnnotations)
+            scanClass(cf);
          if (scanMethodAnnotations || scanParameterAnnotations) scanMethods(cf);
          if (scanFieldAnnotations) scanFields(cf);