org.hyperic.hq.product.PluginManager.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.product.PluginManager.java

Source

/*
 * NOTE: This copyright does *not* cover user programs that use HQ
 * program services by normal system calls through the application
 * program interfaces provided as part of the Hyperic Plug-in Development
 * Kit or the Hyperic Client Development Kit - this is merely considered
 * normal use of the program, and does *not* fall under the heading of
 * "derived work".
 * 
 * Copyright (C) [2004-2010], VMware, Inc.
 * This file is part of Hyperic.
 * 
 * HQ is free software; you can redistribute it and/or modify
 * it under the terms version 2 of the GNU General Public License as
 * published by the Free Software Foundation. This program is distributed
 * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 */

package org.hyperic.hq.product;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.product.pluginxml.PluginData;
import org.hyperic.util.PluginLoader;
import org.hyperic.util.config.ConfigResponse;
import org.hyperic.util.config.ConfigSchema;

/**
 * This class implements common functionality of the GenericPluginManager
 * interface:
 * - maintain a registry of plugins
 * - shutdown() propagated to all plugins
 */
public abstract class PluginManager {
    private final String OS;
    private final String OS_SUFFIX;

    protected Map<String, GenericPlugin> plugins = Collections
            .synchronizedMap(new HashMap<String, GenericPlugin>());
    private Map pluginInfo = Collections.synchronizedMap(new HashMap());
    private Properties props = null;
    protected Log log = null;
    private PluginManager parent = null;

    public PluginManager() {
        this(new Properties());
    }

    public PluginManager(Properties props) {
        log = LogFactory.getLog(this.getClass().getName());
        this.props = props;
        OS = HypericOperatingSystem.getInstance().getName();
        OS_SUFFIX = " " + OS;
    }

    public abstract String getName();

    public void init(PluginManager parent) throws PluginException {
        if (ProductPluginManager.DEBUG_LIFECYCLE) {
            log.debug("init " + getName());
        }
        this.parent = parent;
    }

    public void shutdown() throws PluginException {

        synchronized (plugins) {
            for (Map.Entry<String, GenericPlugin> entry : this.plugins.entrySet()) {
                GenericPlugin plugin = entry.getValue();

                try {
                    plugin.shutdown();
                } catch (PluginException e) {
                    log.error(plugin.getName() + ".shutdown() failed", e);
                }
            }

            this.plugins.clear();
        }

        if (ProductPluginManager.DEBUG_LIFECYCLE) {
            log.debug("shutdown");
        }
    }

    public Properties getProperties() {
        return this.props;
    }

    public String getProperty(String key, String defVal) {
        return getProperties().getProperty(key, defVal);
    }

    public String getProperty(String key) {
        return getProperty(key, System.getProperty(key));
    }

    public boolean isPropertyEnabled(String key, boolean defVal) {
        String val = getProperty(key);
        if (val == null) {
            return defVal;
        }
        return "true".equals(val);
    }

    public boolean isPropertyEnabled(String key) {
        return isPropertyEnabled(key, false);
    }

    public PluginManager getParent() {
        return this.parent;
    }

    protected void mergeConfigSchema(PluginManager pm, ConfigSchema schema, TypeInfo info, ConfigResponse config) {
        try {
            GenericPlugin plugin = pm.getPlugin(info.getName());
            List options = plugin.getConfigSchema(info, config).getOptions();
            schema.addOptions(options);
        } catch (PluginNotFoundException e) {
            //ok
        }
    }

    //XXX PluginLoader.setClassLoader here?
    public ConfigSchema getConfigSchema(String plugin, TypeInfo info, ConfigResponse config)
            throws PluginNotFoundException {

        return getPlugin(plugin).getConfigSchema(info, config);
    }

    public ConfigSchema getConfigSchema(String pluginName, String platformName, String typeName, TypeInfo info,
            ConfigResponse config) throws PluginNotFoundException {

        String fullTypeName = typeName.equals(platformName) ? platformName : (typeName + " " + platformName);

        return getConfigSchema(fullTypeName, info, config);
    }

    private String getServicePluginImpl(GenericPlugin plugin) {
        return plugin.getTypeProperty("SERVICE_" + getName().toUpperCase() + "_PLUGIN");
    }

