package com.redhat.ceylon.common.tool; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Set; public abstract class ServiceToolLoader extends ToolLoader { private final Class<?> serviceClass; private PathPlugins pathPlugins = new PathPlugins(); private List<String> toolClassNames; public ServiceToolLoader(Class<?> serviceClass) { super(); this.serviceClass = serviceClass; } public ServiceToolLoader(ClassLoader loader, Class<?> serviceClass) { super(loader); this.serviceClass = serviceClass; } protected Enumeration<URL> getServiceMeta() { /* Use the same conventions as java.util.ServiceLoader but without * requiring us to load the Service classes */ Enumeration<URL> resources; try { resources = loader.getResources("META-INF/services/"+serviceClass.getName()); } catch (IOException e) { throw new ToolException(e); } return resources; } private List<String> parseServiceInfo(final URL url) { List<String> result = new ArrayList<>(); try { URLConnection con = url.openConnection(); con.setUseCaches(false); final BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8")); try { String className = reader.readLine(); while (className != null) { className = className.trim().replaceAll("#.*", ""); if (!className.isEmpty()) { result.add(className); } className = reader.readLine(); } } finally { reader.close(); } } catch (IOException e) { throw new ToolException("Error reading service file " + url, e); } return result; } @Override protected synchronized Iterable<String> toolClassNames() { if (toolClassNames == null) { List<String> result = new ArrayList<>(); Enumeration<URL> urls = getServiceMeta(); while (urls.hasMoreElements()) { result.addAll(parseServiceInfo(urls.nextElement())); } result.addAll(getPathPlugins()); toolClassNames = Collections.unmodifiableList(result); } return toolClassNames; } protected Set<String> getPathPlugins() { return pathPlugins.getPathPlugins(); } }