package org.pitest.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Constructor; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; /** * Simple java 1.6 ServiceLoader like behaviour for 1.5 From * http://stackoverflow * .com/questions/251336/is-something-similar-to-serviceloader-in-java-1-5 * */ public abstract class ServiceLoader { public static <S> Collection<S> load(final Class<S> ifc) { return load(ifc, Thread.currentThread().getContextClassLoader()); } public static <S> Collection<S> load(final Class<S> ifc, final ClassLoader loader) { try { return loadImpl(ifc, loader); } catch (final IOException ex) { throw new PitError("Error creating service " + ifc.getName(), ex); } } private static <S> Collection<S> loadImpl(final Class<S> ifc, final ClassLoader loader) throws IOException { final Enumeration<URL> e = loader.getResources("META-INF/services/" + ifc.getName()); final Collection<S> services = new ArrayList<S>(); while (e.hasMoreElements()) { final URL url = e.nextElement(); final InputStream is = url.openStream(); try { createServicesFromStream(ifc, loader, services, is); } finally { is.close(); } } return services; } private static <S> void createServicesFromStream(final Class<S> ifc, final ClassLoader loader, final Collection<S> services, final InputStream is) throws IOException { final BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8")); while (true) { String line = r.readLine(); if (line == null) { break; } final int comment = line.indexOf('#'); if (comment >= 0) { line = line.substring(0, comment); } final String name = line.trim(); if (name.length() == 0) { continue; } services.add(createService(name, ifc, loader)); } } private static <S> S createService(final String name, final Class<S> ifc, final ClassLoader loader) { try { final Class<?> clz = Class.forName(name, true, loader); final Class<? extends S> impl = clz.asSubclass(ifc); final Constructor<? extends S> ctor = impl.getConstructor(); return ctor.newInstance(); } catch (final Exception ex) { throw new PitError("Error creating service " + ifc.getName(), ex); } } }