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