1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| public final class ServiceLoader<S> implements Iterable<S> { private static final String PREFIX = "META-INF/services/"; private final Class<S> service; private final ClassLoader loader; private final AccessControlContext acc; private LinkedHashMap<String,S> providers = new LinkedHashMap<>(); private LazyIterator lookupIterator;
public void reload() { providers.clear(); lookupIterator = new LazyIterator(service, loader); }
private ServiceLoader(Class<S> svc, ClassLoader cl) { service = Objects.requireNonNull(svc, "Service interface cannot be null"); loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl; acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null; reload(); }
private int parseLine(Class<?> service, URL u, BufferedReader r, int lc, List<String> names) { String ln = r.readLine(); if (ln == null) { return -1; } int ci = ln.indexOf('#'); if (ci >= 0) ln = ln.substring(0, ci); ln = ln.trim(); int n = ln.length(); if (n != 0) { if (!providers.containsKey(ln) && !names.contains(ln)) names.add(ln); } return lc + 1; }
private Iterator<String> parse(Class<?> service, URL u) throws ServiceConfigurationError { ArrayList<String> names = new ArrayList<>(); InputStream in = u.openStream(); BufferedReader r = new BufferedReader(new InputStreamReader(in, "utf-8")); int lc = 1; while ((lc = parseLine(service, u, r, lc, names)) >= 0); return names.iterator(); }
public Iterator<S> iterator() { return new Iterator<S>() { public boolean hasNext() { return lookupIterator.hasNext(); }
public S next() { return lookupIterator.next(); }
}; }
public static <S> ServiceLoader<S> load(Class<S> service, ClassLoader loader) { return new ServiceLoader<>(service, loader); }
private class LazyIterator implements Iterator<S> { private boolean hasNextService() { if (nextName != null) { return true; } if (configs == null) { try { String fullName = PREFIX + service.getName(); if (loader == null) configs = ClassLoader.getSystemResources(fullName); else configs = loader.getResources(fullName); } catch (IOException x) { fail(service, "Error locating configuration files", x); } } while ((pending == null) || !pending.hasNext()) { if (!configs.hasMoreElements()) { return false; } pending = parse(service, configs.nextElement()); } nextName = pending.next(); return true; }
private S nextService() { String cn = nextName; nextName = null; Class<?> c = Class.forName(cn, false, loader); S p = service.cast(c.newInstance()); providers.put(cn, p); return p; } } }
|