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>'\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<CodecSet> 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