X-Git-Url: https://juplo.de/gitweb/?p=scannotation;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Forg%2Fscannotation%2FAnnotationDB.java;h=92e28c68a8bfdb42c576965859f34f9004f4401f;hp=2c062f29190be5dd0bc589deaf90902306f06fcc;hb=6f8bc0038ccf20fceaf363d36c22b731e0a998e3;hpb=868064416c672c93f8b0a1b5d7b6a170d2b0e7f3 diff --git a/src/main/java/org/scannotation/AnnotationDB.java b/src/main/java/org/scannotation/AnnotationDB.java index 2c062f2..92e28c6 100644 --- a/src/main/java/org/scannotation/AnnotationDB.java +++ b/src/main/java/org/scannotation/AnnotationDB.java @@ -26,7 +26,8 @@ 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. + * 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. * * 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 @@ -47,22 +48,105 @@ public class AnnotationDB implements Serializable protected transient boolean scanMethodAnnotations = true; protected transient boolean scanParameterAnnotations = true; protected transient boolean scanFieldAnnotations = true; + protected transient String[] ignoredPackages = {"javax", "java", "sun", "com.sun", "javassist"}; - public class CrossReferenceException extends RuntimeException + public class CrossReferenceException extends Exception { - private Map> unresolved; + private Set unresolved; - public CrossReferenceException(Map> unresolved) + public CrossReferenceException(Set unresolved) { this.unresolved = unresolved; } - public Map> getUnresolved() + public Set getUnresolved() { return unresolved; } } + public String[] getIgnoredPackages() + { + return ignoredPackages; + } + + /** + * Override/overwrite any ignored packages + * + * @param ignoredPackages cannot be null + */ + public void setIgnoredPackages(String[] ignoredPackages) + { + this.ignoredPackages = ignoredPackages; + } + + public void addIgnoredPackages(String... ignored) + { + String[] tmp = new String[ignoredPackages.length + ignored.length]; + int i = 0; + for (String ign : ignoredPackages) tmp[i++] = ign; + for (String ign : ignored) tmp[i++] = ign; + } + + /** + * 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 {} + * + * The HttpMethod index will have additional classes added to it for any classes annotated with annotations that + * have the HttpMethod meta-annotation. + * + * 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 + * + * + */ + public void crossReferenceMetaAnnotations() throws CrossReferenceException + { + Set unresolved = new HashSet(); + + Set index = new HashSet(); + index.addAll(annotationIndex.keySet()); + + for (String annotation : index) + { + if (ignoreScan(annotation)) + { + continue; + } + if (classIndex.containsKey(annotation)) + { + for (String xref : classIndex.get(annotation)) + { + annotationIndex.get(xref).addAll(annotationIndex.get(annotation)); + } + continue; + } + InputStream bits = Thread.currentThread().getContextClassLoader().getResourceAsStream(annotation.replace('.', '/') + ".class"); + if (bits == null) + { + unresolved.add(annotation); + continue; + } + try + { + scanClass(bits); + } + catch (IOException e) + { + unresolved.add(annotation); + } + for (String xref : classIndex.get(annotation)) + { + annotationIndex.get(xref).addAll(annotationIndex.get(annotation)); + } + + } + if (unresolved.size() > 0) throw new CrossReferenceException(unresolved); + } + /** * Sometimes you want to see if a particular class implements an interface with certain annotations * After you have loaded all your classpaths with the scanArchive() method, call this method to cross reference @@ -70,34 +154,22 @@ public class AnnotationDB implements Serializable * classIndex indexes * * @param ignoredPackages var arg list of packages to ignore - * @throws CrossReferenceException a RuntimeException thrown if referenced interfaces haven't been scanned + * @throws CrossReferenceException an Exception thrown if referenced interfaces haven't been scanned */ - public void crossReferenceImplementedInterfaces(String... ignoredPackages) throws CrossReferenceException + public void crossReferenceImplementedInterfaces() throws CrossReferenceException { - Map> unresolved = new HashMap>(); + Set unresolved = new HashSet(); for (String clazz : implementsIndex.keySet()) { Set intfs = implementsIndex.get(clazz); for (String intf : intfs) { - if (intf.startsWith("java.") || intf.startsWith("javax.")) continue; - boolean ignoreInterface = false; - for (String ignored : ignoredPackages) - { - if (intf.startsWith(ignored + ".")) - { - ignoreInterface = true; - break; - } - } - if (ignoreInterface) continue; + if (ignoreScan(intf)) continue; - Set unresolvedInterfaces = new HashSet(); Set xrefAnnotations = classIndex.get(intf); if (xrefAnnotations == null) { - unresolvedInterfaces.add(intf); - unresolved.put(clazz, unresolvedInterfaces); + unresolved.add(intf); } Set classAnnotations = classIndex.get(clazz); classAnnotations.addAll(xrefAnnotations); @@ -108,9 +180,26 @@ public class AnnotationDB implements Serializable } } } + if (unresolved.size() > 0) throw new CrossReferenceException(unresolved); } + private boolean ignoreScan(String intf) + { + for (String ignored : ignoredPackages) + { + if (intf.startsWith(ignored + ".")) + { + return true; + } + else + { + //System.out.println("NOT IGNORING: " + intf); + } + } + return false; + } + /** * 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. @@ -173,6 +262,7 @@ public class AnnotationDB implements Serializable } + /** * Scan a url that represents an "archive" this is a classpath directory or jar file * @@ -187,7 +277,13 @@ public class AnnotationDB implements Serializable { public boolean accepts(String filename) { - return filename.endsWith(".class"); + if (filename.endsWith(".class")) + { + if (filename.startsWith("/")) filename = filename.substring(1); + if (!ignoreScan(filename.replace('/', '.'))) return true; + //System.out.println("IGNORED: " + filename); + } + return false; } }; @@ -299,9 +395,9 @@ public class AnnotationDB implements Serializable if (visible != null) populate(visible.getAnnotations(), cf.getName()); if (invisible != null) populate(invisible.getAnnotations(), cf.getName()); - } + } protected void populate(Annotation[] annotations, String className)