
clime.messadmin.providers.Service Maven / Gradle / Ivy
/**
* What the hell is this doing in the sun.misc package?
* This mechanism is an official specification since Java 1.3!
*/
//package sun.misc;
package clime.messadmin.providers;
import java.io.*;
import java.net.URL;
import java.util.*;
/**
* From JDK 1.3.1 / 1.4.2 / 1.5.0
* see http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider
*
* see javax.imageio.spi.ServiceRegistry (Java 1.4+)
* see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4640520
* see http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html (Java 6)
* @author Cédrik LIME
*/
public final class Service {
private static class LazyIterator implements Iterator {
Class service;
ClassLoader loader;
Enumeration configs;
Iterator pending;
Set returned;
String nextName;
public boolean hasNext() throws ServiceConfigurationError {
if (nextName != null)
return true;
if (configs == null)
try {
String s = prefix + service.getName();
if (loader == null)
configs = ClassLoader.getSystemResources(s);
else
configs = loader.getResources(s);
} catch (IOException ioe) {
Service.fail(service, ": " + ioe);
}
for (; pending == null || !pending.hasNext();
pending = Service.parse(service, (URL) configs.nextElement(), returned)) {
if (!configs.hasMoreElements())
return false;
}
nextName = (String) pending.next();
return true;
}
public Object next() throws ServiceConfigurationError {
if (!hasNext())
throw new NoSuchElementException();
String s = nextName;
nextName = null;
try {
return Class.forName(s, true, loader).newInstance();
} catch (ClassNotFoundException cnfe) {
Service.fail(service, "Provider " + s + " not found");
} catch (Exception exception) {
Service.fail(service, "Provider " + s
+ " could not be instantiated: " + exception, exception);
}
return null;
}
public void remove() {
throw new UnsupportedOperationException();
}
private LazyIterator(Class class1, ClassLoader classloader) {
configs = null;
pending = null;
returned = new TreeSet();
nextName = null;
service = class1;
loader = classloader;
}
}
private static final String prefix = "META-INF/services/";//$NON-NLS-1$
private Service() {
}
protected static void fail(Class class1, String s) throws ServiceConfigurationError {
throw new ServiceConfigurationError(class1.getName() + ": " + s);
}
protected static void fail(Class class1, URL url, int i, String s) throws ServiceConfigurationError {
fail(class1, url + ":" + i + ": " + s);
}
/**
* @since 1.4
*/
protected static void fail(Class class1, String s, Throwable throwable) throws ServiceConfigurationError {
ServiceConfigurationError serviceconfigurationerror = new ServiceConfigurationError(
class1.getName() + ": " + s);
// serviceconfigurationerror.initCause(throwable);
throw serviceconfigurationerror;
}
private static int parseLine(Class class1, URL url,
BufferedReader bufferedreader, int i, List list, Set set)
throws IOException, ServiceConfigurationError {
String s = bufferedreader.readLine();
if (s == null)
return -1;
int j = s.indexOf('#');
if (j >= 0)
s = s.substring(0, j);
s = s.trim();
int k = s.length();
if (k != 0) {
if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0)
fail(class1, url, i, "Illegal configuration-file syntax");
if (!Character.isJavaIdentifierStart(s.charAt(0)))
fail(class1, url, i, "Illegal provider-class name: " + s);
for (int l = 1; l < k; ++l) {
char c = s.charAt(l);
if (!Character.isJavaIdentifierPart(c) && c != '.')
fail(class1, url, i, "Illegal provider-class name: " + s);
}
if (!set.contains(s)) {
list.add(s);
set.add(s);
}
}
return i + 1;
}
protected static Iterator parse(Class class1, URL url, Set set) throws ServiceConfigurationError {
InputStream inputstream = null;
BufferedReader bufferedreader = null;
ArrayList arraylist = new ArrayList();
try {
inputstream = url.openStream();
bufferedreader = new BufferedReader(new InputStreamReader(inputstream, "utf-8"));//$NON-NLS-1$
for (int i = 1; (i = parseLine(class1, url, bufferedreader, i, arraylist, set)) >= 0;)
;
} catch (IOException ioexception) {
fail(class1, ": " + ioexception);
} finally {
try {
if (bufferedreader != null)
bufferedreader.close();
if (inputstream != null)
inputstream.close();
} catch (IOException ioexception1) {
fail(class1, ": " + ioexception1);
}
}
return arraylist.iterator();
}
/**
* Lazily locates and instantiates the available providers for the given service class and class loader.
*
* @param service The interface or abstract class representing this service
* @param loader The class loader to be used to load provider-configuration files and provider classes, or null if the system class loader (or, failing that, the bootstrap class loader) is to be used
* @return An iterator that lazily locates and instantiates providers for this service
* @throws ServiceConfigurationError
*/
public static Iterator providers(Class service, ClassLoader loader) throws ServiceConfigurationError {
return new LazyIterator(service, loader);
}
/**
* Lazily locates and instantiates the available providers for the given service class, using the current thread's context class loader.
*
* An invocation of this convenience method of the form
*
*
* Service.lookup(service)
*
* is equivalent to
*
*
* Service.lookup(service,
* Thread.currentThread().getContextClassLoader())
*
* @param service The interface or abstract class representing this service
* @return An iterator that lazily locates and instantiates providers for this service
* @throws ServiceConfigurationError
*/
public static Iterator providers(Class service) throws ServiceConfigurationError {
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
return providers(service, classloader);
}
/**
* Lazily locates and instantiates the available providers for the given service class, using the extension class loader.
*
* This convenience method simply locates the extension class loader,
* call it extClassLoader, and then returns
*
*
* Service.lookup(service, extClassLoader)
*
* If the extension class loader cannot be found then the system class
* loader is used; if there is no system class loader then the bootstrap
* class loader is used.
*
*
This method is intended for use when only installed providers are
* desired. The resulting service will only find and load providers that
* have been installed into the current Java virtual machine; providers on
* the application's class path will be ignored.
*
* @param service The interface or abstract class representing this service
* @return An iterator that lazily locates and instantiates providers for this service
* @throws ServiceConfigurationError
*/
public static Iterator installedProviders(Class service) throws ServiceConfigurationError {
ClassLoader classloader = ClassLoader.getSystemClassLoader();
ClassLoader extClassLoader = null;
for (; classloader != null; classloader = classloader.getParent()) {
extClassLoader = classloader;
}
return providers(service, extClassLoader);
}
}