org.jivesoftware.sparkimpl.plugin.viewer.PluginViewer.java Source code

Java tutorial

Introduction

Here is the source code for org.jivesoftware.sparkimpl.plugin.viewer.PluginViewer.java

Source

/**
 * $RCSfile: ,v $
 * $Revision: $
 * $Date: $
 * 
 * Copyright (C) 2004-2011 Jive Software. All rights reserved.
 *
 * 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 org.jivesoftware.sparkimpl.plugin.viewer;

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JViewport;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.protocol.Protocol;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.jivesoftware.resource.Default;
import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.spark.PluginManager;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.component.MessageDialog;
import org.jivesoftware.spark.component.VerticalFlowLayout;
import org.jivesoftware.spark.plugin.Plugin;
import org.jivesoftware.spark.plugin.PublicPlugin;
import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.ModelUtil;
import org.jivesoftware.spark.util.SwingWorker;
import org.jivesoftware.spark.util.URLFileSystem;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.settings.JiveInfo;
import org.jivesoftware.sparkimpl.settings.local.LocalPreferences;
import org.jivesoftware.sparkimpl.settings.local.SettingsManager;
import org.jivesoftware.sparkimpl.updater.EasySSLProtocolSocketFactory;

/**
 * Class to handle the viewing of installed and downloadable Plugins
 */
public class PluginViewer extends JPanel implements Plugin {

    private static final long serialVersionUID = -4249017716988031394L;

    private JTabbedPane tabbedPane;

    private boolean loaded = false;

    private String retrieveListURL = Default.getString("PLUGIN_REPOSITORY");

    private JProgressBar progressBar;

    private JPanel installedPanel;
    private JPanel availablePanel;
    private JPanel deactivatedPanel;
    private LocalPreferences _prefs;
    private List<String> _deactivatedPlugins;

    public PluginViewer() {
        _prefs = SettingsManager.getLocalPreferences();
        _deactivatedPlugins = _prefs.getDeactivatedPlugins();

        EventQueue.invokeLater(new Runnable() {

            public void run() {

                tabbedPane = new JTabbedPane();
                installedPanel = new JPanel();
                availablePanel = new JPanel();
                deactivatedPanel = new JPanel();
                setLayout(new GridBagLayout());

                installedPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
                installedPanel.setBackground(Color.white);

                availablePanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
                availablePanel.setBackground(Color.white);

                // Add TabbedPane
                add(tabbedPane, new GridBagConstraints(0, 1, 2, 1, 1.0, 1.0, GridBagConstraints.WEST,
                        GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));

                // Add Tabs
                tabbedPane.addTab(Res.getString("tab.installed.plugins"), new JScrollPane(installedPanel));
                if (!Default.getBoolean(Default.INSTALL_PLUGINS_DISABLED)) {
                    tabbedPane.addTab(Res.getString("tab.available.plugins"), new JScrollPane(availablePanel));
                }

                loadInstalledPlugins();
                loadDeactivatedPlugins();

                tabbedPane.addChangeListener(new ChangeListener() {
                    public void stateChanged(ChangeEvent changeEvent) {
                        if (tabbedPane.getSelectedComponent()
                                .equals(((JViewport) availablePanel.getParent()).getParent())) {
                            loadAvailablePlugins();
                            loaded = true;
                        }
                    }
                });
            }
        });
    }

    private void loadInstalledPlugins() {
        PluginManager pluginManager = PluginManager.getInstance();
        List<PublicPlugin> plugins = pluginManager.getPublicPlugins();
        for (Object plugin1 : plugins) {
            PublicPlugin plugin = (PublicPlugin) plugin1;
            final SparkPlugUI ui = new SparkPlugUI(plugin);
            ui.useLocalIcon();
            installedPanel.add(ui);
            addSparkPlugUIListener(ui);
        }
    }

