package com.dgrid.service.impl; import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.dgrid.api.JobletTypeHandler; import com.dgrid.errors.TransportException; import com.dgrid.gen.InvalidApiKey; import com.dgrid.gen.InvalidHost; import com.dgrid.handlers.UnknownJobletTypeHandler; import com.dgrid.helpers.PropertyConfigurator; import com.dgrid.plugin.JavaPluginsPlugin; import com.dgrid.plugin.Plugin; import com.dgrid.plugin.PluginContext; import com.dgrid.plugin.PluginManager; import com.dgrid.service.DGridClient; import com.dgrid.service.DGridPluginContext; import com.dgrid.service.DGridPluginManager; public class DGridPluginManagerImpl implements PluginManager, DGridPluginManager { private Log log = LogFactory.getLog(getClass()); private Hashtable<String, Plugin> plugins = new Hashtable<String, Plugin>(); private HashMap<String, JobletTypeHandler> typeHandlers = new HashMap<String, JobletTypeHandler>(); private DGridPluginContext context; private PropertyConfigurator props; public void setPluginContext(PluginContext context) { this.context = (DGridPluginContext) context; } public void setPropertyConfigurator(PropertyConfigurator props) { this.props = props; } public void init() { log.trace("init()"); safeLoadPlugin(JavaPluginsPlugin.class); } public void start() { log.trace("start()"); startPlugins(); } public void stop() { log.trace("stop()"); for (Plugin plugin : plugins.values()) { try { plugin.stop(); } catch (Exception e) { log.warn(String.format( "Exception calling stop() on plugin (%1$s)", plugin)); } } } public Plugin loadPlugin(Plugin plugin) { log.trace("loadPlugin()"); initPlugin(plugin); return plugin; } public void unloadPlugin(String identifier) { log.trace("unloadPlugin()"); Plugin p = plugins.get(identifier); if (p != null) { p.stop(); plugins.remove(identifier); } } public Collection<Plugin> list() { log.trace("list()"); return plugins.values(); } public Plugin getPlugin(String identifier) { return plugins.get(identifier); } public String getProperty(String key) { log.trace("getProperty()"); try { return props.getProperty(key); } catch (IOException e) { log.error("IOException in getProperty()", e); return null; } } public void setJobletTypeHandler(String type, JobletTypeHandler handler) { log.trace("setJobletTypeHandler()"); if (log.isDebugEnabled()) { log.debug(String.format("Adding type (%1$s) with class (%2$s)", type, handler)); } typeHandlers.put(type, handler); } public JobletTypeHandler getJobletTypeHandler(String type) { log.trace("getJobletTypeHandler()"); JobletTypeHandler h = typeHandlers.get(type); if (h == null) { return new UnknownJobletTypeHandler(); } else { return h; } } public void removeJobletTypeHandler(String type) { log.trace("removeJobletTypeHandler()"); if (typeHandlers.containsKey(type)) { typeHandlers.remove(type); } } private void startPlugin(Plugin plugin) { log.trace("startPlugin()"); if (log.isDebugEnabled()) { log.debug(String.format("Loading plugin class (%1$s)", plugin .getClass().getName())); log.debug(String.format("Identifier: (%1$s)", plugin .getIdentifier())); log.debug(String.format("Name: (%1$s)", plugin.getName())); log.debug(String.format("Description: (%1$s)", plugin .getDescription())); } plugin.start(); } private void safeLoadPlugin(Class cls) { log.trace("safeLoadPlugin()"); try { Object obj = cls.newInstance(); Plugin plugin = (Plugin) obj; initPlugin(plugin); } catch (Exception e) { log.warn(String.format("Could not plugin from class %1$s", cls), e); } finally { } } private void startPlugins() { log.trace("startPlugins()"); // because plugins can add other plugins (and thus add to our plugins // hashtable) // we need to snapshot the list and iterate over the snapshot, // avoiding java.util.ConcurrentModificationException errors. Hashtable<String, Plugin> clone = (Hashtable<String, Plugin>) plugins .clone(); for (Iterator<Plugin> iter = clone.values().iterator(); iter.hasNext();) { Plugin p = iter.next(); try { startPlugin(p); } catch (Exception e) { log .warn(String .format( "Could not start plugin with identifier (%1$s). It will be disabled.", p.getIdentifier())); log.warn("Could not start plugin", e); plugins.remove(p.getIdentifier()); } } } private void initPlugin(Plugin plugin) { log.trace("initPlugin()"); if (plugins.containsKey(plugin.getIdentifier())) { if (log.isDebugEnabled()) { log.debug(String.format("Removing old plugin %1$s", plugin .getIdentifier())); } Plugin old = plugins.get(plugin.getIdentifier()); old.stop(); plugins.remove(old.getIdentifier()); } try { if (enabled(plugin)) { plugin.setPluginContext(context); plugin.setPluginManager(this); plugin.init(); plugins.put(plugin.getIdentifier(), plugin); } } catch (Exception e) { log.trace("Exception in initPlugin()", e); } } private boolean enabled(Plugin plugin) throws TransportException, InvalidApiKey, InvalidHost { log.trace("enabled()"); String setting = String.format("plugin.%1$s.enable", plugin .getIdentifier()); DGridClient gridClient = context.getGridClient(); boolean systemEnabled = Boolean.parseBoolean(gridClient.getSetting( setting, Boolean.toString(plugin.enabledByDefault()))); if ((systemEnabled) && (Boolean.parseBoolean(gridClient.getHostSetting(gridClient .getHost().getId(), setting, Boolean .toString(systemEnabled))))) { return true; } else return false; } }