1 package jp.liq.container.reflect;
2
3 import java.io.IOException;
4 import java.lang.annotation.Annotation;
5 import java.net.URL;
6 import java.util.Enumeration;
7 import java.util.HashSet;
8 import java.util.Iterator;
9 import java.util.Set;
10
11 import jp.liq.container.util.AbstractFinder;
12 import jp.liq.container.util.Matcher;
13
14 public class ClassDiscoverer {
15 private Set<Class<?>> classes;
16
17 public ClassDiscoverer() {
18 classes = new HashSet<Class<?>>();
19 }
20
21 public void addClassList(String path) {
22 ClassLoader loader = Thread.currentThread().getContextClassLoader();
23 try {
24 Enumeration<URL> resources = loader.getResources(path);
25 URL u = null;
26 while(resources.hasMoreElements()) {
27 u = resources.nextElement();
28 for(Class<?> type : new ClassListLoader(u, loader)) {
29 classes.add(type);
30 }
31 }
32 } catch (IOException e) {
33 throw new ReflectException(e);
34 }
35 }
36
37 public ClassFinder classes() {
38 return new ClassFinder();
39 }
40
41 private class AnnotationMatcher implements Matcher<Class<?>> {
42 private final Class<? extends Annotation> annotationClass;
43 AnnotationMatcher(Class<? extends Annotation> annotationClass) {
44 this.annotationClass = annotationClass;
45 }
46
47 public boolean matches(Class<?> candidate) {
48 return candidate.isAnnotationPresent(annotationClass);
49 }
50
51 }
52
53 private class SubClassMatcher implements Matcher<Class<?>> {
54 private final Class<?> baseClass;
55 SubClassMatcher(Class<?> baseClass) {
56 this.baseClass = baseClass;
57 }
58
59 public boolean matches(Class<?> candidate) {
60 return baseClass.isAssignableFrom(candidate);
61 }
62
63 }
64
65 public class ClassFinder extends AbstractFinder<Class<?>, ClassFinder> {
66
67 @Override
68 protected Iterator<Class<?>> getCandidates() {
69 return classes.iterator();
70 }
71
72 @Override
73 protected ClassFinder getThis() {
74 return this;
75 }
76
77 public ClassFinder withAnnotation(Class<? extends Annotation> annotationClass) {
78 addMatcher(new AnnotationMatcher(annotationClass));
79 return this;
80 }
81
82 public ClassFinder isA(Class<?> baseClass) {
83 addMatcher(new SubClassMatcher(baseClass));
84 return this;
85 }
86 }
87 }