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