1.0.3
[scannotation] / src / main / java / org / scannotation / AnnotationDB.java
index 92e28c6..230bd6e 100644 (file)
@@ -28,11 +28,11 @@ import java.util.Set;
  * The class allows you to scan an arbitrary set of "archives" for .class files.  These class files
  * are parsed to see what annotations they use.  Two indexes are created.  The javax, java, sun, com.sun, and javassist
  * packages will not be scanned by default.
- *
+ * <p/>
  * One is a map of annotations and what classes
  * use those annotations.   This could be used, for example, by an EJB deployer to find all the EJBs contained
  * in the archive
- *
+ * <p/>
  * Another is a mpa of classes and what annotations those classes use.
  *
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -49,6 +49,7 @@ 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;
 
    public class CrossReferenceException extends Exception
    {
@@ -65,6 +66,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,22 +103,20 @@ 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 {}
-    *
+    * @HttpMethod("GET") public @interface GET {}
+    * <p/>
     * The HttpMethod index will have additional classes added to it for any classes annotated with annotations that
     * have the HttpMethod meta-annotation.
-    *
+    * <p/>
     * WARNING: If the annotation class has not already been scaned, this method will load all annotation classes indexed
-    *  as a resource so they must be in your classpath
-    *
-    *
+    * as a resource so they must be in your classpath
     */
    public void crossReferenceMetaAnnotations() throws CrossReferenceException
    {
@@ -142,7 +157,7 @@ public class AnnotationDB implements Serializable
          {
             annotationIndex.get(xref).addAll(annotationIndex.get(annotation));
          }
-         
+
       }
       if (unresolved.size() > 0) throw new CrossReferenceException(unresolved);
    }
@@ -171,12 +186,19 @@ public class AnnotationDB implements Serializable
             {
                unresolved.add(intf);
             }
-            Set<String> classAnnotations = classIndex.get(clazz);
-            classAnnotations.addAll(xrefAnnotations);
-            for (String annotation : xrefAnnotations)
+            else
             {
-               Set<String> classes = annotationIndex.get(annotation);
-               classes.add(clazz);
+               Set<String> classAnnotations = classIndex.get(clazz);
+               if (classAnnotations == null)
+               {
+                  classIndex.put(clazz, xrefAnnotations);
+               }
+               else classAnnotations.addAll(xrefAnnotations);
+               for (String annotation : xrefAnnotations)
+               {
+                  Set<String> classes = annotationIndex.get(annotation);
+                  classes.add(clazz);
+               }
             }
          }
       }
@@ -186,11 +208,23 @@ 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 + "."))
          {
-            return  true;
+            return true;
          }
          else
          {
@@ -203,7 +237,6 @@ public class AnnotationDB implements Serializable
    /**
     * returns a map keyed by the fully qualified string name of a annotation class.  The Set returne is
     * a list of classes that use that annotation somehow.
-    *
     */
    public Map<String, Set<String>> getAnnotationIndex()
    {
@@ -213,7 +246,6 @@ public class AnnotationDB implements Serializable
    /**
     * returns a map keyed by the list of classes scanned.  The value set returned is a list of annotations
     * used by that class.
-    *
     */
    public Map<String, Set<String>> getClassIndex()
    {
@@ -262,7 +294,6 @@ public class AnnotationDB implements Serializable
    }
 
 
-
    /**
     * Scan a url that represents an "archive"  this is a classpath directory or jar file
     *
@@ -279,8 +310,10 @@ 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;
@@ -309,8 +342,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);