    private GenericPlugin getPluginExtension(String name) {
        String platformName = name;
        boolean isPlatformPlugin = false;
        if (name.endsWith(OS_SUFFIX)) {
            //XXX bleh.
            isPlatformPlugin = true;
            name = name.substring(0, name.length() - OS_SUFFIX.length());
        }
        PluginData.ServiceExtension ext = PluginData.getServiceExtension(name);
        if (ext == null) {
            return null;
        }

        ServiceTypeInfo service = ext.service;
        String serverName = service.getServerName();
        GenericPlugin serverPlugin;
        String msg = " plugin for service '" + name + "' from server '" + serverName + "'";

        try {
            serverPlugin = getPlugin(serverName);
            log.debug("Created" + msg);
        } catch (PluginNotFoundException e) {
            log.debug("PluginNotFound creating" + msg);
            return null;
        }

        String implClass = ext.data.getPlugin(getName(), service.getName());

        if (implClass == null) {
            String defaultImpl = getServicePluginImpl(serverPlugin);

            //did not configure <plugin type="$type" class"..."/>
            if (getName().equals(ProductPlugin.TYPE_MEASUREMENT)) {
                //only default measurement plugin to the server's
                //very unlikely the server control plugin will work
                //for a service.
                if (defaultImpl == null) {
                    implClass = serverPlugin.getClass().getName();
                } else {
                    implClass = defaultImpl;
                }
            } else if (getName().equals(ProductPlugin.TYPE_CONTROL)) {
                //allow server types to define the default service impl
                //<property name="SERVICE.CONTROL"
                //          value="${package}.JBossServiceControlPlugin"/>
                if (ext.data.getControlActions(service.getName()) != null) {
                    implClass = defaultImpl;
                }
            } else {
                return null;
            }
        }

        if (implClass == null) {
            return null;
        }

        log.debug("Using " + implClass + " " + getName() + " plugin from " + serverPlugin.getName() + " for "
                + service.getName());

        String[] mergeProps = { MeasurementPlugin.PROP_TEMPLATE_CONFIG, };

        for (int i = 0; i < mergeProps.length; i++) {
            String key = mergeProps[i];
            String value = ext.data.getProperty(key);
            if (value == null) {
                value = serverPlugin.data.getProperty(key);
                if (value != null) {
                    ext.data.setProperty(key, value);
                }
            }
        }

        //create instance of the plugin using the server type's ClassLoader
        GenericPlugin plugin = ProductPlugin.getPlugin(serverPlugin, implClass, getName(), service);

        if (plugin == null) {
            log.error("Failed to create " + msg);
            return null;
        }

        ProductPluginManager ppm = (ProductPluginManager) getParent();

        plugin.data = ext.data;
        plugin.setName(service.getName());
        plugin.setTypeInfo(service);
        //setPluginInfo from the ProductPlugin
        String productName = plugin.data.getName();
        PluginInfo info = ppm.getPluginInfo(productName);
        setPluginInfo(plugin.getName(), info);

        try {
            ppm.registerTypePlugin(this, info, plugin, service);
        } catch (PluginExistsException e) {
            log.debug("PluginExists creating" + msg);
            return null;
        }

        if (isPlatformPlugin) {
            return this.plugins.get(platformName);
        }
        return plugin;
    }

    public GenericPlugin getPlugin(String name) throws PluginNotFoundException {

        GenericPlugin plugin = this.plugins.get(name);
        if (plugin == null) {
            if (name != null && ((plugin = getPluginExtension(name)) != null)) {
                return plugin;
            }
            String msg = getName() + " plugin name=" + name + " not found";
            throw new PluginNotFoundException(msg);
        }

        return plugin;
    }

    public GenericPlugin getPlatformPlugin(String name) throws PluginNotFoundException {

        return getPlugin(name + OS_SUFFIX);
    }

    public GenericPlugin getPlatformPlugin(String os, String name) throws PluginNotFoundException {

        return getPlugin(name + " " + os);
    }

    public void removePlugin(String name) throws PluginException, PluginNotFoundException {

        if (ProductPluginManager.DEBUG_LIFECYCLE) {
            log.debug("removePlugin=" + name);
        }

        GenericPlugin plugin = getPlugin(name);
        this.plugins.remove(name);

        try {
            plugin.shutdown();
        } catch (PluginException e) {
            throw new PluginException(e.getMessage(), e);
        }
    }

    public boolean isRegistered(String name) {
        return this.plugins.get(name) != null;
    }

    public void registerPlugin(GenericPlugin plugin) throws PluginException, PluginExistsException {

        registerPlugin(plugin, null);
    }

    public void registerPlugin(String name, GenericPlugin plugin) throws PluginException, PluginExistsException {

        plugin.setName(name);
        registerPlugin(plugin);
    }

