de.tor.tribes.ui.windows.DSWorkbenchSplashScreen.java Source code

Java tutorial

Introduction

Here is the source code for de.tor.tribes.ui.windows.DSWorkbenchSplashScreen.java

Source

/*//GEN-LINE:variables
 * Copyright 2015 Torridity.
 *
 * 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 de.tor.tribes.ui.windows;

import de.tor.tribes.dssim.ui.DSWorkbenchSimulatorFrame;
import de.tor.tribes.io.DataHolder;
import de.tor.tribes.io.DataHolderListener;
import de.tor.tribes.io.ServerManager;
import de.tor.tribes.types.UserProfile;
import de.tor.tribes.ui.renderer.ProfileTreeNodeRenderer;
import de.tor.tribes.ui.views.DSWorkbenchSettingsDialog;
import de.tor.tribes.ui.wiz.FirstStartWizard;
import de.tor.tribes.util.*;
import de.tor.tribes.util.GithubVersionCheck.UpdateInfo;
import de.tor.tribes.util.ThreadDeadlockDetector.DefaultDeadlockListener;
import java.io.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.Configurator;
import org.netbeans.api.wizard.WizardDisplayer;
import org.netbeans.spi.wizard.Wizard;
import org.netbeans.spi.wizard.WizardPanelProvider;

/**
 * @author Torridity
 */
public class DSWorkbenchSplashScreen extends javax.swing.JFrame implements DataHolderListener {

    protected enum HIDE_RESULT {
        SUCCESS, RESTART_NEEDED, ERROR
    }

    private static Logger logger = LogManager.getLogger("Launcher");
    private final DSWorkbenchSplashScreen self = this;
    private final SplashRepaintThread t;
    private static DSWorkbenchSplashScreen SINGLETON = null;
    private ThreadDeadlockDetector deadlockDetector = null;

    public static synchronized DSWorkbenchSplashScreen getSingleton() {
        if (SINGLETON == null) {
            SINGLETON = new DSWorkbenchSplashScreen();
        }
        return SINGLETON;
    }

