it.jnrpe.plugins.factory.CPluginFactory.java Source code

Java tutorial

Introduction

Here is the source code for it.jnrpe.plugins.factory.CPluginFactory.java

Source

/*
 * Copyright (c) 2008 Massimiliano Ziccardi
 *  
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */
package it.jnrpe.plugins.factory;

import it.jnrpe.plugins.CPluginProxy;
import it.jnrpe.plugins.IPluginInterface;
import it.jnrpe.utils.CStreamManager;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.digester.Digester;
import org.apache.commons.digester.xmlrules.DigesterLoader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * This class instantiate the plugin classes.
 * 
 * @author Massimiliano Ziccardi
 */
public class CPluginFactory {
    private Log m_Logger = LogFactory.getLog(CPluginFactory.class);
    private static CPluginFactory m_Instance = null;
    private Map m_mPlugins = new HashMap();

    private class CPluginData {
        private String m_sClassName = null;
        private String m_sPluginName = null;
        private COptions m_opts = null;
        private String m_sDescription = null;

        private CPluginData(String sPluginName, String sDescription, String sPluginClassName, COptions opts) {
            m_sClassName = sPluginClassName;
            m_sPluginName = sPluginName;
            m_opts = opts;
            m_sDescription = sDescription;
        }

        public IPluginInterface getPluginInstance() throws PluginInstantiationException {
            try {
                //Thread.currentThread().setContextClassLoader(m_classLoader); // BUG #2814844
                return (IPluginInterface) CPluginData.class.getClassLoader().loadClass(m_sClassName).newInstance();
            } catch (Exception e) {
                throw new PluginInstantiationException("UNABLE TO INSTANTIATE PLUGIN " + m_sPluginName, e);
            }
        }

        public COptions getOptions() {
            return m_opts;
        }

        public String getDescription() {
            return m_sDescription;
        }
    }

    /**
     * Returns an instance of the plugin factory
     * @return
     */
    public static synchronized CPluginFactory getInstance() {
        if (m_Instance == null) {
            m_Instance = new CPluginFactory();
            m_Instance.configure();
        }

        return m_Instance;
    }

    /**
     * This method has been created to facilitate plugin testing.
     * Just call this method, passing the path to your plugin.xml files to get a factory.
     * Then call the getPlugin method to obtain your plugin instance and call the 
     * execute method to execute it.
     * 
     * @param sPluginXMLPath The path to your XML file
     * @return a factory instance
     * @throws FileNotFoundException
     * @throws IOException
     * @throws SAXException
     */
    public static CPluginFactory getInstance(String sPluginXMLPath)
            throws FileNotFoundException, IOException, SAXException {
        if (m_Instance == null) {
            CStreamManager streamMgr = new CStreamManager();
            try {
                m_Instance = new CPluginFactory();
                m_Instance.parsePluginXmlFile(streamMgr.getInputStream(new File(sPluginXMLPath)));
            } finally {
                streamMgr.closeAll();
            }
        }

        return m_Instance;
    }

    /**
     * Configures the factory.
     * 
     * A "jnrpe.plugins.xml" file must be available at classloader's root in order to fetch
     * plugin definitions.
     */
    private void configure() {
        try {
            m_Logger.trace("CONFIGURING PLUGIN FACTORY");
            InputStream is = this.getClass().getClassLoader().getResourceAsStream("jnrpe.plugins.xml");

            if (is != null)
                parsePluginXmlFile(is);
            else
                m_Logger.warn("PLUGIN DEFINITION FILE NOT FOUND.");
        } catch (IOException ex) {
            m_Logger.error("Error " + ex.getMessage(), ex);
        } catch (SAXException ex) {
            m_Logger.error("Error " + ex.getMessage(), ex);
        }
    }

    /**
     * @deprecated
     */
    private void configurePlugins(File fDir) {
        m_Logger.trace("READING PLUGIN CONFIGURATION FROM DIRECTORY " + fDir.getName());
        CStreamManager streamMgr = new CStreamManager();
        File[] vfJars = fDir.listFiles(new FileFilter() {

            public boolean accept(File f) {
                return f.getName().endsWith(".jar");
            }

        });

        // Initializing classloader
        URL[] urls = new URL[vfJars.length];
        URLClassLoader ul = null;

        for (int j = 0; j < vfJars.length; j++) {
            try {
                urls[j] = vfJars[j].toURI().toURL();
            } catch (MalformedURLException e) {
                // should never happen
            }
        }

        ul = URLClassLoader.newInstance(urls);

        for (int i = 0; i < vfJars.length; i++) {
            File file = vfJars[i];

            try {
                m_Logger.info("READING PLUGINS DATA IN FILE '" + file.getName() + "'");

                ZipInputStream jin = (ZipInputStream) streamMgr
                        .handle(new ZipInputStream(new FileInputStream(file)));
                ZipEntry ze = null;

                while ((ze = jin.getNextEntry()) != null) {
                    if (ze.getName().equals("plugin.xml")) {
                        parsePluginXmlFile(jin);
                        break;
                    }
                }
            } catch (Exception e) {
                m_Logger.error("UNABLE TO READ DATA FROM FILE '" + file.getName() + "'. THE FILE WILL BE IGNORED.",
                        e);
            } finally {
                streamMgr.closeAll();
            }

        }
    }

    private void parsePluginXmlFile(InputStream in) throws IOException, SAXException {
        CStreamManager streamMgr = new CStreamManager();

        m_Logger.trace("PARSING FILE plugin.xml IN JAR FILE.");

        Digester digester = DigesterLoader.createDigester(new InputSource(
                streamMgr.handle(this.getClass().getClassLoader().getResourceAsStream("plugin-digester.xml"))));
        CPluginFactoryConfiguration oConf = (CPluginFactoryConfiguration) digester.parse(in);

        List vPluginDefs = oConf.getPluginDefinitions();

        //for (CPluginDefinition pluginDef : vPluginDefs)
        for (Iterator iter = vPluginDefs.iterator(); iter.hasNext();) {
            CPluginDefinition pluginDef = (CPluginDefinition) iter.next();
            m_Logger.debug(
                    "FOUND PLUGIN " + pluginDef.getName() + " IMPLEMENTED BY CLASS " + pluginDef.getPluginClass());
            m_mPlugins.put(pluginDef.getName(), new CPluginData(pluginDef.getName(), pluginDef.getDescription(),
                    pluginDef.getPluginClass(), pluginDef.getOptions()));
        }
    }

    /**
     * Instantiates the plugin
     * @param sPluginName The name of the plugin to be instantiated (as described
     * in the plugin.xml file).
     * @return The plugin
     */
    public CPluginProxy getPlugin(String sPluginName) throws PluginInstantiationException {
        CPluginData pluginData = (CPluginData) m_mPlugins.get(sPluginName);
        if (pluginData != null)
            return new CPluginProxy(sPluginName, pluginData.getDescription(), pluginData.getPluginInstance(),
                    pluginData.getOptions());

        return null;
    }

    public Set getPluginList() {
        return m_mPlugins.keySet();
    }
}