// Path: hawtio-util/src/main/java/io/hawt/util/Predicate.java
// public interface Predicate<T> {
//     boolean evaluate(T value);
// }
// 
// Path: hawtio-util/src/main/java/io/hawt/util/introspect/ClassLoaderProvider.java
// public interface ClassLoaderProvider {
// 
//     /**
//      * Returns the ClassLoader or null if one is not available
//      */
//     ClassLoader getClassLoader();
// }


import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.WeakHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import io.hawt.util.Predicate;
import io.hawt.util.ReflectionHelper;
import io.hawt.util.Strings;
import io.hawt.util.introspect.ClassLoaderProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
        final Class<? extends Annotation> annotationClass = optionallyFindAnnotationClass(annotationClassName);
        if (annotationClass != null && dir.exists()) {
            addClassNamesInDirectoryWithMethodsAnnotatedWith(answer, dir, annotationClass, "");
        }
        return answer;
    }

    protected void addClassNamesInDirectoryWithMethodsAnnotatedWith(SortedSet<String> answer, File dir,
                                                                    Class<? extends Annotation> annotationClass, String packageName) {
        File[] files = dir.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    addClassNamesInDirectoryWithMethodsAnnotatedWith(answer, file, annotationClass, packageName + file.getName() + ".");
                } else if (file.isFile()) {
                    String name = file.getName();
                    if (name.endsWith(".class")) {
                        String className = packageName + (name.substring(0, name.length() - 6).replace('$', '.'));
                        Class<?> aClass = optionallyFindClass(className);
                        if (aClass != null && ReflectionHelper.hasMethodWithAnnotation(aClass, annotationClass, true)) {
                            answer.add(className);
                        }
                    }
                }
            }
        }
    }


    protected Class<? extends Annotation> optionallyFindAnnotationClass(String annotationClassName) {
// Path: hawtio-util/src/main/java/io/hawt/util/Predicate.java
// public interface Predicate<T> {
//     boolean evaluate(T value);
// }
// 
// Path: hawtio-util/src/main/java/io/hawt/util/introspect/ClassLoaderProvider.java
// public interface ClassLoaderProvider {
// 
//     /**
//      * Returns the ClassLoader or null if one is not available
//      */
//     ClassLoader getClassLoader();
// }


// Path: hawtio-util/src/main/java/io/hawt/util/introspect/support/ClassScanner.java
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.WeakHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import io.hawt.util.Predicate;
import io.hawt.util.ReflectionHelper;
import io.hawt.util.Strings;
import io.hawt.util.introspect.ClassLoaderProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

        final Class<? extends Annotation> annotationClass = optionallyFindAnnotationClass(annotationClassName);
        if (annotationClass != null && dir.exists()) {
            addClassNamesInDirectoryWithMethodsAnnotatedWith(answer, dir, annotationClass, "");
        }
        return answer;
    }

    protected void addClassNamesInDirectoryWithMethodsAnnotatedWith(SortedSet<String> answer, File dir,
                                                                    Class<? extends Annotation> annotationClass, String packageName) {
        File[] files = dir.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    addClassNamesInDirectoryWithMethodsAnnotatedWith(answer, file, annotationClass, packageName + file.getName() + ".");
                } else if (file.isFile()) {
                    String name = file.getName();
                    if (name.endsWith(".class")) {
                        String className = packageName + (name.substring(0, name.length() - 6).replace('$', '.'));
                        Class<?> aClass = optionallyFindClass(className);
                        if (aClass != null && ReflectionHelper.hasMethodWithAnnotation(aClass, annotationClass, true)) {
                            answer.add(className);
                        }
                    }
                }
            }
        }
    }


    protected Class<? extends Annotation> optionallyFindAnnotationClass(String annotationClassName) {
        final Class<? extends Annotation> annotationClass = optionallyFindClass(annotationClassName).asSubclass(Annotation.class);