pluginmanager.java.svn-base

来自「开源项目openfire的完整源程序」· SVN-BASE 代码 · 共 708 行 · 第 1/2 页

SVN-BASE
708
字号
/**
 * $Revision: $
 * $Date: $
 *
 * Copyright (C) 2006 Jive Software. All rights reserved.
 *
 * This software is published under the terms of the GNU Lesser Public License (LGPL),
 * a copy of which is included in this distribution.
 */

package org.jivesoftware.spark;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.jivesoftware.MainWindowListener;
import org.jivesoftware.Spark;
import org.jivesoftware.spark.plugin.Plugin;
import org.jivesoftware.spark.plugin.PluginClassLoader;
import org.jivesoftware.spark.plugin.PublicPlugin;
import org.jivesoftware.spark.util.URLFileSystem;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.settings.JiveInfo;

import javax.swing.SwingUtilities;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipFile;

/**
 * This manager is responsible for the loading of all Plugins and Workspaces within Spark environment.
 *
 * @author Derek DeMoro
 */
public class PluginManager implements MainWindowListener {
    private final List<Plugin> plugins = new ArrayList<Plugin>();

    private final List<PublicPlugin> publicPlugins = new CopyOnWriteArrayList<PublicPlugin>();
    private static PluginManager singleton;
    private static final Object LOCK = new Object();

    /**
     * The root Plugins Directory.
     */
    public static File PLUGINS_DIRECTORY = new File(Spark.getBinDirectory().getParent(), "plugins").getAbsoluteFile();

    private PluginClassLoader classLoader;


    /**
     * Returns the singleton instance of <CODE>PluginManager</CODE>,
     * creating it if necessary.
     * <p/>
     *
     * @return the singleton instance of <Code>PluginManager</CODE>
     */
    public static PluginManager getInstance() {
        // Synchronize on LOCK to ensure that we don't end up creating
        // two singletons.
        synchronized (LOCK) {
            if (null == singleton) {
                PluginManager controller = new PluginManager();
                singleton = controller;
                return controller;
            }
        }
        return singleton;
    }

    private PluginManager() {
        try {
            PLUGINS_DIRECTORY = new File(Spark.getBinDirectory().getParentFile(), "plugins").getCanonicalFile();
        }
        catch (IOException e) {
            Log.error(e);
        }

        // Do not use deployable plugins if not installed.
        if (System.getProperty("plugin") == null) {
            movePlugins();
        }

        SparkManager.getMainWindow().addMainWindowListener(this);

        // Create the extension directory if one does not exist.
        if (!PLUGINS_DIRECTORY.exists()) {
            PLUGINS_DIRECTORY.mkdirs();
        }
    }

    private void movePlugins() {
        // Current Plugin directory
        File newPlugins = new File(Spark.getLogDirectory().getParentFile(), "plugins").getAbsoluteFile();
        newPlugins.mkdirs();

        File[] files = PLUGINS_DIRECTORY.listFiles();
        final int no = files != null ? files.length : 0;
        for (int i = 0; i < no; i++) {
            File file = files[i];
            if (file.isFile()) {
                // Copy over
                File newFile = new File(newPlugins, file.getName());

                if (newFile.lastModified() >= file.lastModified()) {
                    continue;
                }

                try {
                    URLFileSystem.copy(file.toURL(), newFile);
                }
                catch (IOException e) {
                    Log.error(e);
                }

            }
        }

        PLUGINS_DIRECTORY = newPlugins;
    }

    /**
     * Loads all {@link Plugin} from the agent plugins.xml and extension lib.
     */
    public void loadPlugins() {
        // Delete all old plugins
        File[] oldFiles = PLUGINS_DIRECTORY.listFiles();
        final int no = oldFiles != null ? oldFiles.length : 0;
        for (int i = 0; i < no; i++) {
            File file = oldFiles[i];
            if (file.isDirectory()) {
                // Check to see if it has an associated .jar
                File jarFile = new File(PLUGINS_DIRECTORY, file.getName() + ".jar");
                if (!jarFile.exists()) {
                    uninstall(file);
                }
            }
        }

        updateClasspath();

        // At the moment, the plug list is hardcode internally until I begin
        // using external property files. All depends on deployment.
        final URL url = getClass().getClassLoader().getResource("META-INF/plugins.xml");
        try {
            InputStreamReader reader = new InputStreamReader(url.openStream());
            loadInternalPlugins(reader);
        }
        catch (IOException e) {
            Log.error("Could not load plugins.xml file.");
        }

        // Load extension plugins
        loadPublicPlugins();

        // For development purposes, load the plugin specified by -Dplugin=...
        String plugin = System.getProperty("plugin");
        if (plugin != null) {
            final StringTokenizer st = new StringTokenizer(plugin, ",", false);
            while (st.hasMoreTokens()) {
                String token = st.nextToken();
                File pluginXML = new File(token);
                loadPublicPlugin(pluginXML.getParentFile());
            }
        }
    }

