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