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