blob: b26dd7475a9c3a6e8114878c6a063b2951e5f3a5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
package lombok.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import lombok.Lombok;
public class SpiLoadUtil {
private SpiLoadUtil() {}
public static <C> Iterator<C> findServices(Class<C> target) throws IOException {
return findServices(target, Thread.currentThread().getContextClassLoader());
}
public static <C> Iterator<C> findServices(final Class<C> target, final ClassLoader loader) throws IOException {
Enumeration<URL> resources = loader.getResources("META-INF/services/" + target.getName());
final Set<String> entries = new LinkedHashSet<String>();
while ( resources.hasMoreElements() ) {
URL url = resources.nextElement();
readServicesFromUrl(entries, url);
}
final Iterator<String> names = entries.iterator();
return new Iterator<C>() {
public boolean hasNext() {
return names.hasNext();
}
public C next() {
try {
return target.cast(Class.forName(names.next(), true, loader).newInstance());
} catch ( Throwable t ) {
throw Lombok.sneakyThrow(t);
}
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
private static void readServicesFromUrl(Collection<String> list, URL url) throws IOException {
InputStream in = url.openStream();
try {
if ( in == null ) return;
BufferedReader r = new BufferedReader(new InputStreamReader(in, "UTF-8"));
while ( true ) {
String line = r.readLine();
if ( line == null ) break;
int idx = line.indexOf('#');
if ( idx != -1 ) line = line.substring(0, idx);
line = line.trim();
if ( line.length() == 0 ) continue;
list.add(line);
}
} finally {
try { in.close(); } catch ( Throwable ignore ) {}
}
}
@SuppressWarnings("unchecked")
public static Class<? extends Annotation> findAnnotationClass(Class<?> c, Class<?> base) {
if ( c == Object.class || c == null ) return null;
for ( Type iface : c.getGenericInterfaces() ) {
if ( iface instanceof ParameterizedType ) {
ParameterizedType p = (ParameterizedType)iface;
if ( !base.equals(p.getRawType()) ) continue;
Type target = p.getActualTypeArguments()[0];
if ( target instanceof Class<?> ) {
if ( Annotation.class.isAssignableFrom((Class<?>) target) ) {
return (Class<? extends Annotation>) target;
}
}
throw new ClassCastException("Not an annotation type: " + target);
}
}
Class<? extends Annotation> potential = findAnnotationClass(c.getSuperclass(), base);
if ( potential != null ) return potential;
for ( Class<?> iface : c.getInterfaces() ) {
potential = findAnnotationClass(iface, base);
if ( potential != null ) return potential;
}
return null;
}
}
|