Package org.spoutcraft.launcher.entrypoint

Source Code of org.spoutcraft.launcher.entrypoint.SpoutcraftLauncher

/*
* This file is part of Spoutcraft Launcher.
*
* Copyright (c) 2011 Spout LLC <http://www.spout.org/>
* Spoutcraft Launcher is licensed under the Spout License Version 1.
*
* Spoutcraft Launcher 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 3 of the License, or
* (at your option) any later version.
*
* In addition, 180 days after any changes are published, you can use the
* software, incorporating those changes, under the terms of the MIT license,
* as described in the Spout License Version 1.
*
* Spoutcraft Launcher 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,
* the MIT license and the Spout License Version 1 along with this program.
* If not, see <http://www.gnu.org/licenses/> for the GNU Lesser General Public
* License and see <http://spout.in/licensev1> for the full license,
* including the MIT license.
*/
package org.spoutcraft.launcher.entrypoint;

import java.awt.Toolkit;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.StreamHandler;

import javax.swing.JOptionPane;
import javax.swing.UIManager;

import com.beust.jcommander.JCommander;
import org.apache.commons.io.IOUtils;

import org.spoutcraft.launcher.GameUpdater;
import org.spoutcraft.launcher.Proxy;
import org.spoutcraft.launcher.Settings;
import org.spoutcraft.launcher.GameLauncher;
import org.spoutcraft.launcher.StartupParameters;
import org.spoutcraft.launcher.api.Launcher;
import org.spoutcraft.launcher.api.SpoutcraftDirectories;
import org.spoutcraft.launcher.exceptions.RestfulAPIException;
import org.spoutcraft.launcher.rest.SpoutcraftBuild;
import org.spoutcraft.launcher.skin.ConsoleFrame;
import org.spoutcraft.launcher.skin.ErrorDialog;
import org.spoutcraft.launcher.skin.MetroLoginFrame;
import org.spoutcraft.launcher.skin.components.LoginFrame;
import org.spoutcraft.launcher.util.OperatingSystem;
import org.spoutcraft.launcher.util.Utils;
import org.spoutcraft.launcher.yml.YAMLFormat;
import org.spoutcraft.launcher.yml.YAMLProcessor;

public class SpoutcraftLauncher {
  private static Logger logger = null;
  protected static RotatingFileHandler handler = null;
  protected static ConsoleFrame console;
  public SpoutcraftLauncher() {
    main(new String[0]);
  }