    /**
     * Initializes the Deactivated Plugins Tab
     */
    private void loadDeactivatedPlugins() {
        deactivatedPanel.setLayout(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false));
        if (!Default.getBoolean(Default.DEINSTALL_PLUGINS_DISABLED)) {
            tabbedPane.addTab(Res.getString("tab.deactivated.plugins"), new JScrollPane(deactivatedPanel));
        }
        for (final String s : _deactivatedPlugins) {
            PublicPlugin plg = new PublicPlugin();
            plg.setName(s);
            final SparkPlugUI ui = new SparkPlugUI(plg);
            ui.useLocalIcon();
            deactivatedPanel.add(ui);
            addDeactivatedListener(ui);

        }

    }

    public void initialize() {
        // Add Plugins Menu
        JMenuBar menuBar = SparkManager.getMainWindow().getJMenuBar();

        // Get last menu which is help
        JMenu sparkMenu = menuBar.getMenu(0);

        JMenuItem viewPluginsMenu = new JMenuItem();

        Action viewAction = new AbstractAction() {
            private static final long serialVersionUID = 6518407602062984752L;

            public void actionPerformed(ActionEvent e) {
                invokeViewer();
            }
        };

        viewAction.putValue(Action.NAME, Res.getString("menuitem.plugins"));
        viewAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.PLUGIN_IMAGE));
        viewPluginsMenu.setAction(viewAction);

        sparkMenu.insert(viewPluginsMenu, 2);
    }

    private boolean uninstall(final PublicPlugin plugin) {
        int ok = JOptionPane.showConfirmDialog(installedPanel,
                Res.getString("message.prompt.plugin.uninstall", plugin.getName()),
                Res.getString("title.confirmation"), JOptionPane.YES_NO_OPTION);
        if (ok == JOptionPane.YES_OPTION) {

            // DOENST DELETE ANYMORE, Plugin will be added to a 'do-not-load-list'
            // Delete main jar.
            // File pluginDir = plugin.getPluginDir();
            // File pluginJAR = new File(plugin.getPluginDir().getParentFile(),
            // pluginDir.getName() + ".jar");
            // File mainpluginJar = new
            // File(Spark.getBinDirectory().getParent()+"/plugins/"+pluginJAR.getName());
            // pluginJAR.delete();
            // mainpluginJar.delete();

            List<String> deact = _prefs.getDeactivatedPlugins();
            deact.add(plugin.getName());
            _prefs.setDeactivatedPlugins(deact);
            _deactivatedPlugins = deact;

            final SparkPlugUI ui = new SparkPlugUI(plugin);
            deactivatedPanel.add(ui);
            addDeactivatedListener(ui);

            JOptionPane.showMessageDialog(this, Res.getString("message.restart.spark.changes"),
                    Res.getString("title.reminder"), JOptionPane.INFORMATION_MESSAGE);
            PluginManager.getInstance().removePublicPlugin(plugin);
            return true;
        }

        return false;
    }

    private void invokeViewer() {
        PluginViewer viewer = new PluginViewer();
        MessageDialog.showComponent(Res.getString("title.plugins"), "", null, viewer, SparkManager.getMainWindow(),
                600, 600, false);
    }

    public void shutdown() {

    }

    public boolean canShutDown() {
        return false;
    }

    private void loadAvailablePlugins() {
        availablePanel.removeAll();
        availablePanel.invalidate();
        availablePanel.validate();
        availablePanel.repaint();

        JLabel label = new JLabel(Res.getString("message.loading.please.wait"));
        availablePanel.add(label);

        SwingWorker worker = new SwingWorker() {
            Collection<PublicPlugin> pluginList = null;

            public Object construct() {
                // Prepare HTTP post
                final GetMethod post = new GetMethod(retrieveListURL);

                // Get HTTP client
                Protocol.registerProtocol("https", new Protocol("https", new EasySSLProtocolSocketFactory(), 443));
                final HttpClient httpclient = new HttpClient();

                if (Default.getBoolean("PLUGIN_REPOSITORY_USE_PROXY")) {
                    String proxyHost = System.getProperty("http.proxyHost");
                    String proxyPort = System.getProperty("http.proxyPort");
                    if (ModelUtil.hasLength(proxyHost) && ModelUtil.hasLength(proxyPort)) {
                        try {
                            httpclient.getHostConfiguration().setProxy(proxyHost, Integer.parseInt(proxyPort));
                        } catch (NumberFormatException e) {
                            Log.error(e);
                        }
                    }
                }

                // Execute request

                try {
                    int result = httpclient.executeMethod(post);
                    if (result != 200) {
                        return null;
                    }

                    pluginList = getPluginList(post.getResponseBodyAsStream());
                } catch (Exception ex) {
                    // Nothing to do
                }
                return "ok";
            }

            public void finished() {
                final PluginManager pluginManager = PluginManager.getInstance();
                if (pluginList == null) {
                    availablePanel.removeAll();
                    availablePanel.invalidate();
                    availablePanel.validate();
                    availablePanel.repaint();

                    JOptionPane.showMessageDialog(availablePanel, Res.getString("message.plugins.not.available"),
                            Res.getString("title.error"), JOptionPane.ERROR_MESSAGE);
                    return;
                }
                Iterator<PublicPlugin> plugs = pluginList.iterator();
                availablePanel.removeAll();

                while (plugs.hasNext()) {
                    PublicPlugin plugin = plugs.next();
                    if (!pluginManager.isInstalled(plugin)) {
                        SparkPlugUI ui = new SparkPlugUI(plugin);
                        availablePanel.add(ui);
                        addSparkPlugUIListener(ui);
                    }
                }

                availablePanel.invalidate();
                availablePanel.validate();
                availablePanel.repaint();
            }
        };

        worker.start();
    }

    private void downloadPlugin(final PublicPlugin plugin) {
        // Prepare HTTP post
        final GetMethod post = new GetMethod(plugin.getDownloadURL());

        // Get HTTP client
        Protocol.registerProtocol("https", new Protocol("https", new EasySSLProtocolSocketFactory(), 443));
        final HttpClient httpclient = new HttpClient();
        String proxyHost = System.getProperty("http.proxyHost");
        String proxyPort = System.getProperty("http.proxyPort");

        if (Default.getBoolean("PLUGIN_REPOSITORY_USE_PROXY")) {
            if (ModelUtil.hasLength(proxyHost) && ModelUtil.hasLength(proxyPort)) {
                try {
                    httpclient.getHostConfiguration().setProxy(proxyHost, Integer.parseInt(proxyPort));
                } catch (NumberFormatException e) {
                    Log.error(e);
                }
            }
        }
        // Execute request

        try {
            int result = httpclient.executeMethod(post);
            if (result != 200) {
                return;
            }

            long length = post.getResponseContentLength();
            int contentLength = (int) length;

            progressBar = new JProgressBar(0, contentLength);

            final JFrame frame = new JFrame(Res.getString("message.downloading", plugin.getName()));

            frame.setIconImage(SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_IMAGE).getImage());

            final Thread thread = new Thread(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(2000);
                        InputStream stream = post.getResponseBodyAsStream();

                        URL url = new URL(plugin.getDownloadURL());
                        String name = URLFileSystem.getFileName(url);
                        String directoryName = URLFileSystem.getName(url);

                        File pluginDownload = new File(PluginManager.PLUGINS_DIRECTORY, name);

                        FileOutputStream out = new FileOutputStream(pluginDownload);
                        copy(stream, out);
                        out.close();

                        frame.dispose();

                        // Remove SparkPlugUI
                        // Clear all selections
                        Component[] comps = availablePanel.getComponents();
                        for (Component comp : comps) {
                            if (comp instanceof SparkPlugUI) {
                                SparkPlugUI sparkPlug = (SparkPlugUI) comp;
                                if (sparkPlug.getPlugin().getDownloadURL().equals(plugin.getDownloadURL())) {
                                    availablePanel.remove(sparkPlug);

                                    _deactivatedPlugins.remove(sparkPlug.getPlugin().getName());
                                    _prefs.setDeactivatedPlugins(_deactivatedPlugins);

                                    PluginManager.getInstance().addPlugin(sparkPlug.getPlugin());

                                    sparkPlug.showOperationButton();
                                    installedPanel.add(sparkPlug);
                                    sparkPlug.getPlugin()
                                            .setPluginDir(new File(PluginManager.PLUGINS_DIRECTORY, directoryName));
                                    installedPanel.invalidate();
                                    installedPanel.repaint();
                                    availablePanel.invalidate();
                                    availablePanel.invalidate();
                                    availablePanel.validate();
                                    availablePanel.repaint();
                                }
                            }
                        }
                    } catch (Exception ex) {
                        // Nothing to do
                    } finally {
                        // Release current connection to the connection pool once you are done
                        post.releaseConnection();
                    }
                }
            });

            frame.getContentPane().setLayout(new GridBagLayout());
            frame.getContentPane().add(new JLabel(Res.getString("message.downloading.spark.plug")),
                    new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
                            GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
            frame.getContentPane().add(progressBar, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0,
                    GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
            frame.pack();
            frame.setSize(400, 100);
            GraphicUtils.centerWindowOnComponent(frame, this);

            frame.setVisible(true);
            thread.start();

        } catch (IOException e) {
            Log.error(e);
        }
    }

    public Collection<PublicPlugin> getPluginList(InputStream response) {
        final List<PublicPlugin> pluginList = new ArrayList<PublicPlugin>();
        SAXReader saxReader = new SAXReader();
        Document pluginXML = null;

        try {
            pluginXML = saxReader.read(response);
        } catch (DocumentException e) {
            Log.error(e);
        }

        List<? extends Node> plugins = pluginXML.selectNodes("/plugins/plugin");

        for (Node plugin1 : plugins) {
            PublicPlugin publicPlugin = new PublicPlugin();

            String clazz;
            String name = null;
            try {
                Element plugin = (Element) plugin1;

                try {
                    String version = plugin.selectSingleNode("minSparkVersion").getText();
                    if (!isGreaterOrEqual(JiveInfo.getVersion(), version)) {
                        Log.error("Unable to load plugin " + name + " due to min version incompatibility.");
                        continue;
                    }
                } catch (Exception e) {
                    Log.error("Unable to load plugin " + name + " due to no minSparkVersion.");
                    continue;
                }

                name = plugin.selectSingleNode("name").getText();
                clazz = plugin.selectSingleNode("class").getText();
                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);

                    Node emailNode = plugin.selectSingleNode("email");
                    if (emailNode != null) {
                        publicPlugin.setEmail(emailNode.getText());
                    }

                    Node descriptionNode = plugin.selectSingleNode("description");
                    if (descriptionNode != null) {
                        publicPlugin.setDescription(descriptionNode.getText());
                    }

                    Node homePageNode = plugin.selectSingleNode("homePage");
                    if (homePageNode != null) {
                        publicPlugin.setHomePage(homePageNode.getText());
                    }

                    Node downloadNode = plugin.selectSingleNode("downloadURL");
                    if (downloadNode != null) {
                        String downloadURL = downloadNode.getText();
                        publicPlugin.setDownloadURL(downloadURL);
                    }

                    Node changeLogNode = plugin.selectSingleNode("changeLog");
                    if (changeLogNode != null) {
                        publicPlugin.setChangeLogURL(changeLogNode.getText());
                    }

                    Node readMeNode = plugin.selectSingleNode("readme");
                    if (readMeNode != null) {
                        publicPlugin.setReadMeURL(readMeNode.getText());
                    }

                    Node smallIcon = plugin.selectSingleNode("smallIcon");
                    if (smallIcon != null) {
                        publicPlugin.setSmallIconAvailable(true);
                    }

                    Node largeIcon = plugin.selectSingleNode("largeIcon");
                    if (largeIcon != null) {
                        publicPlugin.setLargeIconAvailable(true);
                    }

                } catch (Exception e) {
                    Log.error("Error retrieving PluginInformation from xml.", e);
                }
                pluginList.add(publicPlugin);
            } catch (Exception ex) {
                ex.printStackTrace();
            }

        }
        return pluginList;
    }

    /**
     * Common code for copy routines.  By convention, the streams are
     * closed in the same method in which they were opened.  Thus,
     * this method does not close the streams when the copying is done.
     *
     * @param in Stream to copy from.
     * @param out Stream to copy to.
     */
    private void copy(final InputStream in, final OutputStream out) {
        int read = 0;
        while (true) {
            try {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    Log.error(e);
                }
                final byte[] buffer = new byte[4096];

                int bytesRead = in.read(buffer);
                if (bytesRead < 0) {
                    break;
                }
                out.write(buffer, 0, bytesRead);
                read += bytesRead;
                final int readprogr = read;
                EventQueue.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        progressBar.setValue(readprogr);

                    }
                });
            } catch (IOException e) {
                Log.error(e);
            }
        }
    }

    private void addSparkPlugUIListener(final SparkPlugUI ui) {
        ui.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent mouseEvent) {
                // Clear all selections
                Component[] comps = installedPanel.getComponents();
                for (Component comp : comps) {
                    if (comp instanceof SparkPlugUI) {
                        SparkPlugUI sparkPlug = (SparkPlugUI) comp;
                        sparkPlug.setSelected(false);
                    }
                }

                // Clear all selections
                comps = availablePanel.getComponents();
                for (Component comp : comps) {
                    if (comp instanceof SparkPlugUI) {
                        SparkPlugUI sparkPlug = (SparkPlugUI) comp;
                        sparkPlug.setSelected(false);
                    }
                }

                ui.setSelected(true);

                final PluginManager pluginManager = PluginManager.getInstance();
                ui.getInstallButton().addMouseListener(new MouseAdapter() {

                    @Override
                    public void mouseClicked(MouseEvent e) {

                        boolean isInstalled = pluginManager.isInstalled(ui.getPlugin());
                        if (isInstalled) {
                            boolean uninstalled = uninstall(ui.getPlugin());
                            if (uninstalled) {
                                installedPanel.remove(ui);
                                installedPanel.invalidate();
                                installedPanel.repaint();
                                installedPanel.revalidate();
                            }
                        } else {
                            downloadPlugin(ui.getPlugin());
                        }
                    }
                });
            }
        });
    }

    /**
     * Adds the MouseClick Listener to the PluginPreview <br>
     * Adds the MouseClick Listener to the InstallButton
     * @param ui
     */
    private void addDeactivatedListener(final SparkPlugUI ui) {

        ui.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

                for (Component c : deactivatedPanel.getComponents()) {
                    if (c instanceof SparkPlugUI) {
                        ((SparkPlugUI) c).setSelected(false);
                    }
                }
                ui.setSelected(true);
            }
        });

        ui.getInstallButton().addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                deactivatedPanel.remove(ui);
                _deactivatedPlugins.remove(ui.getPlugin().getName());
                _prefs.setDeactivatedPlugins(_deactivatedPlugins);
                deactivatedPanel.repaint();
                deactivatedPanel.revalidate();
            }
        });
    }

    public void uninstall() {
        // Do nothing.
    }

    /**
     * Returns true if the first version number is greater than the second.
     *
     * @param firstVersion the first version number.
     * @param secondVersion the second version number.
     * @return returns true if the first version is greater than the second.
     */
    public boolean isGreaterOrEqual(String firstVersion, String secondVersion) {
        return firstVersion.compareTo(secondVersion) >= 0;
    }

    public boolean isLoaded() {
        return loaded;
    }
}