1 /*
   2  * Copyright (c) 2005, 2012, 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      * @return  An iterator that lazily loads providers for this loader's
 457      *          service
 458      */
 459     public Iterator<S> iterator() {
 460         return new Iterator<S>() {
 461 
 462             Iterator<Map.Entry<String,S>> knownProviders
 463                 = providers.entrySet().iterator();
 464 
 465             public boolean hasNext() {
 466                 if (knownProviders.hasNext())
 467                     return true;
 468                 return lookupIterator.hasNext();
 469             }
 470 
 471             public S next() {
 472                 if (knownProviders.hasNext())
 473                     return knownProviders.next().getValue();
 474                 return lookupIterator.next();
 475             }
 476 
 477             public void remove() {
 478                 throw new UnsupportedOperationException();
 479             }
 480 
 481         };
 482     }
 483 
 484     /**
 485      * Creates a new service loader for the given service type and class
 486      * loader.
 487      *
 488      * @param  <S> the class of the service type
 489      *
 490      * @param  service
 491      *         The interface or abstract class representing the service
 492      *
 493      * @param  loader
 494      *         The class loader to be used to load provider-configuration files
 495      *         and provider classes, or <tt>null</tt> if the system class
 496      *         loader (or, failing that, the bootstrap class loader) is to be
 497      *         used
 498      *
 499      * @return A new service loader
 500      */
 501     public static <S> ServiceLoader<S> load(Class<S> service,
 502                                             ClassLoader loader)
 503     {
 504         return new ServiceLoader<>(service, loader);
 505     }
 506 
 507     /**
 508      * Creates a new service loader for the given service type, using the
 509      * current thread's {@linkplain java.lang.Thread#getContextClassLoader
 510      * context class loader}.
 511      *
 512      * <p> An invocation of this convenience method of the form
 513      *
 514      * <blockquote><pre>
 515      * ServiceLoader.load(<i>service</i>)</pre></blockquote>
 516      *
 517      * is equivalent to
 518      *
 519      * <blockquote><pre>
 520      * ServiceLoader.load(<i>service</i>,
 521      *                    Thread.currentThread().getContextClassLoader())</pre></blockquote>
 522      *
 523      * @param  <S> the class of the service type
 524      *
 525      * @param  service
 526      *         The interface or abstract class representing the service
 527      *
 528      * @return A new service loader
 529      */
 530     public static <S> ServiceLoader<S> load(Class<S> service) {
 531         ClassLoader cl = Thread.currentThread().getContextClassLoader();
 532         return ServiceLoader.load(service, cl);
 533     }
 534 
 535     /**
 536      * Creates a new service loader for the given service type, using the
 537      * extension class loader.
 538      *
 539      * <p> This convenience method simply locates the extension class loader,
 540      * call it <tt><i>extClassLoader</i></tt>, and then returns
 541      *
 542      * <blockquote><pre>
 543      * ServiceLoader.load(<i>service</i>, <i>extClassLoader</i>)</pre></blockquote>
 544      *
 545      * <p> If the extension class loader cannot be found then the system class
 546      * loader is used; if there is no system class loader then the bootstrap
 547      * class loader is used.
 548      *
 549      * <p> This method is intended for use when only installed providers are
 550      * desired.  The resulting service will only find and load providers that
 551      * have been installed into the current Java virtual machine; providers on
 552      * the application's class path will be ignored.
 553      *
 554      * @param  <S> the class of the service type
 555      *
 556      * @param  service
 557      *         The interface or abstract class representing the service
 558      *
 559      * @return A new service loader
 560      */
 561     public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
 562         ClassLoader cl = ClassLoader.getSystemClassLoader();
 563         ClassLoader prev = null;
 564         while (cl != null) {
 565             prev = cl;
 566             cl = cl.getParent();
 567         }
 568         return ServiceLoader.load(service, prev);
 569     }
 570 
 571     /**
 572      * Returns a string describing this service.
 573      *
 574      * @return  A descriptive string
 575      */
 576     public String toString() {
 577         return "java.util.ServiceLoader[" + service.getName() + "]";
 578     }
 579 
 580 }