  public static void main(String[] args) {
    long start = System.currentTimeMillis();
    final long startupTime = start;

    // Prefer IPv4
    System.setProperty("java.net.preferIPv4Stack" , "true");

    SplashScreen splash = new SplashScreen(Toolkit.getDefaultToolkit().getImage(SplashScreen.class.getResource("/org/spoutcraft/launcher/resources/splash.png")));
    splash.setVisible(true);

    StartupParameters params = setupParameters(args);
    SpoutcraftLauncher.logger = setupLogger();
   
    cleanup();

    int launcherBuild = parseInt(getLauncherBuild(), -1);
    logger.info("---------------------------------------------");
    logger.info("Spoutcraft Launcher is starting...");
    logger.info("Operating System: " + System.getProperty("os.name") + " " + System.getProperty("os.version") + " " + System.getProperty("os.arch"));
    logger.info("Java Version: " + System.getProperty("java.vendor") + " " + System.getProperty("java.version") + " <" + System.getProperty("java.vendor.url") + ">");
    logger.info("Launcher Build: " + launcherBuild);

    params.logParameters(logger);

    // Setup directories
    SpoutcraftDirectories dirs = new SpoutcraftDirectories();
    dirs.getSkinDir().mkdirs();
    dirs.getSpoutcraftDir().mkdirs();

    if (Settings.getYAML() == null) {
      YAMLProcessor settings = setupSettings();
      if (settings == null) {
        throw new NullPointerException("The YAMLProcessor object was null for settings.");
      }
      Settings.setYAML(settings);
    }
    Settings.setLauncherBuild(launcherBuild);
    setupProxy();

    if (params.isDebugMode()) {
      Settings.setDebugMode(true);
    }

    if (Settings.isDebugMode()) {
      logger.info("Initial organization and look and feel time took " + (System.currentTimeMillis() - start) + " ms");
      start = System.currentTimeMillis();
    }

    if (Settings.isDebugMode()) {
      logger.info("Loading settings took " + (System.currentTimeMillis() - start) + " ms");
      start = System.currentTimeMillis();
    }

    if (params.relaunch(logger)) {
      try {
        Thread.sleep(3000);
      } catch (InterruptedException e) { }
      System.exit(0);
      return;
    }

    checkInternet();

    validateBuild(params);

    setLookAndFeel();

    if (params.isConsole() || Settings.isDebugMode()) {
      setupConsole();
      logger.info("Debug mode activated!");
    }

    Runtime.getRuntime().addShutdownHook(new ShutdownThread());
    Thread logThread = new LogFlushThread();
    logThread.start();

    if (Settings.isDebugMode()) {
      logger.info("Internet validation and look and feel took " + (System.currentTimeMillis() - start) + " ms");
      start = System.currentTimeMillis();
    }

    // Set up the launcher and load login frame
    LoginFrame frame = new MetroLoginFrame();

    try {
      @SuppressWarnings("unused")
      Launcher launcher = new Launcher(new GameUpdater(), new GameLauncher(), frame);
    } catch (IOException failure) {
      failure.printStackTrace();
      ErrorDialog dialog = new ErrorDialog(frame, failure);
      splash.dispose();
      frame.setVisible(true);
      dialog.setAlwaysOnTop(true);
      dialog.setVisible(true);
      return;
    }
    Launcher.getGameUpdater().start();

    if (Settings.isDebugMode()) {
      logger.info("Loading default launcher skin took " + (System.currentTimeMillis() - start) + " ms");
      start = System.currentTimeMillis();
    }

    splash.dispose();
    frame.setVisible(true);
    if (params.hasAccount()) {
      frame.disableForm();
      frame.doLogin(params.getUser(), params.getPass());
    }

    logger.info("Launcher startup took " + (System.currentTimeMillis() - startupTime) + "ms");
  }

  private static void checkInternet() {
    String localHost = "127.0.0.1";
    try {
      localHost = InetAddress.getLocalHost().getHostAddress().toString();
    } catch (Exception e) { }
    logger.info("Localhost: " + localHost);

    // May not be online, check
    if (localHost.contains("127.0.0.1")) {
      if (pingURL("http://www.google.com") == 404) {
        JOptionPane.showMessageDialog(null, "You must have an internet connection to use Spoutcraft", "No Internet Connection!", JOptionPane.ERROR_MESSAGE);
        System.exit(0);
      } else if (pingURL("http://get.spout.org") ==  404) {
        JOptionPane.showMessageDialog(null, "The Spout webservers are currently not responding. Try again later.", "Spout Servers Down", JOptionPane.ERROR_MESSAGE);
        System.exit(0);
      } else if (pingURL("http://get.spout.org") ==  403) {
        JOptionPane.showMessageDialog(null, "Client connection rejected.  Try again later.", "Client Connection Rejected!", JOptionPane.ERROR_MESSAGE);
        System.exit(0);
      }
    }
  }

  public static int pingURL(String urlLoc) {
    try {
      final URL url = new URL(urlLoc);
      final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
      conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19");
      conn.setConnectTimeout(5000);
      int response = conn.getResponseCode();
      if (logger != null) {
        logger.info("Pinging [" + urlLoc + "], response: " + response);
      }
      return response;
    } catch (IOException e) { }
    if (logger != null) {
      logger.info("Pinged [" + urlLoc + "], no response.");
    }
    return HttpURLConnection.HTTP_NOT_FOUND;
  }

  private static void setupProxy() {
    Proxy proxy = new Proxy();
    proxy.setHost(Settings.getProxyHost());
    proxy.setPort(Settings.getProxyPort());
    proxy.setUser(Settings.getProxyUsername());
    String pass = Settings.getProxyPassword();
    proxy.setPass(pass != null ? pass.toCharArray() : null);
    proxy.setup();
  }

