VASSAL.launch.Launcher.java Source code

Java tutorial

Introduction

Here is the source code for VASSAL.launch.Launcher.java

Source

/*
 * $Id$
 *
 * Copyright (c) 2000-2009 by Rodney Kinney, Joel Uckelman
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License (LGPL) as published by the Free Software Foundation.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, copies are available
 * at http://www.opensource.org.
 */

package VASSAL.launch;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.net.Socket;

import javax.swing.SwingUtilities;

import org.apache.commons.lang.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import VASSAL.Info;
import VASSAL.build.GameModule;
import VASSAL.build.module.ExtensionsLoader;
import VASSAL.i18n.Resources;
import VASSAL.tools.ErrorDialog;
import VASSAL.tools.ThrowableUtils;
import VASSAL.tools.concurrent.listener.EventListener;
import VASSAL.tools.ipc.IPCMessenger;
import VASSAL.tools.ipc.SimpleIPCMessage;
import VASSAL.tools.logging.LoggedOutputStream;
import VASSAL.tools.menu.MenuManager;

/**
 * @author Joel Uckelman
 * @since 3.1.0
 */
public abstract class Launcher {
    private static final Logger logger = LoggerFactory.getLogger(Launcher.class);

    protected IPCMessenger ipc = null;

    protected final LaunchRequest lr;

    private static Launcher instance = null;

    public static Launcher getInstance() {
        return instance;
    }

    protected Launcher(String[] args) {
        if (instance != null)
            throw new IllegalStateException();
        instance = this;

        LaunchRequest lreq = null;
        try {
            lreq = LaunchRequest.parseArgs(args);
        } catch (LaunchRequestException e) {
            System.err.println("VASSAL: " + e.getMessage());
            System.exit(1);
        }

        lr = lreq;

        // Note: We could do more sanity checking of the launch request
        // in standalone mode, but we don't bother because this is meant
        // only for debugging, not for normal use. If you pass nonsense
        // arguments (e.g., '-e' to the Player), don't expect it to work.
        final boolean standalone = lr.standalone;

        /*
            // parse the command line args now if we're standalone, since they
            // could be messed up and so we'll bail before setup
            LaunchRequest lr = null;
            if (standalone) {
              // Note: We could do more sanity checking of the launch request
              // in standalone mode, but we don't bother because this is meant
              // only for debugging, not for normal use. If you pass nonsense
              // arguments (e.g., '-e' to the Player), don't expect it to work.
              try {
                lr = LaunchRequest.parseArgs(args);
              }
              catch (LaunchRequestException e) {
                System.err.println("VASSAL: " + e.getMessage());
                System.exit(1);
              }
            }
        */

        // start the error log and setup system properties
        final StartUp start = SystemUtils.IS_OS_MAC_OSX ? new MacOSXStartUp() : new StartUp();

        start.startErrorLog();

        // log everything which comes across our stderr
        System.setErr(new PrintStream(new LoggedOutputStream(), true));

        logger.info(getClass().getSimpleName());
        Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
        start.initSystemProperties();

        // if we're not standalone, contact the module manager for instructions
        if (!standalone) {
            try {
                final int port = Integer.parseInt(System.getProperty("VASSAL.port"));

                final InetAddress lo = InetAddress.getByName(null);
                final Socket cs = new Socket(lo, port);

                ipc = new IPCMessenger(cs);

                ipc.addEventListener(CloseRequest.class, new CloseRequestListener());

                ipc.start();

                ipc.send(new StartedNotice(Info.getInstanceID()));
            } catch (IOException e) {
                // What we've got here is failure to communicate.
                ErrorDialog.show(e, "Error.communication_error",
                        Resources.getString(getClass().getSimpleName() + ".app_name"));
                System.exit(1);
            }
        }

        createMenuManager();

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    launch();
                } catch (ExtensionsLoader.LoadExtensionException e2) {
                    warn(e2);
                } catch (IOException e1) {
                    warn(e1);
                }
            }

            private void warn(Exception e1) {
                if (ipc == null) {
                    // we are standalone, so warn the user directly
                    ErrorDialog.showDetails(e1, ThrowableUtils.getStackTrace(e1), "Error.module_load_failed",
                            e1.getMessage());
                } else {
                    // we have a manager, so pass the load failure back to it
                    try {
                        ipc.send(new AbstractLaunchAction.NotifyOpenModuleFailed(lr, e1));
                    } catch (IOException e2) {
                        // warn the user directly as a last resort
                        ErrorDialog.showDetails(e1, ThrowableUtils.getStackTrace(e1), "Error.module_load_failed",
                                e1.getMessage());

                        ErrorDialog.show(e2, "Error.communication_error",
                                Resources.getString(getClass().getSimpleName() + ".app_name"));
                    }
                }

                System.exit(1);
            }
        });
    }

    protected abstract void launch() throws IOException;

    protected abstract MenuManager createMenuManager();

    public static class CloseRequest extends SimpleIPCMessage {
        private static final long serialVersionUID = 1L;
    }

    public static class CloseAccept extends SimpleIPCMessage {
        private static final long serialVersionUID = 1L;

        public final long pid;

        public CloseAccept(long pid) {
            this.pid = pid;
        }
    }

    public static class CloseReject extends SimpleIPCMessage {
        private static final long serialVersionUID = 1L;

        public final long pid;

        public CloseReject(long pid) {
            this.pid = pid;
        }
    }

    public static class StartedNotice extends SimpleIPCMessage {
        private static final long serialVersionUID = 1L;

        public final long pid;

        public StartedNotice(long pid) {
            this.pid = pid;
        }
    }

    protected class CloseRequestListener implements EventListener<CloseRequest> {
        private boolean shutdown;

        public void receive(Object src, CloseRequest msg) {
            final GameModule module = GameModule.getGameModule();
            if (module != null) {
                try {
                    SwingUtilities.invokeAndWait(new Runnable() {
                        public void run() {
                            module.getFrame().toFront();
                            shutdown = module.shutDown();
                        }
                    });
                } catch (InterruptedException e) {
                    logger.error("", e);
                    shutdown = false;
                } catch (InvocationTargetException e) {
                    ErrorDialog.bug(e);
                    shutdown = false;
                }
            }

            if (shutdown) {
                if (ipc != null) {
                    try {
                        ipc.send(new CloseAccept(-msg.getId()));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                System.exit(0);
            } else {
                if (ipc != null) {
                    try {
                        ipc.send(new CloseReject(-msg.getId()));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public void sendSaveCmd(File f) {
        if (ipc != null) {
            try {
                ipc.send(new AbstractLaunchAction.NotifySaveFileOk(f));
            }
            // FIXME: review error message
            catch (IOException e) {
            }
        }
    }
}