1.1 --- a/emul/compact/src/main/java/java/util/ServiceLoader.java Tue Feb 26 14:55:55 2013 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,538 +0,0 @@
1.4 -/*
1.5 - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 - *
1.8 - * This code is free software; you can redistribute it and/or modify it
1.9 - * under the terms of the GNU General Public License version 2 only, as
1.10 - * published by the Free Software Foundation. Oracle designates this
1.11 - * particular file as subject to the "Classpath" exception as provided
1.12 - * by Oracle in the LICENSE file that accompanied this code.
1.13 - *
1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 - * version 2 for more details (a copy is included in the LICENSE file that
1.18 - * accompanied this code).
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License version
1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 - *
1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 - * or visit www.oracle.com if you need additional information or have any
1.26 - * questions.
1.27 - */
1.28 -
1.29 -package java.util;
1.30 -
1.31 -import java.io.BufferedReader;
1.32 -import java.io.IOException;
1.33 -import java.io.InputStream;
1.34 -import java.io.InputStreamReader;
1.35 -import java.net.URL;
1.36 -import java.util.ArrayList;
1.37 -import java.util.Enumeration;
1.38 -import java.util.Iterator;
1.39 -import java.util.List;
1.40 -import java.util.NoSuchElementException;
1.41 -
1.42 -
1.43 -/**
1.44 - * A simple service-provider loading facility.
1.45 - *
1.46 - * <p> A <i>service</i> is a well-known set of interfaces and (usually
1.47 - * abstract) classes. A <i>service provider</i> is a specific implementation
1.48 - * of a service. The classes in a provider typically implement the interfaces
1.49 - * and subclass the classes defined in the service itself. Service providers
1.50 - * can be installed in an implementation of the Java platform in the form of
1.51 - * extensions, that is, jar files placed into any of the usual extension
1.52 - * directories. Providers can also be made available by adding them to the
1.53 - * application's class path or by some other platform-specific means.
1.54 - *
1.55 - * <p> For the purpose of loading, a service is represented by a single type,
1.56 - * that is, a single interface or abstract class. (A concrete class can be
1.57 - * used, but this is not recommended.) A provider of a given service contains
1.58 - * one or more concrete classes that extend this <i>service type</i> with data
1.59 - * and code specific to the provider. The <i>provider class</i> is typically
1.60 - * not the entire provider itself but rather a proxy which contains enough
1.61 - * information to decide whether the provider is able to satisfy a particular
1.62 - * request together with code that can create the actual provider on demand.
1.63 - * The details of provider classes tend to be highly service-specific; no
1.64 - * single class or interface could possibly unify them, so no such type is
1.65 - * defined here. The only requirement enforced by this facility is that
1.66 - * provider classes must have a zero-argument constructor so that they can be
1.67 - * instantiated during loading.
1.68 - *
1.69 - * <p><a name="format"> A service provider is identified by placing a
1.70 - * <i>provider-configuration file</i> in the resource directory
1.71 - * <tt>META-INF/services</tt>. The file's name is the fully-qualified <a
1.72 - * href="../lang/ClassLoader.html#name">binary name</a> of the service's type.
1.73 - * The file contains a list of fully-qualified binary names of concrete
1.74 - * provider classes, one per line. Space and tab characters surrounding each
1.75 - * name, as well as blank lines, are ignored. The comment character is
1.76 - * <tt>'#'</tt> (<tt>'\u0023'</tt>, <font size="-1">NUMBER SIGN</font>); on
1.77 - * each line all characters following the first comment character are ignored.
1.78 - * The file must be encoded in UTF-8.
1.79 - *
1.80 - * <p> If a particular concrete provider class is named in more than one
1.81 - * configuration file, or is named in the same configuration file more than
1.82 - * once, then the duplicates are ignored. The configuration file naming a
1.83 - * particular provider need not be in the same jar file or other distribution
1.84 - * unit as the provider itself. The provider must be accessible from the same
1.85 - * class loader that was initially queried to locate the configuration file;
1.86 - * note that this is not necessarily the class loader from which the file was
1.87 - * actually loaded.
1.88 - *
1.89 - * <p> Providers are located and instantiated lazily, that is, on demand. A
1.90 - * service loader maintains a cache of the providers that have been loaded so
1.91 - * far. Each invocation of the {@link #iterator iterator} method returns an
1.92 - * iterator that first yields all of the elements of the cache, in
1.93 - * instantiation order, and then lazily locates and instantiates any remaining
1.94 - * providers, adding each one to the cache in turn. The cache can be cleared
1.95 - * via the {@link #reload reload} method.
1.96 - *
1.97 - * <p> Service loaders always execute in the security context of the caller.
1.98 - * Trusted system code should typically invoke the methods in this class, and
1.99 - * the methods of the iterators which they return, from within a privileged
1.100 - * security context.
1.101 - *
1.102 - * <p> Instances of this class are not safe for use by multiple concurrent
1.103 - * threads.
1.104 - *
1.105 - * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
1.106 - * method in this class will cause a {@link NullPointerException} to be thrown.
1.107 - *
1.108 - *
1.109 - * <p><span style="font-weight: bold; padding-right: 1em">Example</span>
1.110 - * Suppose we have a service type <tt>com.example.CodecSet</tt> which is
1.111 - * intended to represent sets of encoder/decoder pairs for some protocol. In
1.112 - * this case it is an abstract class with two abstract methods:
1.113 - *
1.114 - * <blockquote><pre>
1.115 - * public abstract Encoder getEncoder(String encodingName);
1.116 - * public abstract Decoder getDecoder(String encodingName);</pre></blockquote>
1.117 - *
1.118 - * Each method returns an appropriate object or <tt>null</tt> if the provider
1.119 - * does not support the given encoding. Typical providers support more than
1.120 - * one encoding.
1.121 - *
1.122 - * <p> If <tt>com.example.impl.StandardCodecs</tt> is an implementation of the
1.123 - * <tt>CodecSet</tt> service then its jar file also contains a file named
1.124 - *
1.125 - * <blockquote><pre>
1.126 - * META-INF/services/com.example.CodecSet</pre></blockquote>
1.127 - *
1.128 - * <p> This file contains the single line:
1.129 - *
1.130 - * <blockquote><pre>
1.131 - * com.example.impl.StandardCodecs # Standard codecs</pre></blockquote>
1.132 - *
1.133 - * <p> The <tt>CodecSet</tt> class creates and saves a single service instance
1.134 - * at initialization:
1.135 - *
1.136 - * <blockquote><pre>
1.137 - * private static ServiceLoader<CodecSet> codecSetLoader
1.138 - * = ServiceLoader.load(CodecSet.class);</pre></blockquote>
1.139 - *
1.140 - * <p> To locate an encoder for a given encoding name it defines a static
1.141 - * factory method which iterates through the known and available providers,
1.142 - * returning only when it has located a suitable encoder or has run out of
1.143 - * providers.
1.144 - *
1.145 - * <blockquote><pre>
1.146 - * public static Encoder getEncoder(String encodingName) {
1.147 - * for (CodecSet cp : codecSetLoader) {
1.148 - * Encoder enc = cp.getEncoder(encodingName);
1.149 - * if (enc != null)
1.150 - * return enc;
1.151 - * }
1.152 - * return null;
1.153 - * }</pre></blockquote>
1.154 - *
1.155 - * <p> A <tt>getDecoder</tt> method is defined similarly.
1.156 - *
1.157 - *
1.158 - * <p><span style="font-weight: bold; padding-right: 1em">Usage Note</span> If
1.159 - * the class path of a class loader that is used for provider loading includes
1.160 - * remote network URLs then those URLs will be dereferenced in the process of
1.161 - * searching for provider-configuration files.
1.162 - *
1.163 - * <p> This activity is normal, although it may cause puzzling entries to be
1.164 - * created in web-server logs. If a web server is not configured correctly,
1.165 - * however, then this activity may cause the provider-loading algorithm to fail
1.166 - * spuriously.
1.167 - *
1.168 - * <p> A web server should return an HTTP 404 (Not Found) response when a
1.169 - * requested resource does not exist. Sometimes, however, web servers are
1.170 - * erroneously configured to return an HTTP 200 (OK) response along with a
1.171 - * helpful HTML error page in such cases. This will cause a {@link
1.172 - * ServiceConfigurationError} to be thrown when this class attempts to parse
1.173 - * the HTML page as a provider-configuration file. The best solution to this
1.174 - * problem is to fix the misconfigured web server to return the correct
1.175 - * response code (HTTP 404) along with the HTML error page.
1.176 - *
1.177 - * @param <S>
1.178 - * The type of the service to be loaded by this loader
1.179 - *
1.180 - * @author Mark Reinhold
1.181 - * @since 1.6
1.182 - */
1.183 -
1.184 -public final class ServiceLoader<S>
1.185 - implements Iterable<S>
1.186 -{
1.187 -
1.188 - private static final String PREFIX = "META-INF/services/";
1.189 -
1.190 - // The class or interface representing the service being loaded
1.191 - private Class<S> service;
1.192 -
1.193 - // The class loader used to locate, load, and instantiate providers
1.194 - private ClassLoader loader;
1.195 -
1.196 - // Cached providers, in instantiation order
1.197 - private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
1.198 -
1.199 - // The current lazy-lookup iterator
1.200 - private LazyIterator lookupIterator;
1.201 -
1.202 - /**
1.203 - * Clear this loader's provider cache so that all providers will be
1.204 - * reloaded.
1.205 - *
1.206 - * <p> After invoking this method, subsequent invocations of the {@link
1.207 - * #iterator() iterator} method will lazily look up and instantiate
1.208 - * providers from scratch, just as is done by a newly-created loader.
1.209 - *
1.210 - * <p> This method is intended for use in situations in which new providers
1.211 - * can be installed into a running Java virtual machine.
1.212 - */
1.213 - public void reload() {
1.214 - providers.clear();
1.215 - lookupIterator = new LazyIterator(service, loader);
1.216 - }
1.217 -
1.218 - private ServiceLoader(Class<S> svc, ClassLoader cl) {
1.219 - service = svc;
1.220 - loader = cl;
1.221 - reload();
1.222 - }
1.223 -
1.224 - private static void fail(Class service, String msg, Throwable cause)
1.225 - throws ServiceConfigurationError
1.226 - {
1.227 - throw new ServiceConfigurationError(service.getName() + ": " + msg,
1.228 - cause);
1.229 - }
1.230 -
1.231 - private static void fail(Class service, String msg)
1.232 - throws ServiceConfigurationError
1.233 - {
1.234 - throw new ServiceConfigurationError(service.getName() + ": " + msg);
1.235 - }
1.236 -
1.237 - private static void fail(Class service, URL u, int line, String msg)
1.238 - throws ServiceConfigurationError
1.239 - {
1.240 - fail(service, u + ":" + line + ": " + msg);
1.241 - }
1.242 -
1.243 - // Parse a single line from the given configuration file, adding the name
1.244 - // on the line to the names list.
1.245 - //
1.246 - private int parseLine(Class service, URL u, BufferedReader r, int lc,
1.247 - List<String> names)
1.248 - throws IOException, ServiceConfigurationError
1.249 - {
1.250 - String ln = r.readLine();
1.251 - if (ln == null) {
1.252 - return -1;
1.253 - }
1.254 - int ci = ln.indexOf('#');
1.255 - if (ci >= 0) ln = ln.substring(0, ci);
1.256 - ln = ln.trim();
1.257 - int n = ln.length();
1.258 - if (n != 0) {
1.259 - if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
1.260 - fail(service, u, lc, "Illegal configuration-file syntax");
1.261 - int cp = ln.codePointAt(0);
1.262 - if (!Character.isJavaIdentifierStart(cp))
1.263 - fail(service, u, lc, "Illegal provider-class name: " + ln);
1.264 - for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
1.265 - cp = ln.codePointAt(i);
1.266 - if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
1.267 - fail(service, u, lc, "Illegal provider-class name: " + ln);
1.268 - }
1.269 - if (!providers.containsKey(ln) && !names.contains(ln))
1.270 - names.add(ln);
1.271 - }
1.272 - return lc + 1;
1.273 - }
1.274 -
1.275 - // Parse the content of the given URL as a provider-configuration file.
1.276 - //
1.277 - // @param service
1.278 - // The service type for which providers are being sought;
1.279 - // used to construct error detail strings
1.280 - //
1.281 - // @param u
1.282 - // The URL naming the configuration file to be parsed
1.283 - //
1.284 - // @return A (possibly empty) iterator that will yield the provider-class
1.285 - // names in the given configuration file that are not yet members
1.286 - // of the returned set
1.287 - //
1.288 - // @throws ServiceConfigurationError
1.289 - // If an I/O error occurs while reading from the given URL, or
1.290 - // if a configuration-file format error is detected
1.291 - //
1.292 - private Iterator<String> parse(Class service, URL u)
1.293 - throws ServiceConfigurationError
1.294 - {
1.295 - InputStream in = null;
1.296 - BufferedReader r = null;
1.297 - ArrayList<String> names = new ArrayList<>();
1.298 - try {
1.299 - in = u.openStream();
1.300 - r = new BufferedReader(new InputStreamReader(in, "utf-8"));
1.301 - int lc = 1;
1.302 - while ((lc = parseLine(service, u, r, lc, names)) >= 0);
1.303 - } catch (IOException x) {
1.304 - fail(service, "Error reading configuration file", x);
1.305 - } finally {
1.306 - try {
1.307 - if (r != null) r.close();
1.308 - if (in != null) in.close();
1.309 - } catch (IOException y) {
1.310 - fail(service, "Error closing configuration file", y);
1.311 - }
1.312 - }
1.313 - return names.iterator();
1.314 - }
1.315 -
1.316 - // Private inner class implementing fully-lazy provider lookup
1.317 - //
1.318 - private class LazyIterator
1.319 - implements Iterator<S>
1.320 - {
1.321 -
1.322 - Class<S> service;
1.323 - ClassLoader loader;
1.324 - Enumeration<URL> configs = null;
1.325 - Iterator<String> pending = null;
1.326 - String nextName = null;
1.327 -
1.328 - private LazyIterator(Class<S> service, ClassLoader loader) {
1.329 - this.service = service;
1.330 - this.loader = loader;
1.331 - }
1.332 -
1.333 - public boolean hasNext() {
1.334 - if (nextName != null) {
1.335 - return true;
1.336 - }
1.337 - if (configs == null) {
1.338 - try {
1.339 - String fullName = PREFIX + service.getName();
1.340 - if (loader == null)
1.341 - configs = ClassLoader.getSystemResources(fullName);
1.342 - else
1.343 - configs = loader.getResources(fullName);
1.344 - } catch (IOException x) {
1.345 - fail(service, "Error locating configuration files", x);
1.346 - }
1.347 - }
1.348 - while ((pending == null) || !pending.hasNext()) {
1.349 - if (!configs.hasMoreElements()) {
1.350 - return false;
1.351 - }
1.352 - pending = parse(service, configs.nextElement());
1.353 - }
1.354 - nextName = pending.next();
1.355 - return true;
1.356 - }
1.357 -
1.358 - public S next() {
1.359 - if (!hasNext()) {
1.360 - throw new NoSuchElementException();
1.361 - }
1.362 - String cn = nextName;
1.363 - nextName = null;
1.364 - try {
1.365 - S p = service.cast(Class.forName(cn, true, loader)
1.366 - .newInstance());
1.367 - providers.put(cn, p);
1.368 - return p;
1.369 - } catch (ClassNotFoundException x) {
1.370 - fail(service,
1.371 - "Provider " + cn + " not found");
1.372 - } catch (Throwable x) {
1.373 - fail(service,
1.374 - "Provider " + cn + " could not be instantiated: " + x,
1.375 - x);
1.376 - }
1.377 - throw new Error(); // This cannot happen
1.378 - }
1.379 -
1.380 - public void remove() {
1.381 - throw new UnsupportedOperationException();
1.382 - }
1.383 -
1.384 - }
1.385 -
1.386 - /**
1.387 - * Lazily loads the available providers of this loader's service.
1.388 - *
1.389 - * <p> The iterator returned by this method first yields all of the
1.390 - * elements of the provider cache, in instantiation order. It then lazily
1.391 - * loads and instantiates any remaining providers, adding each one to the
1.392 - * cache in turn.
1.393 - *
1.394 - * <p> To achieve laziness the actual work of parsing the available
1.395 - * provider-configuration files and instantiating providers must be done by
1.396 - * the iterator itself. Its {@link java.util.Iterator#hasNext hasNext} and
1.397 - * {@link java.util.Iterator#next next} methods can therefore throw a
1.398 - * {@link ServiceConfigurationError} if a provider-configuration file
1.399 - * violates the specified format, or if it names a provider class that
1.400 - * cannot be found and instantiated, or if the result of instantiating the
1.401 - * class is not assignable to the service type, or if any other kind of
1.402 - * exception or error is thrown as the next provider is located and
1.403 - * instantiated. To write robust code it is only necessary to catch {@link
1.404 - * ServiceConfigurationError} when using a service iterator.
1.405 - *
1.406 - * <p> If such an error is thrown then subsequent invocations of the
1.407 - * iterator will make a best effort to locate and instantiate the next
1.408 - * available provider, but in general such recovery cannot be guaranteed.
1.409 - *
1.410 - * <blockquote style="font-size: smaller; line-height: 1.2"><span
1.411 - * style="padding-right: 1em; font-weight: bold">Design Note</span>
1.412 - * Throwing an error in these cases may seem extreme. The rationale for
1.413 - * this behavior is that a malformed provider-configuration file, like a
1.414 - * malformed class file, indicates a serious problem with the way the Java
1.415 - * virtual machine is configured or is being used. As such it is
1.416 - * preferable to throw an error rather than try to recover or, even worse,
1.417 - * fail silently.</blockquote>
1.418 - *
1.419 - * <p> The iterator returned by this method does not support removal.
1.420 - * Invoking its {@link java.util.Iterator#remove() remove} method will
1.421 - * cause an {@link UnsupportedOperationException} to be thrown.
1.422 - *
1.423 - * @return An iterator that lazily loads providers for this loader's
1.424 - * service
1.425 - */
1.426 - public Iterator<S> iterator() {
1.427 - return new Iterator<S>() {
1.428 -
1.429 - Iterator<Map.Entry<String,S>> knownProviders
1.430 - = providers.entrySet().iterator();
1.431 -
1.432 - public boolean hasNext() {
1.433 - if (knownProviders.hasNext())
1.434 - return true;
1.435 - return lookupIterator.hasNext();
1.436 - }
1.437 -
1.438 - public S next() {
1.439 - if (knownProviders.hasNext())
1.440 - return knownProviders.next().getValue();
1.441 - return lookupIterator.next();
1.442 - }
1.443 -
1.444 - public void remove() {
1.445 - throw new UnsupportedOperationException();
1.446 - }
1.447 -
1.448 - };
1.449 - }
1.450 -
1.451 - /**
1.452 - * Creates a new service loader for the given service type and class
1.453 - * loader.
1.454 - *
1.455 - * @param service
1.456 - * The interface or abstract class representing the service
1.457 - *
1.458 - * @param loader
1.459 - * The class loader to be used to load provider-configuration files
1.460 - * and provider classes, or <tt>null</tt> if the system class
1.461 - * loader (or, failing that, the bootstrap class loader) is to be
1.462 - * used
1.463 - *
1.464 - * @return A new service loader
1.465 - */
1.466 - public static <S> ServiceLoader<S> load(Class<S> service,
1.467 - ClassLoader loader)
1.468 - {
1.469 - return new ServiceLoader<>(service, loader);
1.470 - }
1.471 -
1.472 - /**
1.473 - * Creates a new service loader for the given service type, using the
1.474 - * current thread's {@linkplain java.lang.Thread#getContextClassLoader
1.475 - * context class loader}.
1.476 - *
1.477 - * <p> An invocation of this convenience method of the form
1.478 - *
1.479 - * <blockquote><pre>
1.480 - * ServiceLoader.load(<i>service</i>)</pre></blockquote>
1.481 - *
1.482 - * is equivalent to
1.483 - *
1.484 - * <blockquote><pre>
1.485 - * ServiceLoader.load(<i>service</i>,
1.486 - * Thread.currentThread().getContextClassLoader())</pre></blockquote>
1.487 - *
1.488 - * @param service
1.489 - * The interface or abstract class representing the service
1.490 - *
1.491 - * @return A new service loader
1.492 - */
1.493 - public static <S> ServiceLoader<S> load(Class<S> service) {
1.494 - ClassLoader cl = null; // XXX: Thread.currentThread().getContextClassLoader();
1.495 - return ServiceLoader.load(service, cl);
1.496 - }
1.497 -
1.498 - /**
1.499 - * Creates a new service loader for the given service type, using the
1.500 - * extension class loader.
1.501 - *
1.502 - * <p> This convenience method simply locates the extension class loader,
1.503 - * call it <tt><i>extClassLoader</i></tt>, and then returns
1.504 - *
1.505 - * <blockquote><pre>
1.506 - * ServiceLoader.load(<i>service</i>, <i>extClassLoader</i>)</pre></blockquote>
1.507 - *
1.508 - * <p> If the extension class loader cannot be found then the system class
1.509 - * loader is used; if there is no system class loader then the bootstrap
1.510 - * class loader is used.
1.511 - *
1.512 - * <p> This method is intended for use when only installed providers are
1.513 - * desired. The resulting service will only find and load providers that
1.514 - * have been installed into the current Java virtual machine; providers on
1.515 - * the application's class path will be ignored.
1.516 - *
1.517 - * @param service
1.518 - * The interface or abstract class representing the service
1.519 - *
1.520 - * @return A new service loader
1.521 - */
1.522 - public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
1.523 - ClassLoader cl = ClassLoader.getSystemClassLoader();
1.524 - ClassLoader prev = null;
1.525 - while (cl != null) {
1.526 - prev = cl;
1.527 - cl = cl.getParent();
1.528 - }
1.529 - return ServiceLoader.load(service, prev);
1.530 - }
1.531 -
1.532 - /**
1.533 - * Returns a string describing this service.
1.534 - *
1.535 - * @return A descriptive string
1.536 - */
1.537 - public String toString() {
1.538 - return "java.util.ServiceLoader[" + service.getName() + "]";
1.539 - }
1.540 -
1.541 -}