Package org.exist.launcher

Source Code of org.exist.launcher.Launcher$LogActionListener

/*
*  eXist Open Source Native XML Database
*  Copyright (C) 2012 The eXist-db Project
*  http://exist-db.org
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*
*  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 Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*
*  $Id$
*/
package org.exist.launcher;

import org.exist.EXistException;
import org.exist.jetty.JettyStart;
import org.exist.repo.ExistRepository;
import org.exist.security.PermissionDeniedException;
import org.exist.security.xacml.AccessContext;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.util.ConfigurationHelper;
import org.exist.xquery.XPathException;
import org.exist.xquery.XQuery;
import org.exist.xquery.value.Sequence;
import org.exist.xquery.value.SequenceIterator;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Observable;
import java.util.Observer;

/**
* A launcher for the eXist-db server integrated with the desktop.
* Shows a splash screen during startup and registers a tray icon
* in the system bar.
*
* @author Wolfgang Meier
*/
public class Launcher extends Observable implements Observer {

    private MenuItem stopItem;
    private MenuItem startItem;
    private MenuItem dashboardItem;
    private MenuItem eXideItem;
    private MenuItem monexItem;

    public final static String PACKAGE_DASHBOARD = "http://exist-db.org/apps/dashboard";
    public final static String PACKAGE_EXIDE = "http://exist-db.org/apps/eXide";
    public final static String PACKAGE_MONEX = "http://exist-db.org/apps/monex";

