Source code: javax/ide/spi/LookupProvider.java
1 package javax.ide.spi;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.InputStreamReader;
7
8 import java.net.URL;
9
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.Enumeration;
13 import java.util.Iterator;
14
15
16 /**
17 * Provides facilities for looking up implementation classes.
18 */
19 public final class LookupProvider
20 {
21 private LookupProvider() {}
22
23 /**
24 * Look up and create the an implementation of a specified
25 * class.<p>
26 *
27 * The implementation class is stored on a jar in the classpath in the
28 * META-INF/services/some.class.Name file. This file contains the fully
29 * qualified name of the implementation class of some.class.Name.<p>
30 *
31 * If there are multiple META-INF/services/some.class.Name files on the
32 * classpath, the <b>last</b> one wins. This is intentionally different
33 * from the normal classpath precendence order so that it is possible to
34 * override a more general implementation (e.g. a JSR-198 default
35 * implementation of some service) with a specific one (e.g. an IDE
36 * specific service).
37 *
38 * @param loader the class loader to look up implementations on.
39 * @param clazz the class to look up an implementation of.
40 * @return the first available implementation of the specified class on the
41 * classpath.
42 *
43 * @throws ProviderNotFoundException if no implementation for the specified
44 * class could be loaded.
45 */
46 public static Object lookup( ClassLoader loader, Class clazz )
47 throws ProviderNotFoundException
48 {
49 Collection impls = lookupAll( loader, clazz );
50 if ( impls.isEmpty() )
51 {
52 throw new ProviderNotFoundException( "No provider for " + clazz );
53 }
54 for ( Iterator i = impls.iterator(); i.hasNext(); )
55 {
56 Object o = i.next();
57 if ( !i.hasNext() )
58 {
59 return o;
60 }
61 }
62 throw new IllegalStateException();
63 }
64
65 /**
66 * Look up and create all available implementations of a specified class.<p>
67 *
68 * The implementation class is stored on a jar in the classpath in the
69 * META-INF/services/some.class.Name file. This file contains the fully
70 * qualified name of the implementation class of some.class.Name.
71 *
72 * @param loader the class loader to look up implementations on.
73 * @param clazz the class to look up an implementation of.
74 * @return all available implementations of the specified class on the
75 * classpath.
76 *
77 * @throws ProviderNotFoundException if no implementation for the specified
78 * class could be loaded.
79 */
80 public static Collection lookupAll( ClassLoader loader, Class clazz )
81 throws ProviderNotFoundException
82 {
83 Enumeration en;
84 try
85 {
86 en = loader.getResources( "META-INF/services/" + clazz.getName() );
87 }
88 catch ( IOException ioe )
89 {
90 throw new ProviderNotFoundException( clazz.getName(), ioe );
91 }
92
93 Collection results = new ArrayList();
94
95 while ( en.hasMoreElements() )
96 {
97 URL url = (URL) en.nextElement();
98 try
99 {
100 InputStream is = url.openStream();
101 try
102 {
103 BufferedReader reader = new BufferedReader(
104 new InputStreamReader( is, "UTF-8" ) );
105 while ( true )
106 {
107 String line = reader.readLine();
108 if ( line == null )
109 {
110 break;
111 }
112 line = line.trim();
113 if ( line.length() == 0 ) continue;
114 if ( line.charAt( 0 ) == '#' ) continue;
115
116 try
117 {
118 Class inst = Class.forName( line, false, loader );
119
120 if ( !clazz.isAssignableFrom( inst ) )
121 {
122 throw new ProviderNotFoundException(
123 inst + " is not correct type for service " + clazz );
124 }
125 results.add( inst.newInstance() );
126 }
127 catch ( Exception e )
128 {
129 throw new ProviderNotFoundException( "Failed to create service class "+line,
130 e );
131 }
132
133 }
134 }
135 finally
136 {
137 is.close();
138 }
139 }
140 catch ( IOException ioe )
141 {
142 throw new ProviderNotFoundException( "Failed to load service class "+clazz, ioe );
143 }
144
145 }
146 return results;
147 }
148
149
150 }