151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.util;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.BufferedReader;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.InputStream;
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.InputStreamReader;
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.net.URL;
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.ArrayList;
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Enumeration;
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Iterator;
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.List;
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.NoSuchElementException;
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A simple service-provider loading facility.
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> A <i>service</i> is a well-known set of interfaces and (usually
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * abstract) classes.  A <i>service provider</i> is a specific implementation
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of a service.  The classes in a provider typically implement the interfaces
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and subclass the classes defined in the service itself.  Service providers
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * can be installed in an implementation of the Java platform in the form of
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * extensions, that is, jar files placed into any of the usual extension
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * directories.  Providers can also be made available by adding them to the
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * application's class path or by some other platform-specific means.
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> For the purpose of loading, a service is represented by a single type,
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that is, a single interface or abstract class.  (A concrete class can be
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * used, but this is not recommended.)  A provider of a given service contains
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * one or more concrete classes that extend this <i>service type</i> with data
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and code specific to the provider.  The <i>provider class</i> is typically
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * not the entire provider itself but rather a proxy which contains enough
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * information to decide whether the provider is able to satisfy a particular
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * request together with code that can create the actual provider on demand.
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The details of provider classes tend to be highly service-specific; no
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * single class or interface could possibly unify them, so no such type is
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * defined here.  The only requirement enforced by this facility is that
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * provider classes must have a zero-argument constructor so that they can be
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * instantiated during loading.
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p><a name="format"> A service provider is identified by placing a
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <i>provider-configuration file</i> in the resource directory
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tt>META-INF/services</tt>.  The file's name is the fully-qualified <a
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * href="../lang/ClassLoader.html#name">binary name</a> of the service's type.
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The file contains a list of fully-qualified binary names of concrete
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * provider classes, one per line.  Space and tab characters surrounding each
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * name, as well as blank lines, are ignored.  The comment character is
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tt>'#'</tt> (<tt>'&#92;u0023'</tt>, <font size="-1">NUMBER SIGN</font>); on
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * each line all characters following the first comment character are ignored.
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The file must be encoded in UTF-8.
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> If a particular concrete provider class is named in more than one
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * configuration file, or is named in the same configuration file more than
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * once, then the duplicates are ignored.  The configuration file naming a
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular provider need not be in the same jar file or other distribution
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * unit as the provider itself.  The provider must be accessible from the same
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * class loader that was initially queried to locate the configuration file;
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * note that this is not necessarily the class loader from which the file was
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * actually loaded.
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> Providers are located and instantiated lazily, that is, on demand.  A
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * service loader maintains a cache of the providers that have been loaded so
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * far.  Each invocation of the {@link #iterator iterator} method returns an
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * iterator that first yields all of the elements of the cache, in
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * instantiation order, and then lazily locates and instantiates any remaining
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * providers, adding each one to the cache in turn.  The cache can be cleared
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * via the {@link #reload reload} method.
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> Service loaders always execute in the security context of the caller.
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Trusted system code should typically invoke the methods in this class, and
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the methods of the iterators which they return, from within a privileged
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * security context.
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> Instances of this class are not safe for use by multiple concurrent
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * threads.
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method in this class will cause a {@link NullPointerException} to be thrown.
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p><span style="font-weight: bold; padding-right: 1em">Example</span>
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Suppose we have a service type <tt>com.example.CodecSet</tt> which is
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * intended to represent sets of encoder/decoder pairs for some protocol.  In
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this case it is an abstract class with two abstract methods:
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre>
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * public abstract Encoder getEncoder(String encodingName);
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * public abstract Decoder getDecoder(String encodingName);</pre></blockquote>
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Each method returns an appropriate object or <tt>null</tt> if the provider
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * does not support the given encoding.  Typical providers support more than
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * one encoding.
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> If <tt>com.example.impl.StandardCodecs</tt> is an implementation of the
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tt>CodecSet</tt> service then its jar file also contains a file named
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre>
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * META-INF/services/com.example.CodecSet</pre></blockquote>
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> This file contains the single line:
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre>
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * com.example.impl.StandardCodecs    # Standard codecs</pre></blockquote>
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> The <tt>CodecSet</tt> class creates and saves a single service instance
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * at initialization:
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre>
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * private static ServiceLoader&lt;CodecSet&gt; codecSetLoader
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     = ServiceLoader.load(CodecSet.class);</pre></blockquote>
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> To locate an encoder for a given encoding name it defines a static
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * factory method which iterates through the known and available providers,
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * returning only when it has located a suitable encoder or has run out of
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * providers.
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote><pre>
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * public static Encoder getEncoder(String encodingName) {
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     for (CodecSet cp : codecSetLoader) {
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         Encoder enc = cp.getEncoder(encodingName);
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         if (enc != null)
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             return enc;
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     }
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     return null;
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * }</pre></blockquote>
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> A <tt>getDecoder</tt> method is defined similarly.
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p><span style="font-weight: bold; padding-right: 1em">Usage Note</span> If
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the class path of a class loader that is used for provider loading includes
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * remote network URLs then those URLs will be dereferenced in the process of
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * searching for provider-configuration files.
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> This activity is normal, although it may cause puzzling entries to be
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * created in web-server logs.  If a web server is not configured correctly,
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * however, then this activity may cause the provider-loading algorithm to fail
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * spuriously.
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> A web server should return an HTTP 404 (Not Found) response when a
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * requested resource does not exist.  Sometimes, however, web servers are
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * erroneously configured to return an HTTP 200 (OK) response along with a
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * helpful HTML error page in such cases.  This will cause a {@link
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ServiceConfigurationError} to be thrown when this class attempts to parse
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the HTML page as a provider-configuration file.  The best solution to this
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * problem is to fix the misconfigured web server to return the correct
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * response code (HTTP 404) along with the HTML error page.
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param  <S>
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         The type of the service to be loaded by this loader
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Mark Reinhold
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.6
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic final class ServiceLoader<S>
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    implements Iterable<S>
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final String PREFIX = "META-INF/services/";
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // The class or interface representing the service being loaded
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Class<S> service;
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // The class loader used to locate, load, and instantiate providers
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private ClassLoader loader;
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Cached providers, in instantiation order
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // The current lazy-lookup iterator
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private LazyIterator lookupIterator;
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Clear this loader's provider cache so that all providers will be
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * reloaded.
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> After invoking this method, subsequent invocations of the {@link
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * #iterator() iterator} method will lazily look up and instantiate
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * providers from scratch, just as is done by a newly-created loader.
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> This method is intended for use in situations in which new providers
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * can be installed into a running Java virtual machine.
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void reload() {
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        providers.clear();
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lookupIterator = new LazyIterator(service, loader);
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private ServiceLoader(Class<S> svc, ClassLoader cl) {
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        service = svc;
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        loader = cl;
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        reload();
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static void fail(Class service, String msg, Throwable cause)
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws ServiceConfigurationError
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throw new ServiceConfigurationError(service.getName() + ": " + msg,
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                            cause);
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static void fail(Class service, String msg)
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws ServiceConfigurationError
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throw new ServiceConfigurationError(service.getName() + ": " + msg);
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static void fail(Class service, URL u, int line, String msg)
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws ServiceConfigurationError
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        fail(service, u + ":" + line + ": " + msg);
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Parse a single line from the given configuration file, adding the name
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // on the line to the names list.
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int parseLine(Class service, URL u, BufferedReader r, int lc,
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          List<String> names)
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException, ServiceConfigurationError
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String ln = r.readLine();
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (ln == null) {
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return -1;
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int ci = ln.indexOf('#');
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (ci >= 0) ln = ln.substring(0, ci);
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ln = ln.trim();
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int n = ln.length();
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (n != 0) {
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                fail(service, u, lc, "Illegal configuration-file syntax");
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int cp = ln.codePointAt(0);
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!Character.isJavaIdentifierStart(cp))
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                fail(service, u, lc, "Illegal provider-class name: " + ln);
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                cp = ln.codePointAt(i);
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    fail(service, u, lc, "Illegal provider-class name: " + ln);
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!providers.containsKey(ln) && !names.contains(ln))
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                names.add(ln);
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return lc + 1;
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Parse the content of the given URL as a provider-configuration file.
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // @param  service
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //         The service type for which providers are being sought;
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //         used to construct error detail strings
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // @param  u
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //         The URL naming the configuration file to be parsed
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // @return A (possibly empty) iterator that will yield the provider-class
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //         names in the given configuration file that are not yet members
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //         of the returned set
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // @throws ServiceConfigurationError
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //         If an I/O error occurs while reading from the given URL, or
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //         if a configuration-file format error is detected
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Iterator<String> parse(Class service, URL u)
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws ServiceConfigurationError
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        InputStream in = null;
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        BufferedReader r = null;
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ArrayList<String> names = new ArrayList<>();
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            in = u.openStream();
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            r = new BufferedReader(new InputStreamReader(in, "utf-8"));
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int lc = 1;
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while ((lc = parseLine(service, u, r, lc, names)) >= 0);
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IOException x) {
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            fail(service, "Error reading configuration file", x);
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (r != null) r.close();
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (in != null) in.close();
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (IOException y) {
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                fail(service, "Error closing configuration file", y);
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return names.iterator();
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Private inner class implementing fully-lazy provider lookup
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    //
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private class LazyIterator
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        implements Iterator<S>
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Class<S> service;
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassLoader loader;
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Enumeration<URL> configs = null;
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Iterator<String> pending = null;
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String nextName = null;
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        private LazyIterator(Class<S> service, ClassLoader loader) {
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.service = service;
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.loader = loader;
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean hasNext() {
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (nextName != null) {
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return true;
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (configs == null) {
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                try {
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    String fullName = PREFIX + service.getName();
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (loader == null)
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        configs = ClassLoader.getSystemResources(fullName);
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    else
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        configs = loader.getResources(fullName);
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } catch (IOException x) {
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    fail(service, "Error locating configuration files", x);
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while ((pending == null) || !pending.hasNext()) {
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!configs.hasMoreElements()) {
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return false;
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                pending = parse(service, configs.nextElement());
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            nextName = pending.next();
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return true;
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public S next() {
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!hasNext()) {
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new NoSuchElementException();
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String cn = nextName;
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            nextName = null;
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Class<?> c = null;
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                c = Class.forName(cn, false, loader);
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (ClassNotFoundException x) {
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                fail(service,
367f8382ed614d5e2bc3056db92d57459ca0564c7ccNarayan Kamath                     "Provider " + cn + " not found", x);
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!service.isAssignableFrom(c)) {
370f8382ed614d5e2bc3056db92d57459ca0564c7ccNarayan Kamath                ClassCastException cce = new ClassCastException(
371f8382ed614d5e2bc3056db92d57459ca0564c7ccNarayan Kamath                        service.getCanonicalName() + " is not assignable from " + c.getCanonicalName());
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                fail(service,
373f8382ed614d5e2bc3056db92d57459ca0564c7ccNarayan Kamath                     "Provider " + cn  + " not a subtype", cce);
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                S p = service.cast(c.newInstance());
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                providers.put(cn, p);
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return p;
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (Throwable x) {
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                fail(service,
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     "Provider " + cn + " could not be instantiated: " + x,
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     x);
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new Error();          // This cannot happen
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void remove() {
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new UnsupportedOperationException();
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Lazily loads the available providers of this loader's service.
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> The iterator returned by this method first yields all of the
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * elements of the provider cache, in instantiation order.  It then lazily
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * loads and instantiates any remaining providers, adding each one to the
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * cache in turn.
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> To achieve laziness the actual work of parsing the available
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * provider-configuration files and instantiating providers must be done by
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the iterator itself.  Its {@link java.util.Iterator#hasNext hasNext} and
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@link java.util.Iterator#next next} methods can therefore throw a
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@link ServiceConfigurationError} if a provider-configuration file
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * violates the specified format, or if it names a provider class that
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * cannot be found and instantiated, or if the result of instantiating the
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * class is not assignable to the service type, or if any other kind of
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * exception or error is thrown as the next provider is located and
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * instantiated.  To write robust code it is only necessary to catch {@link
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ServiceConfigurationError} when using a service iterator.
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> If such an error is thrown then subsequent invocations of the
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * iterator will make a best effort to locate and instantiate the next
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * available provider, but in general such recovery cannot be guaranteed.
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <blockquote style="font-size: smaller; line-height: 1.2"><span
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * style="padding-right: 1em; font-weight: bold">Design Note</span>
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Throwing an error in these cases may seem extreme.  The rationale for
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * this behavior is that a malformed provider-configuration file, like a
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * malformed class file, indicates a serious problem with the way the Java
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * virtual machine is configured or is being used.  As such it is
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * preferable to throw an error rather than try to recover or, even worse,
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * fail silently.</blockquote>
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> The iterator returned by this method does not support removal.
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Invoking its {@link java.util.Iterator#remove() remove} method will
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * cause an {@link UnsupportedOperationException} to be thrown.
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  An iterator that lazily loads providers for this loader's
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          service
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Iterator<S> iterator() {
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return new Iterator<S>() {
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Iterator<Map.Entry<String,S>> knownProviders
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                = providers.entrySet().iterator();
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public boolean hasNext() {
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (knownProviders.hasNext())
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return true;
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return lookupIterator.hasNext();
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public S next() {
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (knownProviders.hasNext())
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return knownProviders.next().getValue();
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return lookupIterator.next();
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public void remove() {
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new UnsupportedOperationException();
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        };
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a new service loader for the given service type and class
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * loader.
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param  service
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         The interface or abstract class representing the service
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param  loader
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         The class loader to be used to load provider-configuration files
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         and provider classes, or <tt>null</tt> if the system class
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         loader (or, failing that, the bootstrap class loader) is to be
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         used
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return A new service loader
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static <S> ServiceLoader<S> load(Class<S> service,
47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                            ClassLoader loader)
47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return new ServiceLoader<>(service, loader);
47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a new service loader for the given service type, using the
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * current thread's {@linkplain java.lang.Thread#getContextClassLoader
48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * context class loader}.
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> An invocation of this convenience method of the form
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <blockquote><pre>
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ServiceLoader.load(<i>service</i>)</pre></blockquote>
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is equivalent to
49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <blockquote><pre>
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ServiceLoader.load(<i>service</i>,
49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                    Thread.currentThread().getContextClassLoader())</pre></blockquote>
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param  service
49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         The interface or abstract class representing the service
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return A new service loader
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static <S> ServiceLoader<S> load(Class<S> service) {
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassLoader cl = Thread.currentThread().getContextClassLoader();
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return ServiceLoader.load(service, cl);
50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a new service loader for the given service type, using the
50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * extension class loader.
50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> This convenience method simply locates the extension class loader,
51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * call it <tt><i>extClassLoader</i></tt>, and then returns
51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <blockquote><pre>
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ServiceLoader.load(<i>service</i>, <i>extClassLoader</i>)</pre></blockquote>
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> If the extension class loader cannot be found then the system class
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * loader is used; if there is no system class loader then the bootstrap
51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * class loader is used.
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> This method is intended for use when only installed providers are
52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * desired.  The resulting service will only find and load providers that
52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * have been installed into the current Java virtual machine; providers on
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the application's class path will be ignored.
52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param  service
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         The interface or abstract class representing the service
52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return A new service loader
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassLoader cl = ClassLoader.getSystemClassLoader();
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ClassLoader prev = null;
53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while (cl != null) {
53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            prev = cl;
53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            cl = cl.getParent();
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return ServiceLoader.load(service, prev);
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
540983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski     * Internal API to support built-in SPIs that check a system property first.
541983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski     * Returns an instance specified by a property with the class' binary name, or null if
542983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski     * no such property is set.
543983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski     * @hide
544983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski     */
545983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski    public static <S> S loadFromSystemProperty(final Class<S> service) {
546983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski        try {
547983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski            final String className = System.getProperty(service.getName());
548983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski            if (className != null) {
549983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski                Class<?> c = ClassLoader.getSystemClassLoader().loadClass(className);
550983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski                return (S) c.newInstance();
551983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski            }
552983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski            return null;
553983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski        } catch (Exception e) {
554983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski            throw new Error(e);
555983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski        }
556983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski    }
557983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski
558983b2c6ff9ea6d35adf7ab6398dccf870b7e180aPiotr Jastrzebski    /**
55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a string describing this service.
56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  A descriptive string
56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String toString() {
56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return "java.util.ServiceLoader[" + service.getName() + "]";
56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
568