    public static void main(final String[] args) {
        final String os = System.getProperty("os.name", "");
        // Switch to native look and feel except for Linux (ugly)
        if (!"Linux".equals(os)) {
            final String nativeLF = UIManager.getSystemLookAndFeelClassName();
            try {
                UIManager.setLookAndFeel(nativeLF);
            } catch (final Exception e) {
                // can be safely ignored
            }
        }
        /* Turn off metal's use of bold fonts */
        //UIManager.put("swing.boldMetal", Boolean.FALSE);

        //Schedule a job for the event-dispatching thread:
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Launcher(args);
            }
        });
    }

    private SystemTray tray = null;
    private TrayIcon trayIcon = null;
    private boolean initSystemTray = true;
    private SplashScreen splash;
    private JettyStart jetty;
    private String home;
    private UtilityPanel utilityPanel;
    private ConfigurationDialog configDialog;

    public Launcher(final String[] args) {
        if (SystemTray.isSupported()) {
            tray = SystemTray.getSystemTray();
        }

        captureConsole();

        home = getJettyHome();

        if (isSystemTraySupported())
            {initSystemTray = initSystemTray(home);}

        configDialog = new ConfigurationDialog(Launcher.this);

        splash = new SplashScreen(this);
        splash.addWindowListener(new WindowAdapter() {
            @Override
            public void windowOpened(WindowEvent windowEvent) {
                if (ConfigurationUtility.isFirstStart()) {
                    splash.setVisible(false);
                    configDialog.open(true);
                    configDialog.requestFocus();
                } else {
                    startJetty();
                }
            }
        });

        final boolean systemTrayReady = tray != null && initSystemTray && tray.getTrayIcons().length > 0;

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                utilityPanel = new UtilityPanel(Launcher.this, systemTrayReady);
            }
        });
    }

    protected void startJetty() {
        new Thread() {
            @Override
            public void run() {
                try {
                    jetty = new JettyStart();
                    jetty.run(new String[]{home}, splash);
                } catch (final Exception e) {
                    showMessageAndExit("Error Occurred", "An error occurred during eXist-db startup. Please check console output and logs.", true);
                    System.exit(1);
                }
            }
        }.start();
    }

    public boolean isSystemTraySupported() {
        return tray != null;
    }

    private boolean initSystemTray(String home) {
        final Dimension iconDim = tray.getTrayIconSize();
        BufferedImage image = null;
        try {
            image = ImageIO.read(getClass().getResource("icon32.png"));
        } catch (final IOException e) {
            showMessageAndExit("Launcher failed", "Failed to read system tray icon.", false);
        }
        trayIcon = new TrayIcon(image.getScaledInstance(iconDim.width, iconDim.height, Image.SCALE_SMOOTH), "eXist-db Launcher");

        final JDialog hiddenFrame = new JDialog();
        hiddenFrame.setUndecorated(true);
        hiddenFrame.setIconImage(image);
       
        final PopupMenu popup = createMenu(home);
        trayIcon.setPopupMenu(popup);

        trayIcon.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                trayIcon.displayMessage(null, "Right click for menu", TrayIcon.MessageType.INFO);
            }
        });

        // add listener for left click on system tray icon. doesn't work well on linux though.
        final String os = System.getProperty("os.name", "");
        if (!os.equals("Linux")) {
            trayIcon.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent mouseEvent) {
                    if (mouseEvent.getButton() == MouseEvent.BUTTON1) {
                        hiddenFrame.add(popup);
                        popup.show(hiddenFrame, mouseEvent.getXOnScreen(), mouseEvent.getYOnScreen());
                    }
                }
            });
        }

        try {
            hiddenFrame.setResizable(false);
            hiddenFrame.pack();
            hiddenFrame.setVisible(true);
            tray.add(trayIcon);
        } catch (final AWTException e) {
            return false;
        }

        return true;
    }

    private PopupMenu createMenu(final String home) {
        final PopupMenu popup = new PopupMenu();
        startItem = new MenuItem("Start server");
        startItem.setEnabled(false);
        popup.add(startItem);
        startItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
            if (jetty.isStarted()) {
                trayIcon.displayMessage(null, "Server already started", TrayIcon.MessageType.WARNING);
            } else {
                jetty.run(new String[]{home}, null);
                if (jetty.isStarted()) {
                    stopItem.setEnabled(true);
                    startItem.setEnabled(false);
                    trayIcon.setToolTip("eXist-db server running on port " + jetty.getPrimaryPort());
                }
            }
            }
        });

        stopItem = new MenuItem("Stop server");
        popup.add(stopItem);
        stopItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                jetty.shutdown();
                stopItem.setEnabled(false);
                startItem.setEnabled(true);
                trayIcon.setToolTip("eXist-db stopped");
            }
        });

        popup.addSeparator();
        MenuItem configItem = new MenuItem("System Configuration");
        popup.add(configItem);
        configItem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                java.awt.EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        configDialog.open(false);
                        configDialog.toFront();
                        configDialog.repaint();
                        configDialog.requestFocus();
                    }
                });
            }
        });

        popup.addSeparator();

        final MenuItem toolbar = new MenuItem("Show Tool Window");
        popup.add(toolbar);
        toolbar.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                java.awt.EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        utilityPanel.toFront();
                        utilityPanel.setVisible(true);
                    }
                });
            }
        });

        MenuItem item;

        if (Desktop.isDesktopSupported()) {
            popup.addSeparator();
            final Desktop desktop = Desktop.getDesktop();
            if (desktop.isSupported(Desktop.Action.BROWSE)) {
                dashboardItem = new MenuItem("Open dashboard");
                dashboardItem.setEnabled(false);
                popup.add(dashboardItem);
                dashboardItem.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent actionEvent) {
                        dashboard(desktop);
                    }
                });
                eXideItem = new MenuItem("Open eXide");
                eXideItem.setEnabled(false);
                popup.add(eXideItem);
                eXideItem.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent actionEvent) {
                        eXide(desktop);
                    }
                });
                item = new MenuItem("Open Java Admin Client");
                popup.add(item);
                item.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent actionEvent) {
                        client();
                    }
                });
                monexItem = new MenuItem("Open Monitoring and Profiling");
                monexItem.setEnabled(false);
                popup.add(monexItem);
                monexItem.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent actionEvent) {
                        monex(desktop);
                    }
                });
            }
            if (desktop.isSupported(Desktop.Action.OPEN)) {
                popup.addSeparator();
                item = new MenuItem("Open exist.log");
                popup.add(item);
                item.addActionListener(new LogActionListener());
            }

            popup.addSeparator();
            item = new MenuItem("Quit (and stop server)");
            popup.add(item);
            item.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent actionEvent) {
                    shutdown(false);
                }
            });
        }
        return popup;
    }

    protected void shutdown(final boolean restart) {
        utilityPanel.setStatus("Shutting down ...");
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                if (jetty != null) {
                    jetty.shutdown();
                }
                if (tray != null) {
                    tray.remove(trayIcon);
                }
                if (restart) {
                    final LauncherWrapper wrapper = new LauncherWrapper(org.exist.launcher.Launcher.class.getName());
                    wrapper.launch();
                }
                System.exit(0);
            }
        });
    }

    protected void dashboard(Desktop desktop) {
        utilityPanel.setStatus("Opening dashboard in browser ...");
        try {
            final URI url = new URI("http://localhost:" + jetty.getPrimaryPort() + "/exist/apps/dashboard/");
            desktop.browse(url);
        } catch (final URISyntaxException e) {
            if (isSystemTraySupported())
                {trayIcon.displayMessage(null, "Failed to open URL", TrayIcon.MessageType.ERROR);}
            utilityPanel.setStatus("Unable to launch browser");
        } catch (final IOException e) {
            if (isSystemTraySupported())
                {trayIcon.displayMessage(null, "Failed to open URL", TrayIcon.MessageType.ERROR);}
            utilityPanel.setStatus("Unable to launch browser");
        }
    }

    protected void eXide(Desktop desktop) {
        utilityPanel.setStatus("Opening dashboard in browser ...");
        try {
            final URI url = new URI("http://localhost:" + jetty.getPrimaryPort() + "/exist/apps/eXide/");
            desktop.browse(url);
        } catch (final URISyntaxException e) {
            if (isSystemTraySupported())
                {trayIcon.displayMessage(null, "Failed to open URL", TrayIcon.MessageType.ERROR);}
            utilityPanel.setStatus("Unable to launch browser");
        } catch (final IOException e) {
            if (isSystemTraySupported())
                {trayIcon.displayMessage(null, "Failed to open URL", TrayIcon.MessageType.ERROR);}
            utilityPanel.setStatus("Unable to launch browser");
        }
    }
   
    protected void monex(Desktop desktop) {
        utilityPanel.setStatus("Opening Monitoring and Profiling in browser ...");
        try {
            final URI url = new URI("http://localhost:" + jetty.getPrimaryPort() + "/exist/apps/monex/");
            desktop.browse(url);
        } catch (final URISyntaxException e) {
            if (isSystemTraySupported())
                {trayIcon.displayMessage(null, "Failed to open URL", TrayIcon.MessageType.ERROR);}
            utilityPanel.setStatus("Unable to launch browser");
        } catch (final IOException e) {
            if (isSystemTraySupported())
                {trayIcon.displayMessage(null, "Failed to open URL", TrayIcon.MessageType.ERROR);}
            utilityPanel.setStatus("Unable to launch browser");
        }
    }

    protected void client() {
        final LauncherWrapper wrapper = new LauncherWrapper("client");
        wrapper.launch();
    }

    protected void signalStarted() {
        if (isSystemTraySupported()) {
            trayIcon.setToolTip("eXist-db server running on port " + jetty.getPrimaryPort());
            startItem.setEnabled(false);
            stopItem.setEnabled(true);
            checkInstalledApps();
            registerObserver();
        }
    }

    protected void signalShutdown() {
        if (isSystemTraySupported()) {
            trayIcon.setToolTip("eXist-db server stopped");
            startItem.setEnabled(true);
            stopItem.setEnabled(false);
        }
    }

    private void checkInstalledApps() {
        BrokerPool pool = null;
        DBBroker broker = null;
        try {
            pool = BrokerPool.getInstance();
            broker = pool.get(pool.getSecurityManager().getSystemSubject());
            final XQuery xquery = broker.getXQueryService();
            final Sequence pkgs = xquery.execute("repo:list()", null, AccessContext.INITIALIZE);
            for (final SequenceIterator i = pkgs.iterate(); i.hasNext(); ) {
                final ExistRepository.Notification notification = new ExistRepository.Notification(ExistRepository.Action.INSTALL, i.nextItem().getStringValue());
                update(pool.getExpathRepo(), notification);
                utilityPanel.update(pool.getExpathRepo(), notification);
            }
        } catch (final EXistException e) {
            System.err.println("Failed to check installed packages: " + e.getMessage());
            e.printStackTrace();
        } catch (final XPathException e) {
            System.err.println("Failed to check installed packages: " + e.getMessage());
            e.printStackTrace();
        } catch (final PermissionDeniedException e) {
            System.err.println("Failed to check installed packages: " + e.getMessage());
            e.printStackTrace();
        } finally {
            if (pool != null)
                {pool.release(broker);}
        }
    }

    private void registerObserver() {
        try {
            final BrokerPool pool = BrokerPool.getInstance();
            pool.getExpathRepo().addObserver(this);
            pool.getExpathRepo().addObserver(utilityPanel);
        } catch (final EXistException e) {
            System.err.println("Failed to register as observer for package manager events");
            e.printStackTrace();
        }
    }

    @Override
    public void update(Observable observable, Object o) {
        final ExistRepository.Notification notification = (ExistRepository.Notification) o;

        if (notification.getPackageURI().equals(PACKAGE_DASHBOARD) && dashboardItem != null) {
            dashboardItem.setEnabled(notification.getAction() == ExistRepository.Action.INSTALL);

        } else if (notification.getPackageURI().equals(PACKAGE_EXIDE) && eXideItem != null) {
            eXideItem.setEnabled(notification.getAction() == ExistRepository.Action.INSTALL);

        } else if (notification.getPackageURI().equals(PACKAGE_MONEX) && monexItem != null) {
            monexItem.setEnabled(notification.getAction() == ExistRepository.Action.INSTALL);
        }
    }

    private String getJettyHome() {
        String jettyProperty = System.getProperty("jetty.home");
        if(jettyProperty==null) {
            final File home = ConfigurationHelper.getExistHome();
            final File jettyHome = new File(new File(home, "tools"), "jetty");
            jettyProperty = jettyHome.getAbsolutePath();
            System.setProperty("jetty.home", jettyProperty);
        }
        final File standaloneFile = new File(new File(jettyProperty, "etc"), "jetty.xml");
        return standaloneFile.getAbsolutePath();
    }

    protected void showMessageAndExit(String title, String message, boolean logs) {
        final JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());

        final JLabel label = new JLabel(message);
        label.setHorizontalAlignment(SwingConstants.CENTER);
        panel.add(label, BorderLayout.CENTER);
        if (logs) {
            final JButton displayLogs = new JButton("View Log");
            displayLogs.addActionListener(new LogActionListener());
            label.setHorizontalAlignment(SwingConstants.CENTER);
            panel.add(displayLogs, BorderLayout.SOUTH);
        }

        utilityPanel.showMessages();
        utilityPanel.toFront();
        utilityPanel.setVisible(true);

        JOptionPane.showMessageDialog(splash, panel, title, JOptionPane.WARNING_MESSAGE);
        //System.exit(1);
    }

    /**
     * Ensure that stdout and stderr messages are also printed
     * to the logs.
     */
    private void captureConsole() {
        System.setOut(createLoggingProxy(System.out));
        System.setErr(createLoggingProxy(System.err));
    }

    public PrintStream createLoggingProxy(final PrintStream realStream) {
        final OutputStream out = new OutputStream() {
            @Override
            public void write(int i) throws IOException {
                realStream.write(i);
                String s = String.valueOf((char) i);
                Launcher.this.setChanged();
                Launcher.this.notifyObservers(s);
            }

            @Override
            public void write(byte[] bytes) throws IOException {
                realStream.write(bytes);
                String s = new String(bytes);
                Launcher.this.setChanged();
                Launcher.this.notifyObservers(s);
            }

            @Override
            public void write(byte[] bytes, int offset, int len) throws IOException {
                realStream.write(bytes, offset, len);
                String s = new String(bytes, offset, len);
                Launcher.this.setChanged();
                Launcher.this.notifyObservers(s);
            }
        };
        return new PrintStream(out);
    }

    private class LogActionListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent actionEvent) {
            if (!Desktop.isDesktopSupported())
                {return;}
            final Desktop desktop = Desktop.getDesktop();
            final File home = ConfigurationHelper.getExistHome();
            final File logFile = new File(home, "webapp/WEB-INF/logs/exist.log");
            if (!logFile.canRead()) {
                trayIcon.displayMessage(null, "Log file not found", TrayIcon.MessageType.ERROR);
            } else {
                try {
                    desktop.open(logFile);
                } catch (final IOException e) {
                    trayIcon.displayMessage(null, "Failed to open log file", TrayIcon.MessageType.ERROR);
                }
            }
        }
    }
}
TOP

Related Classes of org.exist.launcher.Launcher$LogActionListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.