  private static void validateBuild(StartupParameters params) {
    if (params.getSpoutcraftBuild() > 0) {
      List<SpoutcraftBuild> builds;
      try {
        builds = SpoutcraftBuild.getBuildList();
        String build = String.valueOf(params.getSpoutcraftBuild());
        for (SpoutcraftBuild b : builds) {
          if (b.getBuildNumber().equals(build)) {
            return;
          }
        }
      } catch (RestfulAPIException e) {
        e.printStackTrace();
      }
      params.setSpoutcraftBuild(-1);
    }
  }

  private static void cleanup() {
    File temp = new File(Utils.getSystemTemporaryDirectory(), "temp.jar");
    temp.delete();
    temp = new File(Utils.getSystemTemporaryDirectory(), "temp.exe");
    temp.delete();
    temp = new File(Utils.getWorkingDirectory(), "Spoutcraft-Launcher.jar");
    temp.delete();
    temp = new File(Utils.getWorkingDirectory(), "launcherVersion");
    temp.delete();
    temp = new File(Utils.getWorkingDirectory(), "mc.patch");
    temp.delete();
    temp = new File(Utils.getWorkingDirectory(), "config/libraries.yml");
    temp.delete();
    temp = new File(Utils.getWorkingDirectory(), "config/spoutcraft.yml");
    temp.delete();
    temp = new File(Utils.getWorkingDirectory(), "config/minecraft.yml");
    temp.delete();
  }

  private static void setLookAndFeel() {
    OperatingSystem os = OperatingSystem.getOS();
    if (os.isMac()) {
      System.setProperty("apple.laf.useScreenMenuBar", "true");
      System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Spoutcraft");
    }
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Exception e) {
      logger.log(Level.WARNING, "Failed to setup look and feel", e);
    }
  }

  private static int parseInt(String s, int def) {
    try {
      return Integer.parseInt(s);
    } catch (NumberFormatException e) {
      return def;
    }
  }

  protected static Logger setupLogger() {
    final Logger logger = Logger.getLogger("launcher");
    File logDirectory = new File(Utils.getWorkingDirectory(), "logs");
    if (!logDirectory.exists()) {
      logDirectory.mkdir();
    }
    File logs = new File(logDirectory, "spoutcraft_%D.log");
    RotatingFileHandler fileHandler = new RotatingFileHandler(logs.getPath());

    fileHandler.setFormatter(new DateOutputFormatter(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")));

    for (Handler h : logger.getHandlers()) {
      logger.removeHandler(h);
    }
    logger.addHandler(fileHandler);

    SpoutcraftLauncher.handler = fileHandler;

    logger.setUseParentHandlers(false);

    System.setOut(new PrintStream(new LoggerOutputStream(Level.INFO, logger), true));
    System.setErr(new PrintStream(new LoggerOutputStream(Level.SEVERE, logger), true));

    Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
      public void uncaughtException(Thread t, Throwable e) {
          logger.log(Level.SEVERE, "Unhandled Exception in " + t, e);
      }
    });

    return logger;
  }

  public static StartupParameters setupParameters(String[] args) {
    StartupParameters params = new StartupParameters(args);
    try {
      new JCommander(params, args);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    Utils.setStartupParameters(params);

    params.setupProxy();

    return params;
  }

  public static String getLauncherBuild() {
    String build = "0";
    try {
      build = IOUtils.toString(SpoutcraftLauncher.class.getResource("/org/spoutcraft/launcher/resources/version").openStream(), "UTF-8");
    } catch (Exception e) { }
    return build;
  }

  protected static YAMLProcessor setupSettings() {
    File file = new File(Utils.getWorkingDirectory(), "config" + File.separator + "settings.yml");

    if (!file.exists()) {
      try {
        InputStream input = SpoutcraftLauncher.class.getResource("resources/settings.yml").openStream();
        if (input != null) {
          FileOutputStream output = null;
          try {
            file.getParentFile().mkdirs();
            output = new FileOutputStream(file);
            byte[] buf = new byte[8192];
            int length;

            while ((length = input.read(buf)) > 0) {
              output.write(buf, 0, length);
            }

          } catch (Exception e) {
            e.printStackTrace();
          } finally {
            try {
              input.close();
            } catch (Exception ignored) {
            }
            try {
              if (output != null) {
                output.close();
              }
            } catch (Exception e) {
            }
          }
        }
      } catch (Exception e) { }
    }

    return new YAMLProcessor(file, false, YAMLFormat.EXTENDED);
  }

  public static void flush() {
    if (handler != null) handler.flush();
  }

  public static void setupConsole() {
    if (console == null) {
      console = new ConsoleFrame(2500, true);
      console.setVisible(true);
    }
  }

  public static void destroyConsole() {
    if (console != null) {
      console.setVisible(false);
      console.dispose();
    }
  }
}