    /**
     * Loads public plugins.
     *
     * @param pluginDir the directory of the expanded public plugin.
     * @return the new Plugin model for the Public Plugin.
     */
    private Plugin loadPublicPlugin(File pluginDir) {
        File pluginFile = new File(pluginDir, "plugin.xml");
        SAXReader saxReader = new SAXReader();
        Document pluginXML = null;
        try {
            pluginXML = saxReader.read(pluginFile);
        }
        catch (DocumentException e) {
            Log.error(e);
        }

        Plugin pluginClass = null;

        List plugins = pluginXML.selectNodes("/plugin");
        Iterator iter = plugins.iterator();
        while (iter.hasNext()) {
            PublicPlugin publicPlugin = new PublicPlugin();

            String clazz = null;
            String name = null;
            String minVersion;
            String operatingSystem;

            try {
                Element plugin = (Element)iter.next();

                name = plugin.selectSingleNode("name").getText();
                clazz = plugin.selectSingleNode("class").getText();

                // Check for minimum Spark version
                try {
                    minVersion = plugin.selectSingleNode("minSparkVersion").getText();

                    String buildNumber = JiveInfo.getBuildNumber();
                    boolean ok = buildNumber.compareTo(minVersion) >= 0;

                    if (!ok) {
                        return null;
                    }
                }
                catch (Exception e) {
                    Log.error("Unable to load plugin " + name + " due to no minSparkVersion.");
                    return null;
                }

                // Do operating system check.
                boolean operatingSystemOK = isOperatingSystemOK(plugin);
                if (!operatingSystemOK) {
                    return null;
                }

                publicPlugin.setPluginClass(clazz);
                publicPlugin.setName(name);

                try {
                    String version = plugin.selectSingleNode("version").getText();
                    publicPlugin.setVersion(version);

                    String author = plugin.selectSingleNode("author").getText();
                    publicPlugin.setAuthor(author);

                    String email = plugin.selectSingleNode("email").getText();
                    publicPlugin.setEmail(email);

                    String description = plugin.selectSingleNode("description").getText();
                    publicPlugin.setDescription(description);

                    String homePage = plugin.selectSingleNode("homePage").getText();
                    publicPlugin.setHomePage(homePage);
                }
                catch (Exception e) {
                    Log.debug("We can ignore these.");
                }


                try {
                    pluginClass = (Plugin)getParentClassLoader().loadClass(clazz).newInstance();
                    Log.debug(name + " has been loaded.");
                    publicPlugin.setPluginDir(pluginDir);
                    publicPlugins.add(publicPlugin);


                    registerPlugin(pluginClass);
                }
                catch (Throwable e) {
                    Log.error("Unable to load plugin " + clazz + ".", e);
                }
            }
            catch (Exception ex) {
                Log.error("Unable to load plugin " + clazz + ".", ex);
            }


        }

        return pluginClass;
    }

    /**
     * Loads an internal plugin.
     *
     * @param reader the inputstreamreader for an internal plugin.
     */
    private void loadInternalPlugins(InputStreamReader reader) {
        SAXReader saxReader = new SAXReader();
        Document pluginXML = null;
        try {
            pluginXML = saxReader.read(reader);
        }
        catch (DocumentException e) {
            Log.error(e);
        }
        List plugins = pluginXML.selectNodes("/plugins/plugin");
        Iterator iter = plugins.iterator();
        while (iter.hasNext()) {


            String clazz = null;
            String name = null;
            try {
                Element plugin = (Element)iter.next();


                name = plugin.selectSingleNode("name").getText();
                clazz = plugin.selectSingleNode("class").getText();

                Plugin pluginClass = (Plugin)Class.forName(clazz).newInstance();
                Log.debug(name + " has been loaded. Internal plugin.");

                registerPlugin(pluginClass);
            }
            catch (Throwable ex) {
                Log.error("Unable to load plugin " + clazz + ".", ex);
            }
        }
    }

    private void updateClasspath() {
        try {
            classLoader = new PluginClassLoader(getParentClassLoader(), PLUGINS_DIRECTORY);
        }
        catch (MalformedURLException e) {
            Log.error("Error updating classpath.", e);
        }
        Thread.currentThread().setContextClassLoader(classLoader);
    }

    /**
     * Returns the plugin classloader.
     *
     * @return the plugin classloader.
     */
    public ClassLoader getPluginClassLoader() {
        return classLoader;
    }

    /**
     * Registers a plugin.
     *
     * @param plugin the plugin to register.
     */
    public void registerPlugin(Plugin plugin) {
        plugins.add(plugin);
    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?