package org.jvnet.lafplugin; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.Enumeration; import java.util.HashSet; import java.util.Set; /** * Plugin manager for look-and-feels. * * @author Kirill Grouchnikov * @author Erik Vickroy * @author Robert Beeger * @author Frederic Lavigne * @author Pattrick Gotthardt */ public class PluginManager { private String mainTag; private String pluginTag; private String xmlName; private Set plugins; /** * Simple constructor. * * @param xmlName * The name of XML file that contains plugin configuration. * @param mainTag * The main tag in the XML configuration file. * @param pluginTag * The tag that corresponds to a single plugin kind. Specifies * the plugin kind that will be located in * {@link #getAvailablePlugins(boolean)}. */ public PluginManager(String xmlName, String mainTag, String pluginTag) { this.xmlName = xmlName; this.mainTag = mainTag; this.pluginTag = pluginTag; this.plugins = null; } // protected String getPluginClass(URL pluginUrl) { // InputStream is = null; // try { // DocumentBuilder builder = DocumentBuilderFactory.newInstance() // .newDocumentBuilder(); // is = pluginUrl.openStream(); // Document doc = builder.parse(is); // Node root = doc.getFirstChild(); // if (!this.mainTag.equals(root.getNodeName())) // return null; // NodeList children = root.getChildNodes(); // for (int i = 0; i < children.getLength(); i++) { // Node child = children.item(i); // if (!this.pluginTag.equals(child.getNodeName())) // continue; // if (child.getChildNodes().getLength() != 1) // return null; // Node text = child.getFirstChild(); // if (text.getNodeType() != Node.TEXT_NODE) // return null; // return text.getNodeValue(); // } // return null; // } catch (Exception exc) { // return null; // } finally { // if (is != null) { // try { // is.close(); // } catch (Exception e) { // } // } // } // } // protected String getPluginClass(URL pluginUrl) { InputStream is = null; InputStreamReader isr = null; try { XMLElement xml = new XMLElement(); is = pluginUrl.openStream(); isr = new InputStreamReader(is); xml.parseFromReader(isr); if (!this.mainTag.equals(xml.getName())) return null; Enumeration children = xml.enumerateChildren(); while (children.hasMoreElements()) { XMLElement child = (XMLElement) children.nextElement(); if (!this.pluginTag.equals(child.getName())) continue; if (child.countChildren() != 0) return null; return child.getContent(); } return null; } catch (Exception exc) { return null; } finally { if (isr != null) { try { isr.close(); } catch (Exception e) { } } if (is != null) { try { is.close(); } catch (Exception e) { } } } } protected Object getPlugin(URL pluginUrl) throws Exception { String pluginClassName = this.getPluginClass(pluginUrl); if (pluginClassName == null) return null; Class pluginClass = Class.forName(pluginClassName); if (pluginClass == null) return null; Object pluginInstance = pluginClass.newInstance(); if (pluginInstance == null) return null; return pluginInstance; } /** * Returns a collection of all available plugins. * * @return Collection of all available plugins. The classpath is scanned * only once. * @see #getAvailablePlugins(boolean) */ public Set getAvailablePlugins() { return this.getAvailablePlugins(false); } /** * Returns a collection of all available plugins. The parameter specifies * whether the classpath should be rescanned or whether to return the * already found plugins (after first-time scan). * * @param toReload * If <code>true</code>, the classpath is scanned for * available plugins every time <code>this</code> function is * called. If <code>false</code>, the classpath scan is * performed only once. The consecutive calls return the cached * result. * @return Collection of all available plugins. */ public Set getAvailablePlugins(boolean toReload) { if (toReload && (this.plugins != null)) return this.plugins; this.plugins = new HashSet(); ClassLoader cl = PluginManager.class.getClassLoader(); try { Enumeration urls = cl.getResources(this.xmlName); while (urls.hasMoreElements()) { URL pluginUrl = (URL) urls.nextElement(); Object pluginInstance = this.getPlugin(pluginUrl); if (pluginInstance != null) this.plugins.add(pluginInstance); } } catch (Exception exc) { return null; } return plugins; } }