View Javadoc
1   /*
2    * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package java.util;
27  
28  import java.io.BufferedReader;
29  import java.io.IOException;
30  import java.io.InputStream;
31  import java.io.InputStreamReader;
32  import java.net.URL;
33  import java.security.AccessController;
34  import java.security.AccessControlContext;
35  import java.security.PrivilegedAction;
36  import java.util.ArrayList;
37  import java.util.Enumeration;
38  import java.util.Iterator;
39  import java.util.List;
40  import java.util.NoSuchElementException;
41  
42  
43  /**
44   * A simple service-provider loading facility.
45   *
46   * <p> A <i>service</i> is a well-known set of interfaces and (usually
47   * abstract) classes.  A <i>service provider</i> is a specific implementation
48   * of a service.  The classes in a provider typically implement the interfaces
49   * and subclass the classes defined in the service itself.  Service providers
50   * can be installed in an implementation of the Java platform in the form of
51   * extensions, that is, jar files placed into any of the usual extension
52   * directories.  Providers can also be made available by adding them to the
53   * application's class path or by some other platform-specific means.
54   *
55   * <p> For the purpose of loading, a service is represented by a single type,
56   * that is, a single interface or abstract class.  (A concrete class can be
57   * used, but this is not recommended.)  A provider of a given service contains
58   * one or more concrete classes that extend this <i>service type</i> with data
59   * and code specific to the provider.  The <i>provider class</i> is typically
60   * not the entire provider itself but rather a proxy which contains enough
61   * information to decide whether the provider is able to satisfy a particular
62   * request together with code that can create the actual provider on demand.
63   * The details of provider classes tend to be highly service-specific; no
64   * single class or interface could possibly unify them, so no such type is
65   * defined here.  The only requirement enforced by this facility is that
66   * provider classes must have a zero-argument constructor so that they can be
67   * instantiated during loading.
68   *
69   * <p><a name="format"> A service provider is identified by placing a
70   * <i>provider-configuration file</i> in the resource directory
71   * <tt>META-INF/services</tt>.</a>  The file's name is the fully-qualified <a
72   * href="../lang/ClassLoader.html#name">binary name</a> of the service's type.
73   * The file contains a list of fully-qualified binary names of concrete
74   * provider classes, one per line.  Space and tab characters surrounding each
75   * name, as well as blank lines, are ignored.  The comment character is
76   * <tt>'#'</tt> (<tt>'&#92;u0023'</tt>,
77   * <font style="font-size:smaller;">NUMBER SIGN</font>); on
78   * each line all characters following the first comment character are ignored.
79   * The file must be encoded in UTF-8.
80   *
81   * <p> If a particular concrete provider class is named in more than one
82   * configuration file, or is named in the same configuration file more than
83   * once, then the duplicates are ignored.  The configuration file naming a
84   * particular provider need not be in the same jar file or other distribution
85   * unit as the provider itself.  The provider must be accessible from the same
86   * class loader that was initially queried to locate the configuration file;
87   * note that this is not necessarily the class loader from which the file was
88   * actually loaded.
89   *
90   * <p> Providers are located and instantiated lazily, that is, on demand.  A
91   * service loader maintains a cache of the providers that have been loaded so
92   * far.  Each invocation of the {@link #iterator iterator} method returns an
93   * iterator that first yields all of the elements of the cache, in
94   * instantiation order, and then lazily locates and instantiates any remaining
95   * providers, adding each one to the cache in turn.  The cache can be cleared
96   * via the {@link #reload reload} method.
97   *
98   * <p> Service loaders always execute in the security context of the caller.
99   * Trusted system code should typically invoke the methods in this class, and
100  * the methods of the iterators which they return, from within a privileged
101  * security context.
102  *
103  * <p> Instances of this class are not safe for use by multiple concurrent
104  * threads.
105  *
106  * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
107  * method in this class will cause a {@link NullPointerException} to be thrown.
108  *
109  *
110  * <p><span style="font-weight: bold; padding-right: 1em">Example</span>
111  * Suppose we have a service type <tt>com.example.CodecSet</tt> which is
112  * intended to represent sets of encoder/decoder pairs for some protocol.  In
113  * this case it is an abstract class with two abstract methods:
114  *
115  * <blockquote><pre>
116  * public abstract Encoder getEncoder(String encodingName);
117  * public abstract Decoder getDecoder(String encodingName);</pre></blockquote>
118  *
119  * Each method returns an appropriate object or <tt>null</tt> if the provider
120  * does not support the given encoding.  Typical providers support more than
121  * one encoding.
122  *
123  * <p> If <tt>com.example.impl.StandardCodecs</tt> is an implementation of the
124  * <tt>CodecSet</tt> service then its jar file also contains a file named
125  *
126  * <blockquote><pre>
127  * META-INF/services/com.example.CodecSet</pre></blockquote>
128  *
129  * <p> This file contains the single line:
130  *
131  * <blockquote><pre>
132  * com.example.impl.StandardCodecs    # Standard codecs</pre></blockquote>
133  *
134  * <p> The <tt>CodecSet</tt> class creates and saves a single service instance
135  * at initialization:
136  *
137  * <blockquote><pre>
138  * private static ServiceLoader&lt;CodecSet&gt; codecSetLoader
139  *     = ServiceLoader.load(CodecSet.class);</pre></blockquote>
140  *
141  * <p> To locate an encoder for a given encoding name it defines a static
142  * factory method which iterates through the known and available providers,
143  * returning only when it has located a suitable encoder or has run out of
144  * providers.
145  *
146  * <blockquote><pre>
147  * public static Encoder getEncoder(String encodingName) {
148  *     for (CodecSet cp : codecSetLoader) {
149  *         Encoder enc = cp.getEncoder(encodingName);
150  *         if (enc != null)
151  *             return enc;
152  *     }
153  *     return null;
154  * }</pre></blockquote>
155  *
156  * <p> A <tt>getDecoder</tt> method is defined similarly.
157  *
158  *
159  * <p><span style="font-weight: bold; padding-right: 1em">Usage Note</span> If
160  * the class path of a class loader that is used for provider loading includes
161  * remote network URLs then those URLs will be dereferenced in the process of
162  * searching for provider-configuration files.
163  *
164  * <p> This activity is normal, although it may cause puzzling entries to be
165  * created in web-server logs.  If a web server is not configured correctly,
166  * however, then this activity may cause the provider-loading algorithm to fail
167  * spuriously.
168  *
169  * <p> A web server should return an HTTP 404 (Not Found) response when a
170  * requested resource does not exist.  Sometimes, however, web servers are
171  * erroneously configured to return an HTTP 200 (OK) response along with a
172  * helpful HTML error page in such cases.  This will cause a {@link
173  * ServiceConfigurationError} to be thrown when this class attempts to parse
174  * the HTML page as a provider-configuration file.  The best solution to this
175  * problem is to fix the misconfigured web server to return the correct
176  * response code (HTTP 404) along with the HTML error page.
177  *
178  * @param  <S>
179  *         The type of the service to be loaded by this loader
180  *
181  * @author Mark Reinhold
182  * @since 1.6
183  */
184 
185 public final class ServiceLoader<S>
186     implements Iterable<S>
187 {
188 
189     private static final String PREFIX = "META-INF/services/";
190 
191     // The class or interface representing the service being loaded
192     private final Class<S> service;
193 
194     // The class loader used to locate, load, and instantiate providers
195     private final ClassLoader loader;
196 
197     // The access control context taken when the ServiceLoader is created
198     private final AccessControlContext acc;
199 
200     // Cached providers, in instantiation order
201     private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
202 
203     // The current lazy-lookup iterator
204     private LazyIterator lookupIterator;
205 
206     /**
207      * Clear this loader's provider cache so that all providers will be
208      * reloaded.
209      *
210      * <p> After invoking this method, subsequent invocations of the {@link
211      * #iterator() iterator} method will lazily look up and instantiate
212      * providers from scratch, just as is done by a newly-created loader.
213      *
214      * <p> This method is intended for use in situations in which new providers
215      * can be installed into a running Java virtual machine.
216      */
217     public void reload() {
218         providers.clear();
219         lookupIterator = new LazyIterator(service, loader);
220     }
221 
222     private ServiceLoader(Class<S> svc, ClassLoader cl) {
223         service = Objects.requireNonNull(svc, "Service interface cannot be null");
224         loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
225         acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
226         reload();
227     }
228 
229     private static void fail(Class<?> service, String msg, Throwable cause)
230         throws ServiceConfigurationError
231     {
232         throw new ServiceConfigurationError(service.getName() + ": " + msg,
233                                             cause);
234     }
235 
236     private static void fail(Class<?> service, String msg)
237         throws ServiceConfigurationError
238     {
239         throw new ServiceConfigurationError(service.getName() + ": " + msg);
240     }
241 
242     private static void fail(Class<?> service, URL u, int line, String msg)
243         throws ServiceConfigurationError
244     {
245         fail(service, u + ":" + line + ": " + msg);
246     }
247 
248     // Parse a single line from the given configuration file, adding the name
249     // on the line to the names list.
250     //
251     private int parseLine(Class<?> service, URL u, BufferedReader r, int lc,
252                           List<String> names)
253         throws IOException, ServiceConfigurationError
254     {
255         String ln = r.readLine();
256         if (ln == null) {
257             return -1;
258         }
259         int ci = ln.indexOf('#');
260         if (ci >= 0) ln = ln.substring(0, ci);
261         ln = ln.trim();
262         int n = ln.length();
263         if (n != 0) {
264             if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
265                 fail(service, u, lc, "Illegal configuration-file syntax");
266             int cp = ln.codePointAt(0);
267             if (!Character.isJavaIdentifierStart(cp))
268                 fail(service, u, lc, "Illegal provider-class name: " + ln);
269             for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
270                 cp = ln.codePointAt(i);
271                 if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
272                     fail(service, u, lc, "Illegal provider-class name: " + ln);
273             }
274             if (!providers.containsKey(ln) && !names.contains(ln))
275                 names.add(ln);
276         }
277         return lc + 1;
278     }
279 
280     // Parse the content of the given URL as a provider-configuration file.
281     //
282     // @param  service
283     //         The service type for which providers are being sought;
284     //         used to construct error detail strings
285     //
286     // @param  u
287     //         The URL naming the configuration file to be parsed
288     //
289     // @return A (possibly empty) iterator that will yield the provider-class
290     //         names in the given configuration file that are not yet members
291     //         of the returned set
292     //
293     // @throws ServiceConfigurationError
294     //         If an I/O error occurs while reading from the given URL, or
295     //         if a configuration-file format error is detected
296     //
297     private Iterator<String> parse(Class<?> service, URL u)
298         throws ServiceConfigurationError
299     {
300         InputStream in = null;
301         BufferedReader r = null;
302         ArrayList<String> names = new ArrayList<>();
303         try {
304             in = u.openStream();
305             r = new BufferedReader(new InputStreamReader(in, "utf-8"));
306             int lc = 1;
307             while ((lc = parseLine(service, u, r, lc, names)) >= 0);
308         } catch (IOException x) {
309             fail(service, "Error reading configuration file", x);
310         } finally {
311             try {
312                 if (r != null) r.close();
313                 if (in != null) in.close();
314             } catch (IOException y) {
315                 fail(service, "Error closing configuration file", y);
316             }
317         }
318         return names.iterator();
319     }
320 
321     // Private inner class implementing fully-lazy provider lookup
322     //
323     private class LazyIterator
324         implements Iterator<S>
325     {
326 
327         Class<S> service;
328         ClassLoader loader;
329         Enumeration<URL> configs = null;
330         Iterator<String> pending = null;
331         String nextName = null;
332 
333         private LazyIterator(Class<S> service, ClassLoader loader) {
334             this.service = service;
335             this.loader = loader;
336         }
337 
338         private boolean hasNextService() {
339             if (nextName != null) {
340                 return true;
341             }
342             if (configs == null) {
343                 try {
344                     String fullName = PREFIX + service.getName();
345                     if (loader == null)
346                         configs = ClassLoader.getSystemResources(fullName);
347                     else
348                         configs = loader.getResources(fullName);
349                 } catch (IOException x) {
350                     fail(service, "Error locating configuration files", x);
351                 }
352             }
353             while ((pending == null) || !pending.hasNext()) {
354                 if (!configs.hasMoreElements()) {
355                     return false;
356                 }
357                 pending = parse(service, configs.nextElement());
358             }
359             nextName = pending.next();
360             return true;
361         }
362 
363         private S nextService() {
364             if (!hasNextService())
365                 throw new NoSuchElementException();
366             String cn = nextName;
367             nextName = null;
368             Class<?> c = null;
369             try {
370                 c = Class.forName(cn, false, loader);
371             } catch (ClassNotFoundException x) {
372                 fail(service,
373                      "Provider " + cn + " not found");
374             }
375             if (!service.isAssignableFrom(c)) {
376                 fail(service,
377                      "Provider " + cn  + " not a subtype");
378             }
379             try {
380                 S p = service.cast(c.newInstance());
381                 providers.put(cn, p);
382                 return p;
383             } catch (Throwable x) {
384                 fail(service,
385                      "Provider " + cn + " could not be instantiated: " + x,
386                      x);
387             }
388             throw new Error();          // This cannot happen
389         }
390 
391         public boolean hasNext() {
392             if (acc == null) {
393                 return hasNextService();
394             } else {
395                 PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {
396                     public Boolean run() { return hasNextService(); }
397                 };
398                 return AccessController.doPrivileged(action, acc);
399             }
400         }
401 
402         public S next() {
403             if (acc == null) {
404                 return nextService();
405             } else {
406                 PrivilegedAction<S> action = new PrivilegedAction<S>() {
407                     public S run() { return nextService(); }
408                 };
409                 return AccessController.doPrivileged(action, acc);
410             }
411         }
412 
413         public void remove() {
414             throw new UnsupportedOperationException();
415         }
416 
417     }
418 
419     /**
420      * Lazily loads the available providers of this loader's service.
421      *
422      * <p> The iterator returned by this method first yields all of the
423      * elements of the provider cache, in instantiation order.  It then lazily
424      * loads and instantiates any remaining providers, adding each one to the
425      * cache in turn.
426      *
427      * <p> To achieve laziness the actual work of parsing the available
428      * provider-configuration files and instantiating providers must be done by
429      * the iterator itself.  Its {@link java.util.Iterator#hasNext hasNext} and
430      * {@link java.util.Iterator#next next} methods can therefore throw a
431      * {@link ServiceConfigurationError} if a provider-configuration file
432      * violates the specified format, or if it names a provider class that
433      * cannot be found and instantiated, or if the result of instantiating the
434      * class is not assignable to the service type, or if any other kind of
435      * exception or error is thrown as the next provider is located and
436      * instantiated.  To write robust code it is only necessary to catch {@link
437      * ServiceConfigurationError} when using a service iterator.
438      *
439      * <p> If such an error is thrown then subsequent invocations of the
440      * iterator will make a best effort to locate and instantiate the next
441      * available provider, but in general such recovery cannot be guaranteed.
442      *
443      * <blockquote style="font-size: smaller; line-height: 1.2"><span
444      * style="padding-right: 1em; font-weight: bold">Design Note</span>
445      * Throwing an error in these cases may seem extreme.  The rationale for
446      * this behavior is that a malformed provider-configuration file, like a
447      * malformed class file, indicates a serious problem with the way the Java
448      * virtual machine is configured or is being used.  As such it is
449      * preferable to throw an error rather than try to recover or, even worse,
450      * fail silently.</blockquote>
451      *
452      * <p> The iterator returned by this method does not support removal.
453      * Invoking its {@link java.util.Iterator#remove() remove} method will
454      * cause an {@link UnsupportedOperationException} to be thrown.
455      *
456      * @implNote When adding providers to the cache, the {@link #iterator
457      * Iterator} processes resources in the order that the {@link
458      * java.lang.ClassLoader#getResources(java.lang.String)
459      * ClassLoader.getResources(String)} method finds the service configuration
460      * files.
461      *
462      * @return  An iterator that lazily loads providers for this loader's
463      *          service
464      */
465     public Iterator<S> iterator() {
466         return new Iterator<S>() {
467 
468             Iterator<Map.Entry<String,S>> knownProviders
469                 = providers.entrySet().iterator();
470 
471             public boolean hasNext() {
472                 if (knownProviders.hasNext())
473                     return true;
474                 return lookupIterator.hasNext();
475             }
476 
477             public S next() {
478                 if (knownProviders.hasNext())
479                     return knownProviders.next().getValue();
480                 return lookupIterator.next();
481             }
482 
483             public void remove() {
484                 throw new UnsupportedOperationException();
485             }
486 
487         };
488     }
489 
490     /**
491      * Creates a new service loader for the given service type and class
492      * loader.
493      *
494      * @param  <S> the class of the service type
495      *
496      * @param  service
497      *         The interface or abstract class representing the service
498      *
499      * @param  loader
500      *         The class loader to be used to load provider-configuration files
501      *         and provider classes, or <tt>null</tt> if the system class
502      *         loader (or, failing that, the bootstrap class loader) is to be
503      *         used
504      *
505      * @return A new service loader
506      */
507     public static <S> ServiceLoader<S> load(Class<S> service,
508                                             ClassLoader loader)
509     {
510         return new ServiceLoader<>(service, loader);
511     }
512 
513     /**
514      * Creates a new service loader for the given service type, using the
515      * current thread's {@linkplain java.lang.Thread#getContextClassLoader
516      * context class loader}.
517      *
518      * <p> An invocation of this convenience method of the form
519      *
520      * <blockquote><pre>
521      * ServiceLoader.load(<i>service</i>)</pre></blockquote>
522      *
523      * is equivalent to
524      *
525      * <blockquote><pre>
526      * ServiceLoader.load(<i>service</i>,
527      *                    Thread.currentThread().getContextClassLoader())</pre></blockquote>
528      *
529      * @param  <S> the class of the service type
530      *
531      * @param  service
532      *         The interface or abstract class representing the service
533      *
534      * @return A new service loader
535      */
536     public static <S> ServiceLoader<S> load(Class<S> service) {
537         ClassLoader cl = Thread.currentThread().getContextClassLoader();
538         return ServiceLoader.load(service, cl);
539     }
540 
541     /**
542      * Creates a new service loader for the given service type, using the
543      * extension class loader.
544      *
545      * <p> This convenience method simply locates the extension class loader,
546      * call it <tt><i>extClassLoader</i></tt>, and then returns
547      *
548      * <blockquote><pre>
549      * ServiceLoader.load(<i>service</i>, <i>extClassLoader</i>)</pre></blockquote>
550      *
551      * <p> If the extension class loader cannot be found then the system class
552      * loader is used; if there is no system class loader then the bootstrap
553      * class loader is used.
554      *
555      * <p> This method is intended for use when only installed providers are
556      * desired.  The resulting service will only find and load providers that
557      * have been installed into the current Java virtual machine; providers on
558      * the application's class path will be ignored.
559      *
560      * @param  <S> the class of the service type
561      *
562      * @param  service
563      *         The interface or abstract class representing the service
564      *
565      * @return A new service loader
566      */
567     public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
568         ClassLoader cl = ClassLoader.getSystemClassLoader();
569         ClassLoader prev = null;
570         while (cl != null) {
571             prev = cl;
572             cl = cl.getParent();
573         }
574         return ServiceLoader.load(service, prev);
575     }
576 
577     /**
578      * Returns a string describing this service.
579      *
580      * @return  A descriptive string
581      */
582     public String toString() {
583         return "java.util.ServiceLoader[" + service.getName() + "]";
584     }
585 
586 }