package me.prettyprint.hom.annotations; import org.apache.xbean.finder.AnnotationFinder; import org.apache.xbean.finder.UrlSet; import org.apache.xbean.finder.archive.ClasspathArchive; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Modifier; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Scan for classes annotated with an annotation. The scan starts in the given * package root so it doesn't need to scan through the entire package structure. * * @author Todd Burruss */ public class DefaultAnnotationScanner implements AnnotationScanner { @Override public Set<Class<?>> scan(String packageRoot, Class<? extends Annotation> anno) { final ClassLoader cl = Thread.currentThread().getContextClassLoader(); UrlSet set; try { set = new UrlSet(cl); if (cl.getParent() != cl) { set = set.exclude(cl.getParent()); } set = set.excludeJavaExtDirs(); set = set.excludeJavaHome(); set = set.excludeJavaEndorsedDirs(); // exclude some well known libs to go faster in real apps set = set.exclude(".*/activation(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/activeio-core(-[\\d.]+)?(-incubator)?.jar(!/)?"); set = set.exclude(".*/activemq-(core|ra)(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/annotations-api-6.[01].[\\d.]+.jar(!/)?"); set = set.exclude(".*/asm-(all|commons|util|tree)?[\\d.]+.jar(!/)?"); set = set.exclude(".*/avalon-framework(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/axis2-jaxws-api(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/backport-util-concurrent(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/bcprov-jdk15(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/catalina(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/cglib-(nodep-)?[\\d.]+.jar(!/)?"); set = set.exclude(".*/com\\.ibm\\.ws\\.[^/]*.jar(!/)?"); set = set.exclude(".*/commons-(logging|logging-api|cli|pool|lang|collections|dbcp|dbcp-all)(-[\\d.r-]+)?.jar(!/)?"); set = set.exclude(".*/cxf-bundle(-[\\d.]+)?(incubator)?.jar(!/)?"); set = set.exclude(".*/openejb-cxf-bundle(-[\\d.]+)?(incubator)?.jar(!/)?"); set = set.exclude(".*/derby(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/ejb31-api-experimental(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/geronimo-(connector|transaction)(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/geronimo-[^/]+_spec(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/geronimo-javamail_([\\d.]+)_mail(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/hibernate-(entitymanager|annotations)?(-[\\d.]+(ga)?)?.jar(!/)?"); set = set.exclude(".*/howl(-[\\d.-]+)?.jar(!/)?"); set = set.exclude(".*/hsqldb(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/idb(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/idea_rt.jar(!/)?"); set = set.exclude(".*/javaee-api(-embedded)?-[\\d.-]+.jar(!/)?"); set = set.exclude(".*/javassist[^/]*.jar(!/)?"); set = set.exclude(".*/jaxb-(impl|api)(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/jboss-[^/]*.jar(!/)?"); set = set.exclude(".*/jbossall-[^/]*.jar(!/)?"); set = set.exclude(".*/jbosscx-[^/]*.jar(!/)?"); set = set.exclude(".*/jbossjts-?[^/]*.jar(!/)?"); set = set.exclude(".*/jbosssx-[^/]*.jar(!/)?"); set = set.exclude(".*/jmdns(-[\\d.]+)?(-RC\\d)?.jar(!/)?"); set = set.exclude(".*/juli(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/junit(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/log4j(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/logkit(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/mail(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/neethi(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/org\\.eclipse\\.persistence\\.[^/]*.jar(!/)?"); set = set.exclude(".*/org\\.junit_.[^/]*.jar(!/)?"); set = set.exclude(".*/openjpa-(jdbc|kernel|lib|persistence|persistence-jdbc)(-5)?(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/openjpa(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/opensaml(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/quartz(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/saaj-impl(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/spring(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/serp(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/servlet-api(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/slf4j-api(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/slf4j-jdk14(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/stax-api(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/swizzle-stream(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/sxc-(jaxb|runtime)(-[\\d.]+)?(-SNAPSHOT)?.jar(!/)?"); set = set.exclude(".*/wsdl4j(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/wss4j(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/wstx-asl(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/xbean-(reflect|naming|finder)-(shaded-)?[\\d.]+.jar(!/)?"); set = set.exclude(".*/xmlParserAPIs(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/xmlunit(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/xmlsec(-[\\d.]+)?.jar(!/)?"); set = set.exclude(".*/XmlSchema(-[\\d.]+)?.jar(!/)?"); } catch (IOException e) { throw new RuntimeException(e); } final ClasspathArchive archive = new ClasspathArchive(cl, set.getUrls()); final AnnotationFinder scanner = new AnnotationFinder(archive); final List<Class<?>> list = scanner.findAnnotatedClasses(anno); final Set<Class<?>> result = new HashSet<Class<?>>(); for (Class<?> clazz : list) { if (clazz.getPackage().getName().startsWith(packageRoot) && !Modifier.isAbstract(clazz.getModifiers())) { result.add(clazz); } } return result; } }