Added ability to implicitly cast instances from the Loader.
[jglob.git] / src / dolda / jglob / Loader.java
CommitLineData
01e70f63
FT
1package dolda.jglob;
2
3import java.util.*;
4import java.io.*;
5import java.net.*;
6import java.lang.annotation.*;
7
8public class Loader {
9 private final Class<? extends Annotation> an;
10 private final ClassLoader cl;
01e70f63
FT
11
12 private Loader(Class<? extends Annotation> annotation, ClassLoader loader) {
13 this.an = annotation;
14 this.cl = loader;
15 }
16
17 public Iterable<String> names() {
18 return(new Iterable<String>() {
19 public Iterator<String> iterator() {
20 return(new Iterator<String>() {
21 private Enumeration<URL> rls;
22 private Iterator<String> cur = null;
23
24 private Iterator<String> parse(URL url) {
25 try {
26 List<String> buf = new LinkedList<String>();
27 InputStream in = url.openStream();
28 try {
29 BufferedReader r = new BufferedReader(new InputStreamReader(in, "utf-8"));
30 String ln;
31 while((ln = r.readLine()) != null) {
32 ln = ln.trim();
33 if(ln.length() < 1)
34 continue;
35 buf.add(ln);
36 }
37 return(buf.iterator());
38 } finally {
39 in.close();
40 }
41 } catch(IOException e) {
42 throw(new GlobAccessException(e));
43 }
44 }
45
46 public boolean hasNext() {
47 if((cur == null) || !cur.hasNext()) {
48 if(rls == null) {
49 try {
50 rls = cl.getResources("META-INF/glob/" + an.getName());
51 } catch(IOException e) {
52 throw(new GlobAccessException(e));
53 }
54 }
55 if(!rls.hasMoreElements())
56 return(false);
57 URL u = rls.nextElement();
58 cur = parse(u);
59 }
60 return(true);
61 }
62
63 public String next() {
64 if(!hasNext())
65 throw(new NoSuchElementException());
66 String ret = cur.next();
67 return(ret);
68 }
69
70 public void remove() {throw(new UnsupportedOperationException());}
71 });
72 }
73 });
74 }
75
76 public Iterable<Class<?>> classes() {
77 return(new Iterable<Class<?>>() {
78 public Iterator<Class<?>> iterator() {
79 return(new Iterator<Class<?>>() {
80 private final Iterator<String> names = names().iterator();
81 private Class<?> n = null;
82
83 public boolean hasNext() {
84 while(n == null) {
85 if(!names.hasNext())
86 return(false);
87 String nm = names.next();
88 Class<?> c;
89 try {
90 c = cl.loadClass(nm);
91 } catch(ClassNotFoundException e) {
92 continue;
93 }
94 if(c.getAnnotation(an) == null)
95 continue;
96 n = c;
97 }
98 return(true);
99 }
100
101 public Class<?> next() {
102 if(!hasNext())
103 throw(new NoSuchElementException());
104 Class<?> r = n;
105 n = null;
106 return(r);
107 }
108
109 public void remove() {throw(new UnsupportedOperationException());}
110 });
111 }
112 });
113 }
114
70e5fe9d
FT
115 public <T> Iterable<T> instances(final Class<T> cast) {
116 return(new Iterable<T>() {
117 public Iterator<T> iterator() {
118 return(new Iterator<T>() {
01e70f63 119 private final Iterator<Class<?>> classes = classes().iterator();
70e5fe9d 120 private T n = null;
01e70f63
FT
121
122 public boolean hasNext() {
123 while(n == null) {
124 if(!classes.hasNext())
125 return(false);
126 Class<?> cl = classes.next();
70e5fe9d 127 T inst;
01e70f63 128 try {
70e5fe9d 129 inst = cast.cast(cl.newInstance());
01e70f63
FT
130 } catch(InstantiationException e) {
131 throw(new GlobInstantiationException(e));
132 } catch(IllegalAccessException e) {
133 throw(new GlobInstantiationException(e));
134 }
135 n = inst;
136 }
137 return(true);
138 }
139
70e5fe9d 140 public T next() {
01e70f63
FT
141 if(!hasNext())
142 throw(new NoSuchElementException());
70e5fe9d 143 T r = n;
01e70f63
FT
144 n = null;
145 return(r);
146 }
147
148 public void remove() {throw(new UnsupportedOperationException());}
149 });
150 }
151 });
152 }
153
70e5fe9d
FT
154 public Iterable<?> instances() {
155 return(instances(Object.class));
156 }
157
01e70f63
FT
158 public static Loader get(Class<? extends Annotation> annotation, ClassLoader loader) {
159 return(new Loader(annotation, loader));
160 }
161
162 public static Loader get(Class<? extends Annotation> annotation) {
163 return(get(annotation, annotation.getClassLoader()));
164 }
165}