    public void registerPlugin(GenericPlugin plugin, ConfigResponse response)
            throws PluginException, PluginExistsException {

        String pluginName = plugin.getName();

        if ((pluginName == null) || (pluginName.length() < 1)) {
            String msg = "malformed name '" + pluginName + "' for plugin instance: " + plugin.getClass().getName();
            throw new PluginException(msg);
        }

        if (this.plugins.get(pluginName) != null) {
            throw new PluginExistsException("Plugin name=" + pluginName + " already exists");
        }

        //put before init() since init() may register a proxy
        //who's init() method checks if the proxy is alredy registered 
        this.plugins.put(pluginName, plugin);

        boolean setClassLoader = PluginLoader.setClassLoader(plugin);

        try {
            plugin.init(this);

            if (response != null) {
                plugin.configure(response);
            }
        } catch (PluginException e) {
            this.plugins.remove(pluginName);
            throw e;
        } finally {
            if (setClassLoader) {
                PluginLoader.resetClassLoader(plugin);
            }
        }

        if (ProductPluginManager.DEBUG_LIFECYCLE) {
            log.debug("registerPlugin=" + pluginName);
        }
    }

    public void updatePlugin(GenericPlugin plugin, ConfigResponse response)
            throws PluginException, PluginNotFoundException {

        if (ProductPluginManager.DEBUG_LIFECYCLE) {
            log.debug("updatePlugin=" + plugin.getName());
        }

        removePlugin(plugin.getName());

        try {
            registerPlugin(plugin, response);
        } catch (PluginExistsException e) {
            //this will never happen.
            throw new PluginException("plugin was not removed?");
        }
    }

    public GenericPlugin createPlugin(String name, String type, ConfigResponse config)
            throws PluginException, PluginExistsException, PluginNotFoundException {

        return createPlugin(name, getPlugin(type), config);
    }

    public GenericPlugin createPlugin(String name, GenericPlugin pluginType)
            throws PluginException, PluginExistsException {

        return createPlugin(name, pluginType, null);
    }

    public GenericPlugin createPlugin(String name, GenericPlugin pluginType, ConfigResponse config)
            throws PluginException, PluginExistsException {

        GenericPlugin plugin;

        try {
            plugin = pluginType.getClass().newInstance();
        } catch (Exception e) {
            throw new PluginException(e.getMessage(), e);
        }

        plugin.data = pluginType.data;
        plugin.setName(name);
        plugin.setPluginVersion(pluginType.getPluginVersion());
        plugin.setTypeInfo(pluginType.getTypeInfo());

        registerPlugin(plugin, config);

        PluginInfo info = getPluginInfo(pluginType.getName());
        if (info != null) {
            setPluginInfo(name, new PluginInfo(name, info));
        }

        return plugin;
    }

    public Map<String, GenericPlugin> getPlugins() {
        return this.plugins;
    }

    /**
     * @return Map of plugins registered for the given platform.
     */
    public Map getPlatformPlugins(String os) {
        os = " " + os;
        HashMap found = new HashMap();

        Map plugins = getPlugins();

        synchronized (plugins) {
            for (Iterator it = plugins.entrySet().iterator(); it.hasNext();) {
                Map.Entry entry = (Map.Entry) it.next();
                String name = (String) entry.getKey();

                if (name.endsWith(os)) {
                    found.put(name, entry.getValue());
                }
            }
        }

        return found;
    }

    /**
     * @return Map of plugins registered for the current platform.
     */
    public Map getPlatformPlugins() {
        return getPlatformPlugins(OS);
    }

    //match all plugins instances from the same jar
    public List getPlugins(PluginInfo info) {
        ArrayList found = new ArrayList();

        synchronized (pluginInfo) {
            for (Iterator it = this.pluginInfo.entrySet().iterator(); it.hasNext();) {
                Map.Entry entry = (Map.Entry) it.next();
                PluginInfo pi = (PluginInfo) entry.getValue();

                if (pi.matches(info)) {
                    found.add(pi.name);
                }
            }
        }

        return found;
    }

    public void setPluginInfo(String name, PluginInfo info) {
        this.pluginInfo.put(name, info);
    }

    public PluginInfo getPluginInfo(String name) {
        return (PluginInfo) this.pluginInfo.get(name);
    }

    protected String classNotFoundMessage(NoClassDefFoundError e) {
        return "Plugin class not found: " + e.getMessage() + " (invalid classpath or corrupt plugin jar)";
    }

}