class LogFlushThread extends Thread {
  public LogFlushThread() {
    super("Log Flush Thread");
    this.setDaemon(true);
  }

  @Override
  public void run() {
    while (!this.isInterrupted()) {
      if (SpoutcraftLauncher.handler != null) {
        SpoutcraftLauncher.handler.flush();
      }
      try {
        sleep(60000);
      } catch (InterruptedException e) { }
    }
  }
}

class ShutdownThread extends Thread {
  public ShutdownThread() {
    super("Shutdown Thread");
    this.setDaemon(true);
  }

  @Override
  public void run() {
    if (SpoutcraftLauncher.handler != null) {
      SpoutcraftLauncher.handler.flush();
    }
  }
}

class LoggerOutputStream extends ByteArrayOutputStream {
  private final String separator = System.getProperty("line.separator");
  private final Level level;
  private final Logger log;

  public LoggerOutputStream(Level level, Logger log) {
    super();
    this.level = level;
    this.log = log;
  }

  @Override
  public synchronized void flush() throws IOException {
    super.flush();
    String record = this.toString();
    super.reset();

    if (record.length() > 0 && !record.equals(separator)) {
      log.logp(level, "LoggerOutputStream", "log" + level, record);
      if (SpoutcraftLauncher.console != null) {
        SpoutcraftLauncher.console.log(record + "\n");
      }
    }
  }
}

class RotatingFileHandler extends StreamHandler {
  private final SimpleDateFormat date;
  private final String logFile;
  private String filename;

  public RotatingFileHandler(String logFile) {
    this.logFile = logFile;
    date = new SimpleDateFormat("yyyy-MM-dd");
    filename = calculateFilename();
    try {
      setOutputStream(new FileOutputStream(filename, true));
    } catch (FileNotFoundException ex) {
      ex.printStackTrace();
    }
  }

  @Override
  public synchronized void flush() {
    if (!filename.equals(calculateFilename())) {
      filename = calculateFilename();
      try {
        setOutputStream(new FileOutputStream(filename, true));
      } catch (FileNotFoundException ex) {
        ex.printStackTrace();
      }
    }
    super.flush();
  }

  private String calculateFilename() {
    return logFile.replace("%D", date.format(new Date()));
  }
}

class DateOutputFormatter extends Formatter {
  private final SimpleDateFormat date;

  public DateOutputFormatter(SimpleDateFormat date) {
    this.date = date;
  }

  @Override
  public String format(LogRecord record) {
    StringBuilder builder = new StringBuilder();

    builder.append(date.format(record.getMillis()));
    builder.append(" [");
    builder.append(record.getLevel().getLocalizedName().toUpperCase());
    builder.append("] ");
    builder.append(formatMessage(record));
    builder.append('\n');

    if (record.getThrown() != null) {
      StringWriter writer = new StringWriter();
      record.getThrown().printStackTrace(new PrintWriter(writer));
      builder.append(writer.toString());
    }

    return builder.toString();
  }
}
TOP

Related Classes of org.spoutcraft.launcher.entrypoint.SpoutcraftLauncher

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.