package ie.dcu.plugin; import java.io.*; import java.net.*; import java.util.*; import org.xml.sax.*; import org.xml.sax.helpers.*; public class PluginLoader { public static final String SPECFILE = "plugin.xml"; private final File root; private final Map metadata; private final List jarFiles; private URLClassLoader pluginClassLoader; public PluginLoader(File root) { this.root = root; this.metadata = new HashMap(); this.jarFiles = new ArrayList(); // Extract plugin name String name = root.getName(); int idx = name.lastIndexOf('.'); if (idx > 1) { name = name.substring(0, idx); } metadata.put("name", name); } public File getRootFolder() { return root; } public File getSpecFile() { return new File(root, SPECFILE); } public Map getMetadata() { return metadata; } public String getMetaValue(String key) { return metadata.get(key); } public Plugin load() throws PluginException { try { loadMetadata(); loadJars(); return new Plugin(root, metadata, pluginClassLoader); } catch (SAXException e) { throw new PluginException(e); } catch (IOException e) { throw new PluginException(e); } } public Class loadClass(String name) throws ClassNotFoundException { if (pluginClassLoader == null) { throw new IllegalStateException("load() not called"); } return pluginClassLoader.loadClass(name); } private void addJarFile(String path) throws MalformedURLException { jarFiles.add(new JarResource(root, path)); } private void addMetadata(String key, String value) { metadata.put(key, value); } private void loadMetadata() throws SAXException, IOException { BufferedReader reader = new BufferedReader( new FileReader(getSpecFile())); try { InputSource source = new InputSource(reader); XMLReader xmlreader = XMLReaderFactory.createXMLReader(); xmlreader.setContentHandler(new SaxHandler()); xmlreader.parse(source); } finally { reader.close(); } } private void loadJars() { URL[] jarUrls = new URL[jarFiles.size()]; int i = 0; for (JarResource resource : jarFiles) { jarUrls[i++] = resource.url; } ClassLoader parent = getClass().getClassLoader(); pluginClassLoader = new PluginClassLoader(root, jarUrls, parent); } private class SaxHandler extends DefaultHandler { private Attributes attrs; private String elem; String getMandatoryAttribute(String name) throws SAXException { String value = attrs.getValue(name); if (value == null) { exception("Missing mandatory attribute '%s'", name); } return value; } private void exception(String message, Object ... args) throws SAXException { String a = String.format(message, args); String m = String.format("In element <%s>: %s", elem, a); throw new SAXException(m); } public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { elem = name; attrs = attributes; parseElem(); } private void parseElem() throws SAXException { if (elem.equals("meta")) { String name = getMandatoryAttribute("name"); String value = getMandatoryAttribute("value"); addMetadata(name, value); } else if (elem.equals("jar")) { String path = getMandatoryAttribute("file"); try { addJarFile(path); } catch (MalformedURLException e) { throw new SAXException(e); } } else { // Ignore other elements } } } } class JarResource { public final File file; public final URI uri; public final URL url; public JarResource(File root, String path) throws MalformedURLException { if (new File(path).isAbsolute()) { this.file = new File(path); } else { this.file = new File(root, path); } uri = file.toURI(); url = uri.toURL(); } }