174 * @param <S>
175 * The type of the service to be loaded by this loader
176 *
177 * @author Mark Reinhold
178 * @since 1.6
179 */
180
181 public final class ServiceLoader<S>
182 implements Iterable<S>
183 {
184
185 private static final String PREFIX = "META-INF/services/";
186
187 // The class or interface representing the service being loaded
188 private Class<S> service;
189
190 // The class loader used to locate, load, and instantiate providers
191 private ClassLoader loader;
192
193 // Cached providers, in instantiation order
194 private LinkedHashMap<String,S> providers = new LinkedHashMap<String,S>();
195
196 // The current lazy-lookup iterator
197 private LazyIterator lookupIterator;
198
199 /**
200 * Clear this loader's provider cache so that all providers will be
201 * reloaded.
202 *
203 * <p> After invoking this method, subsequent invocations of the {@link
204 * #iterator() iterator} method will lazily look up and instantiate
205 * providers from scratch, just as is done by a newly-created loader.
206 *
207 * <p> This method is intended for use in situations in which new providers
208 * can be installed into a running Java virtual machine.
209 */
210 public void reload() {
211 providers.clear();
212 lookupIterator = new LazyIterator(service, loader);
213 }
214
274 // @param service
275 // The service type for which providers are being sought;
276 // used to construct error detail strings
277 //
278 // @param u
279 // The URL naming the configuration file to be parsed
280 //
281 // @return A (possibly empty) iterator that will yield the provider-class
282 // names in the given configuration file that are not yet members
283 // of the returned set
284 //
285 // @throws ServiceConfigurationError
286 // If an I/O error occurs while reading from the given URL, or
287 // if a configuration-file format error is detected
288 //
289 private Iterator<String> parse(Class service, URL u)
290 throws ServiceConfigurationError
291 {
292 InputStream in = null;
293 BufferedReader r = null;
294 ArrayList<String> names = new ArrayList<String>();
295 try {
296 in = u.openStream();
297 r = new BufferedReader(new InputStreamReader(in, "utf-8"));
298 int lc = 1;
299 while ((lc = parseLine(service, u, r, lc, names)) >= 0);
300 } catch (IOException x) {
301 fail(service, "Error reading configuration file", x);
302 } finally {
303 try {
304 if (r != null) r.close();
305 if (in != null) in.close();
306 } catch (IOException y) {
307 fail(service, "Error closing configuration file", y);
308 }
309 }
310 return names.iterator();
311 }
312
313 // Private inner class implementing fully-lazy provider lookup
314 //
446 }
447
448 /**
449 * Creates a new service loader for the given service type and class
450 * loader.
451 *
452 * @param service
453 * The interface or abstract class representing the service
454 *
455 * @param loader
456 * The class loader to be used to load provider-configuration files
457 * and provider classes, or <tt>null</tt> if the system class
458 * loader (or, failing that, the bootstrap class loader) is to be
459 * used
460 *
461 * @return A new service loader
462 */
463 public static <S> ServiceLoader<S> load(Class<S> service,
464 ClassLoader loader)
465 {
466 return new ServiceLoader<S>(service, loader);
467 }
468
469 /**
470 * Creates a new service loader for the given service type, using the
471 * current thread's {@linkplain java.lang.Thread#getContextClassLoader
472 * context class loader}.
473 *
474 * <p> An invocation of this convenience method of the form
475 *
476 * <blockquote><pre>
477 * ServiceLoader.load(<i>service</i>)</pre></blockquote>
478 *
479 * is equivalent to
480 *
481 * <blockquote><pre>
482 * ServiceLoader.load(<i>service</i>,
483 * Thread.currentThread().getContextClassLoader())</pre></blockquote>
484 *
485 * @param service
486 * The interface or abstract class representing the service
|
174 * @param <S>
175 * The type of the service to be loaded by this loader
176 *
177 * @author Mark Reinhold
178 * @since 1.6
179 */
180
181 public final class ServiceLoader<S>
182 implements Iterable<S>
183 {
184
185 private static final String PREFIX = "META-INF/services/";
186
187 // The class or interface representing the service being loaded
188 private Class<S> service;
189
190 // The class loader used to locate, load, and instantiate providers
191 private ClassLoader loader;
192
193 // Cached providers, in instantiation order
194 private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
195
196 // The current lazy-lookup iterator
197 private LazyIterator lookupIterator;
198
199 /**
200 * Clear this loader's provider cache so that all providers will be
201 * reloaded.
202 *
203 * <p> After invoking this method, subsequent invocations of the {@link
204 * #iterator() iterator} method will lazily look up and instantiate
205 * providers from scratch, just as is done by a newly-created loader.
206 *
207 * <p> This method is intended for use in situations in which new providers
208 * can be installed into a running Java virtual machine.
209 */
210 public void reload() {
211 providers.clear();
212 lookupIterator = new LazyIterator(service, loader);
213 }
214
274 // @param service
275 // The service type for which providers are being sought;
276 // used to construct error detail strings
277 //
278 // @param u
279 // The URL naming the configuration file to be parsed
280 //
281 // @return A (possibly empty) iterator that will yield the provider-class
282 // names in the given configuration file that are not yet members
283 // of the returned set
284 //
285 // @throws ServiceConfigurationError
286 // If an I/O error occurs while reading from the given URL, or
287 // if a configuration-file format error is detected
288 //
289 private Iterator<String> parse(Class service, URL u)
290 throws ServiceConfigurationError
291 {
292 InputStream in = null;
293 BufferedReader r = null;
294 ArrayList<String> names = new ArrayList<>();
295 try {
296 in = u.openStream();
297 r = new BufferedReader(new InputStreamReader(in, "utf-8"));
298 int lc = 1;
299 while ((lc = parseLine(service, u, r, lc, names)) >= 0);
300 } catch (IOException x) {
301 fail(service, "Error reading configuration file", x);
302 } finally {
303 try {
304 if (r != null) r.close();
305 if (in != null) in.close();
306 } catch (IOException y) {
307 fail(service, "Error closing configuration file", y);
308 }
309 }
310 return names.iterator();
311 }
312
313 // Private inner class implementing fully-lazy provider lookup
314 //
446 }
447
448 /**
449 * Creates a new service loader for the given service type and class
450 * loader.
451 *
452 * @param service
453 * The interface or abstract class representing the service
454 *
455 * @param loader
456 * The class loader to be used to load provider-configuration files
457 * and provider classes, or <tt>null</tt> if the system class
458 * loader (or, failing that, the bootstrap class loader) is to be
459 * used
460 *
461 * @return A new service loader
462 */
463 public static <S> ServiceLoader<S> load(Class<S> service,
464 ClassLoader loader)
465 {
466 return new ServiceLoader<>(service, loader);
467 }
468
469 /**
470 * Creates a new service loader for the given service type, using the
471 * current thread's {@linkplain java.lang.Thread#getContextClassLoader
472 * context class loader}.
473 *
474 * <p> An invocation of this convenience method of the form
475 *
476 * <blockquote><pre>
477 * ServiceLoader.load(<i>service</i>)</pre></blockquote>
478 *
479 * is equivalent to
480 *
481 * <blockquote><pre>
482 * ServiceLoader.load(<i>service</i>,
483 * Thread.currentThread().getContextClassLoader())</pre></blockquote>
484 *
485 * @param service
486 * The interface or abstract class representing the service
|