org.hyperic.hq.hqu.RenditServerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.hqu.RenditServerImpl.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-2007], Hyperic, Inc.
 * This file is part of HQ.
 * 
 * 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.hqu;

import java.io.File;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
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.authz.server.session.AuthzSubject;
import org.hyperic.hq.authz.server.session.Resource;
import org.hyperic.hq.common.SystemException;
import org.hyperic.hq.context.Bootstrap;
import org.hyperic.hq.hqu.server.session.Attachment;
import org.hyperic.hq.hqu.server.session.UIPlugin;
import org.hyperic.hq.hqu.shared.UIPluginManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

@Service
public class RenditServerImpl implements RenditServer {
    public static final String PROP_PLUGIN_NAME = "plugin.name";
    public static final String PROP_PLUGIN_VER = "plugin.version";
    public static final String PROP_PLUGIN_APIMAJ = "plugin.apiMajor";
    public static final String PROP_PLUGIN_APIMIN = "plugin.apiMinor";

    private final Log log = LogFactory.getLog(RenditServerImpl.class);
    private final Object cfgLock = new Object();
    private Map<String, PluginWrapper> plugins = new HashMap<String, PluginWrapper>();
    private UIPluginManager uiPluginManager;

    private ClassLoader getUseLoader() {
        return RenditServerImpl.class.getClassLoader();
    }

    private PluginWrapper getPlugin(String name) {
        PluginWrapper res;

        synchronized (cfgLock) {
            res = (PluginWrapper) plugins.get(name);
        }

        if (res == null) {
            throw new IllegalArgumentException("Unknown plugin [" + name + "]");
        }
        return res;
    }

    @Transactional
    public void addPluginDir(File path) throws Exception {
        log.info("Loading plugin from [" + path + "]");

        loadPlugin(path);
    }

    public void removePluginDir(String pluginName) {
        log.info("Removing plugin [" + pluginName + "]");
        synchronized (cfgLock) {
            plugins.remove(pluginName);
        }
        UIPlugin plugin = uiPluginManager.findPluginByName(pluginName);
        if (plugin != null) {
            uiPluginManager.deletePlugin(plugin);
        }
    }

    /**
     * Loads a plugin into the rendit system, verifying the version numbers,
     * etc.
     *
     * @param path Path to the plugin
     */
    public PluginWrapper loadPlugin(final File path) throws PluginLoadException {
        try {
            return loadPluginInternal(path);
        } catch (Exception e) {
            throw new PluginLoadException(e.getMessage(), e);
        }
    }

    /**
     * Loads a plugin into the rendit system, verifying the version numbers,
     * etc.
     * 
     * @param path Path to the plugin
     */
    private PluginWrapper loadPluginInternal(final File path) throws PluginLoadException {
        final PluginWrapper plugin = new PluginWrapper(path, getUseLoader());

        try {
            plugin.loadDispatcher();
        } catch (Exception e) {
            throw new PluginLoadException("Failed to load plugin", e);
        }

        Properties props;

        try {
            props = plugin.loadPlugin();
        } catch (PluginLoadException e) {
            throw e;
        } catch (Exception e) {
            throw new PluginLoadException("Error loading plugin at [" + path.getAbsolutePath() + "]", e);
        }

        final String pluginName = props.getProperty(PROP_PLUGIN_NAME);
        final String pluginVer = props.getProperty(PROP_PLUGIN_VER);

        log.info(pluginName + " version " + pluginVer + " loaded at [" + path.getName() + "]");
        deployPlugin(plugin, path, pluginName, pluginVer);
        return plugin;
    }

    private void deployPlugin(final PluginWrapper plugin, final File path, String pluginName, String pluginVer) {
        try {
            // TODO Need to change this...this is done for short term to get past circular dependency w/ UIPluginManager
            uiPluginManager = Bootstrap.getBean(UIPluginManager.class);

            UIPlugin p = uiPluginManager.createOrUpdate(pluginName, pluginVer);
            plugin.deploy(p);
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {

                public void suspend() {
                }

                public void resume() {
                }

                public void flush() {
                }

                public void beforeCompletion() {
                }

                public void beforeCommit(boolean readOnly) {
                }

                public void afterCompletion(int status) {
                }

                public void afterCommit() {
                    synchronized (cfgLock) {
                        plugins.put(path.getName(), plugin);
                    }
                }
            });
        } catch (Exception e) {
            throw new PluginLoadException("Error loading HQU plugin [" + pluginName + "]", e);
        }
    }

    /**
     * Handles regular web requests for a UI plugin. 
     */
    public void handleRequest(String pluginName, Object request) throws Exception {
        PluginWrapper plugin = getPlugin(pluginName);
        plugin.handleRequest(request);
    }

    public AttachmentDescriptor getAttachmentDescriptor(String pluginName, Attachment a, Resource ent,
            AuthzSubject u) {
        PluginWrapper plugin = getPlugin(pluginName);
        return plugin.getAttachmentDescriptor(a, ent, u);
    }

    public Object invokeMethod(String plugin, InvokeMethodInvocationBindings b) throws Exception {
        PluginWrapper p = getPlugin(plugin);
        return p.invokeMethod(b);
    }

    /**
     * Renders a template (.gsp file) to a Writer
     * This facility relies on a plugin being registered under the name
     * 'tmpl_render' which how to deal with a render invocation from the
     * dispatcher.
     * 
     * @params template The template to render
     * @params params   Local variables to pass to the template
     * @params output   Writer to render to
     */
    public void renderTemplate(File template, Map params, Writer output) throws Exception {
        PluginWrapper plugin = getPlugin("tmpl_render");
        List args = new ArrayList();

        if (plugin == null) {
            throw new SystemException("Required plugin [tmpl_render] not " + "found");
        }

        args.add(template);
        args.add(params);
        args.add(output);
        InvokeMethodInvocationBindings b = new InvokeMethodInvocationBindings("Renderer", "render", args);

        plugin.invokeMethod(b);
    }
}