001 /* ServiceLoader.java -- Allows loading of plug-in services. 002 Copyright (C) 2006, 2007 Free Software Foundation 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 package java.util; 039 040 import gnu.classpath.ServiceFactory; 041 042 /** 043 * <p> 044 * Facilities for loading service providers. A service is 045 * defined by a set of interfaces or abstract classes, and 046 * a service provider gives a concrete implementation of this. 047 * Service providers may be installed as part of the runtime 048 * environment using JAR files in the extension directories, 049 * or may be simply supplied on the classpath. 050 * </p> 051 * <p> 052 * In terms of loading a service, the service is defined by 053 * a single interface or abstract class which the provider 054 * implements. This may not constitute the entire service, 055 * but is simply a mechanism by which a provider of the 056 * service can be loaded and its capabilities determined. 057 * The variety of possible services means that no more 058 * requirements are made of the service provider other than 059 * that it must have an accessible zero argument constructor 060 * in order to allow an instance to be created. 061 * </p> 062 * <p> 063 * Service providers are listed in a file named after the 064 * service type in the directory <code>META-INF/services</code>. 065 * The file contains a list of classes, and must be encoded 066 * using UTF-8. Whitespace is ignored. Comments can be 067 * included by using a <code>'#'</code> prefix; anything occurring 068 * on the same line after this symbol is ignored. Duplicate classes 069 * are ignored. 070 * </p> 071 * <p> 072 * The classes are loaded using the same classloader that was 073 * queried in order to locate the configuration file. As a result, 074 * the providers do not need to reside in the same JAR file as the 075 * resource; they merely have to be accessible to this classloader, 076 * which may differ from the one that loaded the file itself. 077 * </p> 078 * <p> 079 * Providers are located and instantiated lazily, as calls to the 080 * {@link #iterator()} are made. Providers are cached, and those in 081 * the cache are returned first. The cache may be cleared by calling 082 * {@link #reload()}. Service loaders always execute in the security 083 * context of the caller, so ideally calls should be made from a trusted 084 * source. 085 * </p> 086 * <p> 087 * Note that this class is not thread-safe, and that strange errors may 088 * occur as the result of the use of remote URLs occurring on the classpath, 089 * which lead to erroneous web pages. 090 * </p> 091 * 092 * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 093 * @since 1.6 094 */ 095 public final class ServiceLoader<S> 096 implements Iterable<S> 097 { 098 099 /** 100 * The class of the service provider. 101 */ 102 private Class<S> spi; 103 104 /** 105 * The class loader for the service provider. 106 */ 107 private ClassLoader loader; 108 109 /** 110 * The cache of service providers. 111 */ 112 private List<S> cache; 113 114 /** 115 * The {@link gnu.classpath.ServiceFactory} iterator 116 * from which providers are obtained. 117 */ 118 private Iterator<S> serviceIt; 119 120 /** 121 * Constructs a new {@link ServiceLoader} with 122 * the specified provider and class loader. 123 * 124 * @param spi the service to load. 125 * @param loader the class loader to use. 126 */ 127 private ServiceLoader(Class<S> spi, ClassLoader loader) 128 { 129 this.spi = spi; 130 this.loader = loader; 131 cache = new ArrayList<S>(); 132 } 133 134 /** 135 * Lazily loads the available providers. The iterator first returns 136 * providers from the cache, in instantiation order, followed by any 137 * remaining providers, which are added to the cache after loading. 138 * The actual loading and parsing of the configuration file takes 139 * place in the {@link Iterator#hasNext()} and {@link Iterator#next()} 140 * methods, which means that they may result in a 141 * {@link ServiceConfigurationError} being thrown. If such an error 142 * does occur, subsequent invocations will attempt to recover. 143 * The {@link remove()} method is not supported and instead throws 144 * an {@link UnsupportedOperationException}. 145 * 146 * @return an iterator that lazily loads service providers. 147 */ 148 public Iterator<S> iterator() 149 { 150 return new Iterator<S>() 151 { 152 /** 153 * The cache iterator. 154 */ 155 private Iterator<S> cacheIt = cache.iterator(); 156 157 public boolean hasNext() 158 { 159 if (cacheIt.hasNext()) 160 return true; 161 if (serviceIt == null) 162 serviceIt = 163 ServiceFactory.lookupProviders(spi, loader, true); 164 return serviceIt.hasNext(); 165 } 166 167 public S next() 168 { 169 if (cacheIt.hasNext()) 170 return cacheIt.next(); 171 if (serviceIt == null) 172 serviceIt = 173 ServiceFactory.lookupProviders(spi, loader, true); 174 S nextService = serviceIt.next(); 175 cache.add(nextService); 176 return nextService; 177 } 178 179 public void remove() 180 { 181 throw new UnsupportedOperationException(); 182 } 183 }; 184 } 185 186 /** 187 * Creates a new service loader for the given service, 188 * using the context class loader of the current thread. 189 * This is equivalent to calling <code>ServiceLoader.load(service, 190 * Thread.currentThread().getContextClassLoader())</code>. 191 * 192 * @param service the interface or abstract class that represents 193 * the service. 194 * @return a new {@link ServiceLoader} instance. 195 */ 196 public static <S> ServiceLoader<S> load(Class<S> service) 197 { 198 return load(service, 199 Thread.currentThread().getContextClassLoader()); 200 } 201 202 /** 203 * Creates a new service loader for the given service, 204 * using the specified class loader. The class loader is 205 * used to access the configuration file and the service 206 * provider instances themselves. If the loader is 207 * <code>null</code>, the system class loader (or, if 208 * this is also <code>null</code>, the bootstrap class 209 * loader). 210 * 211 * @param service the interface or abstract class that represents 212 * the service. 213 * @param loader the class loader used to load the configuration 214 * file and service providers. 215 * @return a new {@link ServiceLoader} instance. 216 */ 217 public static <S> ServiceLoader<S> load(Class<S> service, 218 ClassLoader loader) 219 { 220 if (loader == null) 221 loader = ClassLoader.getSystemClassLoader(); 222 return new ServiceLoader(service, loader); 223 } 224 225 /** 226 * Creates a new service loader for the given service, 227 * using the extension class loader. If the extension 228 * class loader can not be found, the system class loader 229 * is used (or, if this is <code>null</code>, the 230 * bootstrap class loader). The primary use of this method 231 * is to only obtain installed services, ignoring any which 232 * may appear on the classpath. This is equivalent to calling 233 * <code>load(service, extClassLoader)</code> where 234 * <code>extClassLoader</code> is the extension class loader 235 * (or <code>null</code> if this is unavailable). 236 * 237 * @param service the interface or abstract class that represents 238 * the service. 239 * @return a new {@link ServiceLoader} instance. 240 */ 241 public static <S> ServiceLoader<S> loadInstalled(Class<S> service) 242 { 243 /* We expect the extension class loader to be the parent 244 * of the system class loader, as in 245 * ClassLoader.getDefaultSystemClassLoader() */ 246 return load(service, 247 ClassLoader.getSystemClassLoader().getParent()); 248 } 249 250 /** 251 * Clears the cache of the provider, so that all providers 252 * are again read from the configuration file and instantiated. 253 */ 254 public void reload() 255 { 256 cache.clear(); 257 } 258 259 /** 260 * Returns a textual representation of this 261 * {@link ServiceLoader}. 262 * 263 * @return a textual representation of the 264 * service loader. 265 */ 266 public String toString() 267 { 268 return getClass().getName() + 269 "[spi=" + spi + 270 ",loader=" + loader + 271 "]"; 272 } 273 274 }