    /**
     * Creates new form DSWorkbenchSplashScreen
     */
    DSWorkbenchSplashScreen() {
        initComponents();
        if (GlobalOptions.isMinimal()) {
            jLabel1.setIcon(new ImageIcon("./graphics/splash_mini.gif"));
        } else {
            jLabel1.setIcon(new ImageIcon("./graphics/splash.gif"));
        }

        setTitle("DS Workbench " + Constants.VERSION + Constants.VERSION_ADDITION);
        jProfileDialog.getContentPane().setBackground(Constants.DS_BACK_LIGHT);
        jProfileDialog.pack();
        jProfileDialog.setLocationRelativeTo(DSWorkbenchSplashScreen.this);
        t = new SplashRepaintThread();
        t.start();
        new Timer("StartupTimer", true).schedule(new HideSplashTask(), 1000);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jProfileDialog = new javax.swing.JDialog();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTree1 = new javax.swing.JTree();
        jButton1 = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        jStatusOutput = new javax.swing.JProgressBar();

        jProfileDialog.setTitle("Profile");
        jProfileDialog.setModal(true);
        jProfileDialog.setUndecorated(true);

        jScrollPane2.setViewportView(jTree1);

        jButton1.setBackground(new java.awt.Color(239, 235, 223));
        jButton1.setText("Profil auswhlen");
        jButton1.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                fireSelectAccountEvent(evt);
            }
        });

        javax.swing.GroupLayout jProfileDialogLayout = new javax.swing.GroupLayout(jProfileDialog.getContentPane());
        jProfileDialog.getContentPane().setLayout(jProfileDialogLayout);
        jProfileDialogLayout.setHorizontalGroup(
                jProfileDialogLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(jProfileDialogLayout.createSequentialGroup().addContainerGap()
                                .addGroup(jProfileDialogLayout
                                        .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 380,
                                                Short.MAX_VALUE)
                                        .addComponent(jButton1, javax.swing.GroupLayout.Alignment.TRAILING))
                                .addContainerGap()));
        jProfileDialogLayout.setVerticalGroup(jProfileDialogLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jProfileDialogLayout.createSequentialGroup().addContainerGap()
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 187,
                                javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18).addComponent(jButton1)
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setUndecorated(true);

        jLabel1.setMaximumSize(new java.awt.Dimension(516, 250));
        jLabel1.setMinimumSize(new java.awt.Dimension(516, 250));
        jLabel1.setPreferredSize(new java.awt.Dimension(516, 250));
        getContentPane().add(jLabel1, java.awt.BorderLayout.CENTER);

        jStatusOutput.setIndeterminate(true);
        jStatusOutput.setMinimumSize(new java.awt.Dimension(10, 20));
        jStatusOutput.setPreferredSize(new java.awt.Dimension(146, 20));
        jStatusOutput.setString("Lade Einstellungen...");
        jStatusOutput.setStringPainted(true);
        getContentPane().add(jStatusOutput, java.awt.BorderLayout.SOUTH);

        pack();
    }// </editor-fold>                        

    private void fireSelectAccountEvent(java.awt.event.MouseEvent evt) {
        Object[] path = jTree1.getSelectionPath().getPath();
        UserProfile profile = null;
        try {
            profile = (UserProfile) ((DefaultMutableTreeNode) path[2]).getUserObject();
        } catch (Exception ignored) {
        }
        if (profile == null) {
            JOptionPaneHelper.showWarningBox(jProfileDialog, "Bitte eine Profil auswhlen.", "Bitte whlen");
        } else {
            String server = profile.getServerId();
            if (ServerManager.getServerURL(server) == null) {
                //no world data update any longer
                JOptionPaneHelper.showWarningBox(jProfileDialog,
                        "Der Server des gewhlten Profils scheint nicht mehr verfgbar zu sein. Es wird keine Aktualisierung der Weltdaten mehr stattfinden.",
                        "Server nicht verfgbar.");
            }
            GlobalOptions.setSelectedServer(server);
            GlobalOptions.setSelectedProfile(profile);
            GlobalOptions.addProperty("default.server", server);
            GlobalOptions.addProperty("selected.profile", Long.toString(profile.getProfileId()));
            GlobalOptions.addProperty("default.player", Long.toString(profile.getProfileId()));
            jProfileDialog.setVisible(false);
        }
    }

    protected HIDE_RESULT hideSplash() {
        try {
            if (!new File(".").canWrite()) {
                try {
                    throw new IOException(
                            "Failed to access installation directory " + new File(".").getAbsolutePath());
                } catch (Exception e) {
                    showFatalError(e);
                    return HIDE_RESULT.ERROR;
                }
            }
            File f = new File("./servers");
            if (!f.exists() && !f.mkdir()) {
                try {
                    throw new IOException(
                            "Failed to create server directory at location " + new File(".").getAbsolutePath());
                } catch (Exception e) {
                    showFatalError(e);
                    return HIDE_RESULT.ERROR;
                }
            }

            ProfileManager.getSingleton().loadProfiles();
            if (ProfileManager.getSingleton().getProfiles().length == 0) {
                logger.debug("Starting first start wizard");

                //first start wizard
                if (!new File("./hfsw").exists()) {
                    logger.debug(" - Initializing first start wizard");
                    Map result = new HashMap<>();

                    try {
                        WizardPanelProvider provider = new FirstStartWizard();
                        Wizard wizard = provider.createWizard();
                        logger.debug(" - Showing wizard");
                        result = (Map) WizardDisplayer.showWizard(wizard);
                        logger.debug("Wizard finished with result " + result);
                    } catch (Throwable t) {
                        logger.error("Wizard exception", t);
                        result = null;
                    }
                    logger.debug(" - Wizard has finished");
                    if (result == null) {
                        logger.warn(" - Wizard returned no result. Startup will fail.");
                        JOptionPaneHelper.showWarningBox(self,
                                "Du musst die grundlegenden Einstellungen zumindest einmalig durchfhren,\n"
                                        + "um DS Workbench verwenden zu knnen. Bitte starte DS Workbench neu.",
                                "Abbruch");
                        return HIDE_RESULT.ERROR;
                    } else {
                        logger.debug("Wizard result: " + result);
                    }
                    logger.debug("- First start wizard finished");
                    GlobalOptions.addProperty("proxySet", result.get("proxySet").toString());
                    GlobalOptions.addProperty("proxyHost", result.get("proxyHost").toString());
                    GlobalOptions.addProperty("proxyPort", result.get("proxyPort").toString());
                    GlobalOptions.addProperty("proxyType", result.get("proxyType").toString());
                    GlobalOptions.addProperty("proxyUser", result.get("proxyUser").toString());
                    GlobalOptions.addProperty("proxyPassword", result.get("proxyPassword").toString());
                    GlobalOptions.addProperty("default.server", result.get("server").toString());
                    GlobalOptions.addProperty("default.player", result.get("tribe.id").toString());
                    logger.debug("Creating initial profile");
                    UserProfile p = UserProfile.create(GlobalOptions.getProperty("default.server"),
                            result.get("tribe.name").toString());
                    GlobalOptions.setSelectedProfile(p);
                    GlobalOptions.addProperty("selected.profile", Long.toString(p.getProfileId()));
                    logger.debug(" - Disabling first start wizard");
                    FileUtils.touch(new File("./hfsw"));
                    GlobalOptions.saveProperties();
                }
            }

            //load properties, cursors, skins, world decoration
            logger.debug("Adding startup listeners");
            DataHolder.getSingleton().addDataHolderListener(this);
            DataHolder.getSingleton().addDataHolderListener(DSWorkbenchSettingsDialog.getSingleton());
            GlobalOptions.addDataHolderListener(this);
        } catch (Exception e) {
            logger.error("Failed to initialize global options", e);
            showFatalError(e);
            return HIDE_RESULT.ERROR;
        }

        logger.debug("Starting profile selection");
        boolean settingsRestored = false;

        ServerManager.loadServerList(DSWorkbenchSettingsDialog.getSingleton().getWebProxy());
        try {
            //open profile selection
            if (ProfileManager.getSingleton().getProfiles().length == 0) {
                logger.debug("No profile exists, SettingsDialog will handle this");
                //no profile found...this is handles by the settings validation
            } else if (ProfileManager.getSingleton().getProfiles().length == 1) {
                logger.debug("One profile exists. Using it...");
                //only one single profile was found, use it
                UserProfile profile = ProfileManager.getSingleton().getProfiles()[0];
                String server = profile.getServerId();
                GlobalOptions.setSelectedServer(server);
                GlobalOptions.setSelectedProfile(profile);
                GlobalOptions.addProperty("default.server", server);
                GlobalOptions.addProperty("selected.profile", Long.toString(profile.getProfileId()));
            } else {
                logger.debug("More than one profiles exist. Showing selection dialog");
                File f = new File("./servers");
                List<String> servers = new LinkedList<>();
                for (File server : f.listFiles()) {
                    servers.add(server.getName());
                }
                //sort server names
                Collections.sort(servers, new Comparator<String>() {
                    @Override
                    public int compare(String o1, String o2) {
                        if (o1.length() < o2.length()) {
                            return -1;
                        } else if (o1.length() > o2.length()) {
                            return 1;
                        }
                        return o1.compareTo(o2);
                    }
                });
                List<Object> path = new LinkedList<>();
                DefaultMutableTreeNode root = new DefaultMutableTreeNode("Profile");
                long selectedProfile = GlobalOptions.getProperties().getLong("selected.profile");
                path.add(root);
                for (String server : servers) {
                    DefaultMutableTreeNode serverNode = new DefaultMutableTreeNode(server);
                    boolean profileAdded = false;
                    for (UserProfile profile : ProfileManager.getSingleton().getProfiles(server)) {
                        DefaultMutableTreeNode profileNode = new DefaultMutableTreeNode(profile);
                        if (profile.getProfileId() == selectedProfile) {
                            path.add(serverNode);
                            path.add(profileNode);
                        }
                        serverNode.add(profileNode);
                        profileAdded = true;
                    }
                    if (profileAdded) {
                        root.add(serverNode);
                    }
                }

                jTree1.setModel(new DefaultTreeModel(root));
                jTree1.setSelectionPath(new TreePath(path.toArray()));
                jTree1.scrollPathToVisible(new TreePath(path.toArray()));
                jTree1.setCellRenderer(new ProfileTreeNodeRenderer());
                jProfileDialog.setVisible(true);
            }
            logger.debug("Profile selection finished");
            //check settings
            DSWorkbenchSettingsDialog.getSingleton().restoreProperties();
            settingsRestored = true;
            if (!DSWorkbenchSettingsDialog.getSingleton().checkSettings()) {
                logger.debug("Settings check in settings dialog failed");
                logger.info("Reading user settings returned error(s)");
                DSWorkbenchSettingsDialog.getSingleton().setBlocking(true);
                DSWorkbenchSettingsDialog.getSingleton().setVisible(true);
            }
        } catch (Exception e) {
            logger.warn("Failed to open profile manager", e);
        }

        if (!settingsRestored) {
            DSWorkbenchSettingsDialog.getSingleton().restoreProperties();
        }

        // <editor-fold defaultstate="collapsed" desc=" Check for data updates ">
        logger.debug("Checking for application updates");
        boolean checkForUpdates = GlobalOptions.getProperties().getBoolean("check.updates.on.startup");

        try {
            if (!DataHolder.getSingleton().loadData(checkForUpdates)) {
                throw new Exception("loadData() returned 'false'. See log for more details.");
            }
        } catch (Exception e) {
            logger.error("Failed to load server data", e);
            showFatalError(e);
            return HIDE_RESULT.ERROR;
        }
        // </editor-fold>
        try {
            logger.debug("Initializing application window");
            DSWorkbenchMainFrame.getSingleton().init();
            logger.info("Showing application window");

            DSWorkbenchMainFrame.getSingleton().setVisible(true);

            //check for version updates
            logger.info("Checking for DS Workbench update.");
            UpdateInfo info = GithubVersionCheck.getUpdateInformation();
            switch (info.getStatus()) {
            case UPDATE_AVAILABLE:
                NotifierFrame.doNotification(
                        "Eine neue DS Workbench Version ist verfgbar. Klick den grnen Punkt oben links, um auf die Download Seite zu gelangen. ",
                        NotifierFrame.NOTIFY_UPDATE);
            default:
                logger.info("No update available or update check failed.");
            }

            try {
                ReportServer.getSingleton().start(GlobalOptions.getProperties().getInt("report.server.port"));
            } catch (Exception e) {
                logger.error("Failed to start report server", e);
            }

            // <editor-fold defaultstate="collapsed" desc=" Init HelpSystem ">
            if (!Constants.DEBUG) {
                GlobalOptions.getHelpBroker().enableHelpKey(DSWorkbenchSimulatorFrame.getSingleton().getRootPane(),
                        "pages.astar", GlobalOptions.getHelpBroker().getHelpSet());
                GlobalOptions.getHelpBroker().enableHelpKey(DSWorkbenchMainFrame.getSingleton().getRootPane(),
                        "index", GlobalOptions.getHelpBroker().getHelpSet());
            }
            // </editor-fold>

            // <editor-fold defaultstate="collapsed" desc=" Init A*Star Servers ">
            ServerManager.giveSimulatorServerList();
            // </editor-fold>

            t.stopRunning();
            setVisible(false);
            GlobalOptions.removeDataHolderListener(this);

            return HIDE_RESULT.SUCCESS;
        } catch (Throwable th) {
            logger.fatal("Fatal error while running DS Workbench", th);
            showFatalError(th);
            return HIDE_RESULT.ERROR;
        }
    }

    private void showFatalError(Throwable t) {
        FatalErrorDialog errorDialog = new FatalErrorDialog(self, true);
        errorDialog.setLocationRelativeTo(self);
        errorDialog.show(t);
    }

    public static class ExceptionHandler implements Thread.UncaughtExceptionHandler {

        public void handle(Throwable thrown) {
            // for EDT exceptions
            handleException(Thread.currentThread().getName(), thrown);
        }

        @Override
        public void uncaughtException(Thread thread, Throwable thrown) {
            // for other uncaught exceptions
            handleException(thread.getName(), thrown);
        }

        protected void handleException(String tname, Throwable thrown) {
            logger.warn("Unhandled exception in thread '" + tname + "'", thrown);
        }
    }

    private boolean SPECIAL_DEBUG_MODE = false;

    public void initializeSuperSpecialDebugFeatures() {
        if (SPECIAL_DEBUG_MODE) {
            return;
        }
        SystrayHelper.showInfoMessage("Switching to debug mode");
        deadlockDetector = new ThreadDeadlockDetector();
        deadlockDetector.addListener(new DefaultDeadlockListener());
        Configurator.setAllLevels(LogManager.getRootLogger().getName(), Level.DEBUG);
        logger.debug("==========================");
        logger.debug("==DEBUG MODE ESTABLISHED==");
        logger.debug("==========================");

        logger.debug("---------System Information---------");
        logger.debug("Operating System: " + System.getProperty("os.name") + " (" + System.getProperty("os.version")
                + "/" + System.getProperty("os.arch") + ")");
        logger.debug("Java: " + System.getProperty("java.vendor") + " " + System.getProperty("java.version") + " ("
                + System.getProperty("java.home") + ")");
        logger.debug("Working Dir: " + System.getProperty("user.dir"));
        logger.debug("------------------------------------");
        SPECIAL_DEBUG_MODE = true;
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        Locale.setDefault(Locale.GERMAN);
        int mode = -1;
        int minimal = 0;
        boolean ssd = false;
        if (args != null) {
            for (String arg : args) {
                switch (arg) {
                case "-d":
                case "--debug":
                    //debug mode
                    mode = 0;
                    SystrayHelper.showInfoMessage("Running in debug mode");
                    break;
                case "-m":
                    minimal = 1;
                    break;
                case "-ssd":
                    ssd = true;
                    break;
                }
            }
        }
        Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
        System.setProperty("sun.awt.exception.handler", ExceptionHandler.class.getName());

        if (mode == 0) {
            Configurator.setAllLevels(LogManager.getRootLogger().getName(), Level.DEBUG);
        }
        GlobalOptions.setMinimalVersion(minimal == 1);

        try {
            GlobalDefaults.initialize();
            GlobalOptions.initialize();
            //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            logger.error("Failed to setup LnF", e);
        }

        final boolean useSSD = ssd;

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    DSWorkbenchSplashScreen.getSingleton().setLocationRelativeTo(null);
                    if (useSSD) {
                        DSWorkbenchSplashScreen.getSingleton().initializeSuperSpecialDebugFeatures();
                    }
                    DSWorkbenchSplashScreen.getSingleton().setVisible(true);
                } catch (Exception e) {
                    logger.error("Fatal application error", e);
                }
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JDialog jProfileDialog;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JProgressBar jStatusOutput;
    private javax.swing.JTree jTree1;
    // End of variables declaration                   

    @Override
    public void fireDataHolderEvent(String eventMessage) {
        jStatusOutput.setString(eventMessage);
    }

    public void updateStatus() {
        jStatusOutput.repaint();
    }

    @Override
    public void fireDataLoadedEvent(boolean pSuccess) {
        if (pSuccess) {
            jStatusOutput.setString("Daten geladen");
        } else {
            jStatusOutput.setString("Download fehlgeschlagen");
        }
    }
}

class HideSplashTask extends TimerTask {

    public HideSplashTask() {
        super();
    }

    @Override
    public void run() {
        try {
            switch (DSWorkbenchSplashScreen.getSingleton().hideSplash()) {
            case ERROR: {
                System.exit(1);
                break;
            }
            case RESTART_NEEDED: {
                System.exit(0);
                break;
            }
            default: {
                //finally, add the shutdown hook to guarantee a proper termination
                Runtime.getRuntime().addShutdownHook(MainShutdownHook.getSingleton());
                GlobalOptions.setStarted();
                break;
            }
            }
        } catch (Throwable t) {
            System.exit(1);
        }
    }
}

class SplashRepaintThread extends Thread {

    private boolean running = true;

    public SplashRepaintThread() {
        setName("SplashHideThread");
        setDaemon(true);
    }

    @Override
    public void run() {
        while (running) {
            DSWorkbenchSplashScreen.getSingleton().updateStatus();
            try {
                Thread.sleep(50);
            } catch (InterruptedException ignored) {
            }
        }
    }

    public void stopRunning() {
        running = false;
    }
}