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>.  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>, <font size="-1">NUMBER SIGN</font>); on
  77  * each line all characters following the first comment character are ignored.
  78  * The file must be encoded in UTF-8.
  79  *
  80  * <p> If a particular concrete provider class is named in more than one
  81  * configuration file, or is named in the same configuration file more than
  82  * once, then the duplicates are ignored.  The configuration file naming a
  83  * particular provider need not be in the same jar file or other distribution
  84  * unit as the provider itself.  The provider must be accessible from the same
  85  * class loader that was initially queried to locate the configuration file;
  86  * note that this is not necessarily the class loader from which the file was
  87  * actually loaded.
  88  *
  89  * <p> Providers are located and instantiated lazily, that is, on demand.  A
  90  * service loader maintains a cache of the providers that have been loaded so
  91  * far.  Each invocation of the {@link #iterator iterator} method returns an
  92  * iterator that first yields all of the elements of the cache, in
  93  * instantiation order, and then lazily locates and instantiates any remaining
  94  * providers, adding each one to the cache in turn.  The cache can be cleared
  95  * via the {@link #reload reload} method.
  96  *
  97  * <p> Service loaders always execute in the security context of the caller.
  98  * Trusted system code should typically invoke the methods in this class, and
  99  * the methods of the iterators which they return, from within a privileged
 100  * security context.
 101  *
 102  * <p> Instances of this class are not safe for use by multiple concurrent
 103  * threads.
 104  *
 105  * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
 106  * method in this class will cause a {@link NullPointerException} to be thrown.
 107  *
 108  *
 109  * <p><span style="font-weight: bold; padding-right: 1em">Example</span>
 110  * Suppose we have a service type <tt>com.example.CodecSet</tt> which is
 111  * intended to represent sets of encoder/decoder pairs for some protocol.  In
 112  * this case it is an abstract class with two abstract methods:
 113  *
 114  * <blockquote><pre>
 115  * public abstract Encoder getEncoder(String encodingName);
 116  * public abstract Decoder getDecoder(String encodingName);</pre></blockquote>
 117  *
 118  * Each method returns an appropriate object or <tt>null</tt> if the provider
 119  * does not support the given encoding.  Typical providers support more than
 120  * one encoding.
 121  *
 122  * <p> If <tt>com.example.impl.StandardCodecs</tt> is an implementation of the
 123  * <tt>CodecSet</tt> service then its jar file also contains a file named
 124  *
 125  * <blockquote><pre>
 126  * META-INF/services/com.example.CodecSet</pre></blockquote>
 127  *
 128  * <p> This file contains the single line:
 129  *
 130  * <blockquote><pre>
 131  * com.example.impl.StandardCodecs    # Standard codecs</pre></blockquote>
 132  *
 133  * <p> The <tt>CodecSet</tt> class creates and saves a single service instance
 134  * at initialization:
 135  *
 136  * <blockquote><pre>
 137  * private static ServiceLoader&lt;CodecSet&gt; codecSetLoader
 138  *     = ServiceLoader.load(CodecSet.class);</pre></blockquote>
 139  *
 140  * <p> To locate an encoder for a given encoding name it defines a static
 141  * factory method which iterates through the known and available providers,
 142  * returning only when it has located a suitable encoder or has run out of
 143  * providers.
 144  *
 145  * <blockquote><pre>
 146  * public static Encoder getEncoder(String encodingName) {
 147  *     for (CodecSet cp : codecSetLoader) {
 148  *         Encoder enc = cp.getEncoder(encodingName);
 149  *         if (enc != null)
 150  *             return enc;
 151  *     }
 152  *     return null;
 153  * }</pre></blockquote>
 154  *
 155  * <p> A <tt>getDecoder</tt> method is defined similarly.
 156  *
 157  *
 158  * <p><span style="font-weight: bold; padding-right: 1em">Usage Note</span> If
 159  * the class path of a class loader that is used for provider loading includes
 160  * remote network URLs then those URLs will be dereferenced in the process of
 161  * searching for provider-configuration files.
 162  *
 163  * <p> This activity is normal, although it may cause puzzling entries to be
 164  * created in web-server logs.  If a web server is not configured correctly,
 165  * however, then this activity may cause the provider-loading algorithm to fail
 166  * spuriously.
 167  *
 168  * <p> A web server should return an HTTP 404 (Not Found) response when a
 169  * requested resource does not exist.  Sometimes, however, web servers are
 170  * erroneously configured to return an HTTP 200 (OK) response along with a
 171  * helpful HTML error page in such cases.  This will cause a {@link
 172  * ServiceConfigurationError} to be thrown when this class attempts to parse
 173  * the HTML page as a provider-configuration file.  The best solution to this
 174  * problem is to fix the misconfigured web server to return the correct
 175  * response code (HTTP 404) along with the HTML error page.
 176  *
 177  * @param  <S>
 178  *         The type of the service to be loaded by this loader
 179  *
 180  * @author Mark Reinhold
 181  * @since 1.6
 182  */
 183 
 184 public final class ServiceLoader<S>
 185     implements Iterable<S>
 186 {
 187 
 188     private static final String PREFIX = "META-INF/services/";
 189 
 190     // The class or interface representing the service being loaded
 191     private final Class<S> service;
 192 
 193     // The class loader used to locate, load, and instantiate providers
 194     private final ClassLoader loader;
 195 
 196     // The access control context taken when the ServiceLoader is created
 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      */
 216     public void reload() {
 217         providers.clear();
 218         lookupIterator = new LazyIterator(service, loader);
 219     }
 220 
 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         acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
 225         reload();
 226     }
 227 
 228     private static void fail(Class<?> service, String msg, Throwable cause)
 229         throws ServiceConfigurationError
 230     {
 231         throw new ServiceConfigurationError(service.getName() + ": " + msg,
 232                                             cause);
 233     }
 234 
 235     private static void fail(Class<?> service, String msg)
 236         throws ServiceConfigurationError
 237     {
 238         throw new ServiceConfigurationError(service.getName() + ": " + msg);
 239     }
 240 
 241     private static void fail(Class<?> service, URL u, int line, String msg)
 242         throws ServiceConfigurationError
 243     {
 244         fail(service, u + ":" + line + ": " + msg);
 245     }
 246 
 247     // Parse a single line from the given configuration file, adding the name
 248     // on the line to the names list.
 249     //
 250     private int parseLine(Class<?> service, URL u, BufferedReader r, int lc,
 251                           List<String> names)
 252         throws IOException, ServiceConfigurationError
 253     {
 254         String ln = r.readLine();
 255         if (ln == null) {
 256             return -1;
 257         }
 258         int ci = ln.indexOf('#');
 259         if (ci >= 0) ln = ln.substring(0, ci);
 260         ln = ln.trim();
 261         int n = ln.length();
 262         if (n != 0) {
 263             if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
 264                 fail(service, u, lc, "Illegal configuration-file syntax");
 265             int cp = ln.codePointAt(0);
 266             if (!Character.isJavaIdentifierStart(cp))
 267                 fail(service, u, lc, "Illegal provider-class name: " + ln);
 268             for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
 269                 cp = ln.codePointAt(i);
 270                 if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
 271                     fail(service, u, lc, "Illegal provider-class name: " + ln);
 272             }
 273             if (!providers.containsKey(ln) && !names.contains(ln))
 274                 names.add(ln);
 275         }
 276         return lc + 1;
 277     }
 278 
 279     // Parse the content of the given URL as a provider-configuration file.
 280     //
 281     // @param  service
 282     //         The service type for which providers are being sought;
 283     //         used to construct error detail strings
 284     //
 285     // @param  u
 286     //         The URL naming the configuration file to be parsed
 287     //
 288     // @return A (possibly empty) iterator that will yield the provider-class
 289     //         names in the given configuration file that are not yet members
 290     //         of the returned set
 291     //
 292     // @throws ServiceConfigurationError
 293     //         If an I/O error occurs while reading from the given URL, or
 294     //         if a configuration-file format error is detected
 295     //
 296     private Iterator<String> parse(Class<?> service, URL u)
 297         throws ServiceConfigurationError
 298     {
 299         InputStream in = null;
 300         BufferedReader r = null;
 301         ArrayList<String> names = new ArrayList<>();
 302         try {
 303             in = u.openStream();
 304             r = new BufferedReader(new InputStreamReader(in, "utf-8"));
 305             int lc = 1;
 306             while ((lc = parseLine(service, u, r, lc, names)) >= 0);
 307         } catch (IOException x) {
 308             fail(service, "Error reading configuration file", x);
 309         } finally {
 310             try {
 311                 if (r != null) r.close();
 312                 if (in != null) in.close();
 313             } catch (IOException y) {
 314                 fail(service, "Error closing configuration file", y);
 315             }
 316         }
 317         return names.iterator();
 318     }
 319 
 320     // Private inner class implementing fully-lazy provider lookup
 321     //
 322     private class LazyIterator
 323         implements Iterator<S>
 324     {
 325 
 326         Class<S> service;
 327         ClassLoader loader;
 328         Enumeration<URL> configs = null;
 329         Iterator<String> pending = null;
 330         String nextName = null;
 331 
 332         private LazyIterator(Class<S> service, ClassLoader loader) {
 333             this.service = service;
 334             this.loader = loader;
 335         }
 336 
 337         private boolean hasNextService() {
 338             if (nextName != null) {
 339                 return true;
 340             }
 341             if (configs == null) {
 342                 try {
 343                     String fullName = PREFIX + service.getName();
 344                     if (loader == null)
 345                         configs = ClassLoader.getSystemResources(fullName);
 346                     else
 347                         configs = loader.getResources(fullName);
 348                 } catch (IOException x) {
 349                     fail(service, "Error locating configuration files", x);
 350                 }
 351             }
 352             while ((pending == null) || !pending.hasNext()) {
 353                 if (!configs.hasMoreElements()) {
 354                     return false;
 355                 }
 356                 pending = parse(service, configs.nextElement());
 357             }
 358             nextName = pending.next();
 359             return true;
 360         }
 361 
 362         private S nextService() {
 363             if (!hasNextService())
 364                 throw new NoSuchElementException();
 365             String cn = nextName;
 366             nextName = null;
 367             Class<?> c = null;
 368             try {
 369                 c = Class.forName(cn, false, loader);
 370             } catch (ClassNotFoundException x) {
 371                 fail(service,
 372                      "Provider " + cn + " not found");
 373             }
 374             if (!service.isAssignableFrom(c)) {
 375                 fail(service,
 376                      "Provider " + cn  + " not a subtype");
 377             }
 378             try {
 379                 S p = service.cast(c.newInstance());
 380                 providers.put(cn, p);
 381                 return p;
 382             } catch (Throwable x) {
 383                 fail(service,
 384                      "Provider " + cn + " could not be instantiated: " + x,
 385                      x);
 386             }
 387             throw new Error();          // This cannot happen
 388         }
 389 
 390         public boolean hasNext() {
 391             if (acc == null) {
 392                 return hasNextService();
 393             } else {
 394                 PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {
 395                     public Boolean run() { return hasNextService(); }
 396                 };
 397                 return AccessController.doPrivileged(action, acc);
 398             }
 399         }
 400 
 401         public S next() {
 402             if (acc == null) {
 403                 return nextService();
 404             } else {
 405                 PrivilegedAction<S> action = new PrivilegedAction<S>() {
 406                     public S run() { return nextService(); }
 407                 };
 408                 return AccessController.doPrivileged(action, acc);
 409             }
 410         }
 411 
 412         public void remove() {
 413             throw new UnsupportedOperationException();
 414         }
 415 
 416     }
 417 
 418     /**
 419      * Lazily loads the available providers of this loader's service.
 420      *
 421      * <p> The iterator returned by this method first yields all of the
 422      * elements of the provider cache, in instantiation order.  It then lazily
 423      * loads and instantiates any remaining providers, adding each one to the
 424      * cache in turn.
 425      *
 426      * <p> To achieve laziness the actual work of parsing the available
 427      * provider-configuration files and instantiating providers must be done by
 428      * the iterator itself.  Its {@link java.util.Iterator#hasNext hasNext} and
 429      * {@link java.util.Iterator#next next} methods can therefore throw a
 430      * {@link ServiceConfigurationError} if a provider-configuration file
 431      * violates the specified format, or if it names a provider class that
 432      * cannot be found and instantiated, or if the result of instantiating the
 433      * class is not assignable to the service type, or if any other kind of
 434      * exception or error is thrown as the next provider is located and
 435      * instantiated.  To write robust code it is only necessary to catch {@link
 436      * ServiceConfigurationError} when using a service iterator.
 437      *
 438      * <p> If such an error is thrown then subsequent invocations of the
 439      * iterator will make a best effort to locate and instantiate the next
 440      * available provider, but in general such recovery cannot be guaranteed.
 441      *
 442      * <blockquote style="font-size: smaller; line-height: 1.2"><span
 443      * style="padding-right: 1em; font-weight: bold">Design Note</span>
 444      * Throwing an error in these cases may seem extreme.  The rationale for
 445      * this behavior is that a malformed provider-configuration file, like a
 446      * malformed class file, indicates a serious problem with the way the Java
 447      * virtual machine is configured or is being used.  As such it is
 448      * preferable to throw an error rather than try to recover or, even worse,
 449      * fail silently.</blockquote>
 450      *
 451      * <p> The iterator returned by this method does not support removal.
 452      * Invoking its {@link java.util.Iterator#remove() remove} method will
 453      * cause an {@link UnsupportedOperationException} to be thrown.
 454      *
 455      * @return  An iterator that lazily loads providers for this loader's
 456      *          service
 457      */
 458     public Iterator<S> iterator() {
 459         return new Iterator<S>() {
 460 
 461             Iterator<Map.Entry<String,S>> knownProviders
 462                 = providers.entrySet().iterator();
 463 
 464             public boolean hasNext() {
 465                 if (knownProviders.hasNext())
 466                     return true;
 467                 return lookupIterator.hasNext();
 468             }
 469 
 470             public S next() {
 471                 if (knownProviders.hasNext())
 472                     return knownProviders.next().getValue();
 473                 return lookupIterator.next();
 474             }
 475 
 476             public void remove() {
 477                 throw new UnsupportedOperationException();
 478             }
 479 
 480         };
 481     }
 482 
 483     /**
 484      * Creates a new service loader for the given service type and class
 485      * loader.
 486      *
 487      * @param  service
 488      *         The interface or abstract class representing the service
 489      *
 490      * @param  loader
 491      *         The class loader to be used to load provider-configuration files
 492      *         and provider classes, or <tt>null</tt> if the system class
 493      *         loader (or, failing that, the bootstrap class loader) is to be
 494      *         used
 495      *
 496      * @return A new service loader
 497      */
 498     public static <S> ServiceLoader<S> load(Class<S> service,
 499                                             ClassLoader loader)
 500     {
 501         return new ServiceLoader<>(service, loader);
 502     }
 503 
 504     /**
 505      * Creates a new service loader for the given service type, using the
 506      * current thread's {@linkplain java.lang.Thread#getContextClassLoader
 507      * context class loader}.
 508      *
 509      * <p> An invocation of this convenience method of the form
 510      *
 511      * <blockquote><pre>
 512      * ServiceLoader.load(<i>service</i>)</pre></blockquote>
 513      *
 514      * is equivalent to
 515      *
 516      * <blockquote><pre>
 517      * ServiceLoader.load(<i>service</i>,
 518      *                    Thread.currentThread().getContextClassLoader())</pre></blockquote>
 519      *
 520      * @param  service
 521      *         The interface or abstract class representing the service
 522      *
 523      * @return A new service loader
 524      */
 525     public static <S> ServiceLoader<S> load(Class<S> service) {
 526         ClassLoader cl = Thread.currentThread().getContextClassLoader();
 527         return ServiceLoader.load(service, cl);
 528     }
 529 
 530     /**
 531      * Creates a new service loader for the given service type, using the
 532      * extension class loader.
 533      *
 534      * <p> This convenience method simply locates the extension class loader,
 535      * call it <tt><i>extClassLoader</i></tt>, and then returns
 536      *
 537      * <blockquote><pre>
 538      * ServiceLoader.load(<i>service</i>, <i>extClassLoader</i>)</pre></blockquote>
 539      *
 540      * <p> If the extension class loader cannot be found then the system class
 541      * loader is used; if there is no system class loader then the bootstrap
 542      * class loader is used.
 543      *
 544      * <p> This method is intended for use when only installed providers are
 545      * desired.  The resulting service will only find and load providers that
 546      * have been installed into the current Java virtual machine; providers on
 547      * the application's class path will be ignored.
 548      *
 549      * @param  service
 550      *         The interface or abstract class representing the service
 551      *
 552      * @return A new service loader
 553      */
 554     public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
 555         ClassLoader cl = ClassLoader.getSystemClassLoader();
 556         ClassLoader prev = null;
 557         while (cl != null) {
 558             prev = cl;
 559             cl = cl.getParent();
 560         }
 561         return ServiceLoader.load(service, prev);
 562     }
 563 
 564     /**
 565      * Returns a string describing this service.
 566      *
 567      * @return  A descriptive string
 568      */
 569     public String toString() {
 570         return "java.util.ServiceLoader[" + service.getName() + "]";
 571     }
 572 
 573 }