Author: sebb Date: Wed Sep 16 00:38:43 2009 New Revision: 815579 URL: http://svn.apache.org/viewvc?rev=815579&view=rev Log: Add findAnnotatedClasses method (part of Bugzilla 47803)
Modified: jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/reflect/ClassFinder.java Modified: jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/reflect/ClassFinder.java URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/reflect/ClassFinder.java?rev=815579&r1=815578&r2=815579&view=diff ============================================================================== --- jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/reflect/ClassFinder.java (original) +++ jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/reflect/ClassFinder.java Wed Sep 16 00:38:43 2009 @@ -21,6 +21,8 @@ import java.io.File; import java.io.FilenameFilter; import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Enumeration; @@ -108,6 +110,40 @@ return false; } } + + private static class AnnoFilterTreeSet extends TreeSet<String>{ + private final boolean inner; // are inner classes OK? + + private final Class<? extends Annotation>[] annotations; // annotation classes to check + private final transient ClassLoader contextClassLoader + = Thread.currentThread().getContextClassLoader(); // Potentially expensive; do it once + AnnoFilterTreeSet(Class<? extends Annotation> []annotations, boolean inner){ + super(); + this.annotations = annotations; + this.inner=inner; + } + /** + * Override the superclass so we only add classnames that + * meet the criteria. + * + * @param s - classname (must be a String) + * @return true if it is a new entry + * + * @see java.util.TreeSet#add(java.lang.Object) + */ + @Override + public boolean add(String s){ + if (contains(s)) { + return false;// No need to check it again + } + if ((s.indexOf("$") == -1) || inner) { // $NON-NLS-1$ + if (hasAnnotationOnMethod(annotations,s, contextClassLoader)) { + return super.add(s); + } + } + return false; + } + } /** * Convenience method for @@ -173,10 +209,42 @@ final Class<?>[] superClasses, final boolean innerClasses, String contains, String notContains) throws IOException { - + return findClassesThatExtend(strPathsOrJars, superClasses, innerClasses, contains, notContains, false); + } + + /** + * Find classes in the provided path(s)/jar(s) that extend the class(es). + * @param strPathsOrJars - pathnames or jarfiles to search for classes + * @param annotations - required annotations + * @param innerClasses - should we include inner classes? + * + * @return List containing discovered classes + */ + public static List<String> findAnnotatedClasses(String[] strPathsOrJars, + final Class<? extends Annotation>[] annotations, final boolean innerClasses) + throws IOException { + return findClassesThatExtend(strPathsOrJars, annotations, innerClasses, null, null, true); + } + + /** + * Find classes in the provided path(s)/jar(s) that extend the class(es). + * @param strPathsOrJars - pathnames or jarfiles to search for classes + * @param classNames - required parent class(es) or annotations + * @param innerClasses - should we include inner classes? + * @param contains - classname should contain this string + * @param notContains - classname should not contain this string + * @param annotations - true if classnames are annotations + * + * @return List containing discovered classes + */ + @SuppressWarnings("unchecked") + public static List<String> findClassesThatExtend(String[] strPathsOrJars, + final Class<?>[] classNames, final boolean innerClasses, + String contains, String notContains, boolean annotations) + throws IOException { if (log.isDebugEnabled()) { - for (int i = 0; i < superClasses.length ; i++){ - log.debug("superclass: "+superClasses[i].getName()); + for (int i = 0; i < classNames.length ; i++){ + log.debug("superclass: "+classNames[i].getName()); } } @@ -198,7 +266,11 @@ } } - Set<String> listClasses = new FilterTreeSet(superClasses, innerClasses, contains, notContains); + Set<String> listClasses = + annotations ? + new AnnoFilterTreeSet((Class<? extends Annotation>[]) classNames, innerClasses) + : + new FilterTreeSet(classNames, innerClasses, contains, notContains); // first get all the classes findClassesInPaths(listPaths, listClasses); if (log.isDebugEnabled()) { @@ -384,11 +456,29 @@ } } } - } catch (Throwable ignored) { + } catch (ClassNotFoundException ignored) { log.debug(ignored.getLocalizedMessage()); } return false; } + + private static boolean hasAnnotationOnMethod(Class<? extends Annotation>[] annotations, String classInQuestion, + ClassLoader contextClassLoader ){ + try{ + Class<?> c = Class.forName(classInQuestion, false, contextClassLoader); + for(Method method : c.getMethods()) { + for(int i = 0;i<annotations.length;i++) { + Class<? extends Annotation> annotation = annotations[i]; + if(method.isAnnotationPresent(annotation)) { + return true; + } + } + } + } catch (ClassNotFoundException ignored) { + log.debug(ignored.getLocalizedMessage()); + } + return false; + } /* --------------------------------------------------------------------- To unsubscribe, e-mail: jmeter-dev-unsubscr...@jakarta.apache.org For additional commands, e-mail: jmeter-dev-h...@jakarta.apache.org