SubServers-2/SubServers.Host/src/net/ME1312/SubServers/Host/Launch.java

321 lines
14 KiB
Java

package net.ME1312.SubServers.Host;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.xml.parsers.DocumentBuilderFactory;
import jline.console.ConsoleReader;
import jline.console.CursorBuffer;
import net.ME1312.SubServers.Host.Library.TextColor;
import net.ME1312.SubServers.Host.Library.Util;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.AnsiConsole;
import org.w3c.dom.NodeList;
/**
* SubServers.Host Launcher Class
*/
public final class Launch {
private static File dir = null;
private static Process process = null;
/**
* Prepare and launch SubServers.Host
*
* @param args Args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
if (System.getProperty("RM.subservers", "true").equalsIgnoreCase("true")) {
launch(args);
} else {
System.out.println(">> SubServers code has been disallowed to work on this machine");
System.out.println(">> Check with your provider for more information");
System.exit(1);
}
}
private static void launch(String[] args) throws Exception {
String plugins = "";
File rtdir = new File(System.getProperty("user.dir"));
File pldir = new File(rtdir, "Plugins");
dir = File.createTempFile("SubServers.Host.", ".jar");
dir.delete();
dir.mkdir();
System.out.println(">> Created " + dir.getPath().replace(File.separator, "/"));
extractJar(getCodeSourceLocation(), dir);
System.out.println(">> Extracted ~/" + getCodeSourceLocation().getName());
if (pldir.isDirectory() && pldir.listFiles().length > 0) {
for (File plugin : Arrays.asList(pldir.listFiles())) {
try {
boolean success = false;
if (getFileExtension(plugin.getName()).equalsIgnoreCase("zip")) {
InputStream stream = new FileInputStream(plugin);
Util.unzip(stream, dir);
stream.close();
success = true;
} else if (getFileExtension(plugin.getName()).equalsIgnoreCase("jar")) {
extractJar(plugin, dir);
success = true;
}
if (new File(dir, "package.xml").exists()) {
NodeList xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(dir, "package.xml")).getElementsByTagName("class");
if (xml.getLength() > 0) {
for (int i = 0; i < xml.getLength(); i++) {
plugins += ((plugins.length() == 0)?"":" ") + xml.item(i).getTextContent().replace(' ', '_');
}
}
new File(dir, "package.xml").delete();
}
if (success) System.out.println(">> Extracted ~/plugins/" + plugin.getName());
} catch (Exception e) {
System.out.println(">> Couldn't extract ~/plugins/" + plugin.getName());
e.printStackTrace();
}
}
}
ArrayList<String> arguments = new ArrayList<String>();
String javaPath = String.valueOf(System.getProperty("java.home")) + File.separator + "bin" + File.separator + "java";
arguments.add(javaPath);
arguments.addAll(getVmArgs());
arguments.add("-Dsubservers.host.runtime=" + URLEncoder.encode(dir.getPath(), "UTF-8"));
if (!plugins.equals(""))
arguments.add("-Dsubservers.host.plugins=" + URLEncoder.encode(plugins, "UTF-8"));
arguments.add("-cp");
arguments.add(dir.getPath());
arguments.add("net.ME1312.SubServers.Host.ExHost");
arguments.addAll(Arrays.asList(args));
ProcessBuilder processBuilder = new ProcessBuilder(arguments);
processBuilder.directory(new File(System.getProperty("user.dir")));
processBuilder.redirectErrorStream(true);
syncConsole(processBuilder.start());
Thread.sleep(250);
int code = process.exitValue();
process = null;
exit(code);
}
private static void syncConsole(Process process) throws Exception {
ConsoleReader console = new ConsoleReader(System.in, (System.getProperty("subservers.host.log.color", "true").equalsIgnoreCase("true"))?AnsiConsole.out:System.out);
console.setExpandEvents(false);
Launch.process = process;
try {
new Thread(() -> {
try {
String line;
BufferedWriter cmd = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
if (Launch.process != null && Launch.process.isAlive()) {
try {
stashLine(console);
console.println(">> Received request from system to shutdown");
unstashLine(console);
console.flush();
cmd.write("exit");
cmd.newLine();
cmd.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}));
while (process.isAlive() && (line = console.readLine(">")) != null) {
if (line.equals("")) continue;
cmd.write(line);
cmd.newLine();
cmd.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
String line;
BufferedReader obr = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while (process.isAlive() && (line = obr.readLine()) != null) {
stashLine(console);
if (System.getProperty("subservers.host.log.color", "true").equalsIgnoreCase("true")) {
console.println(ConsoleColor.parseColor(line) + ConsoleColor.RESET);
} else {
console.println(ConsoleColor.stripColor(line.replaceAll("\u001B\\[[;\\d]*m", "")));
}
unstashLine(console);
console.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
String line;
BufferedReader obr = new BufferedReader(new InputStreamReader(process.getInputStream()));
while (process.isAlive() && (line = obr.readLine()) != null) {
stashLine(console);
if (System.getProperty("subservers.host.log.color", "true").equalsIgnoreCase("true")) {
console.println(ConsoleColor.parseColor(line) + ConsoleColor.RESET);
} else {
console.println(ConsoleColor.stripColor(line.replaceAll("\u001B\\[[;\\d]*m", "")));
}
unstashLine(console);
console.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
stashLine(console);
}
private static void exit(int code) {
System.out.println(">> Cleaning up");
deleteDir(dir);
System.exit(code);
}
private static void extractJar(File jarFile, File dir) throws Exception {
JarFile jar = new JarFile(jarFile);
Enumeration<JarEntry> files = jar.entries();
ArrayList<JarEntry> entries = new ArrayList<JarEntry>();
while (files.hasMoreElements()) {
entries.add(files.nextElement());
}
for (JarEntry file : entries) {
File f = new File(dir, file.getName());
if (f.exists()) {
continue;
}
if (file.isDirectory()) {
f.mkdirs();
continue;
}
if (!f.getParentFile().exists()) {
f.getParentFile().mkdirs();
}
InputStream is = jar.getInputStream(file);
FileOutputStream fos = new FileOutputStream(f);
while (is.available() > 0) {
fos.write(is.read());
}
fos.close();
is.close();
}
}
private static void deleteDir(File f) {
if (f.isDirectory()) {
for (File c : f.listFiles()) {
deleteDir(c);
}
}
f.delete();
}
private static List<String> getVmArgs() {
ArrayList<String> values = new ArrayList<String>();
values.addAll(ManagementFactory.getRuntimeMXBean().getInputArguments());
return values;
}
private static File getCodeSourceLocation() {
try {
return new File(Launch.class.getProtectionDomain().getCodeSource().getLocation().toURI());
}
catch (URISyntaxException e) {
e.printStackTrace();
return null;
}
}
private static String getFileExtension(String fileName) {
String extension = "";
int i = fileName.lastIndexOf(46);
if (i >= 0) {
extension = fileName.substring(i + 1);
}
return extension;
}
private static CursorBuffer stashed;
private static void stashLine(ConsoleReader console) {
stashed = console.getCursorBuffer().copy();
try {
console.getOutput().write("\u001b[1G\u001b[K");
console.flush();
} catch (IOException e) {
// ignore
}
}
private static void unstashLine(ConsoleReader console) {
try {
console.resetPromptLine(console.getPrompt(),
stashed.toString(), stashed.cursor);
} catch (IOException e) {
// ignore
}
}
private enum ConsoleColor {
AQUA(TextColor.AQUA, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.CYAN).bold().toString()),
BLACK(TextColor.BLACK, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.BLACK).boldOff().toString()),
BLUE(TextColor.BLUE, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.BLUE).bold().toString()),
BOLD(TextColor.BOLD, Ansi.ansi().a(Ansi.Attribute.UNDERLINE_DOUBLE).toString()),
DARK_AQUA(TextColor.DARK_AQUA, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.CYAN).boldOff().toString()),
DARK_BLUE(TextColor.DARK_BLUE, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.BLUE).boldOff().toString()),
DARK_GRAY(TextColor.DARK_GRAY, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.BLACK).bold().toString()),
DARK_GREEN(TextColor.DARK_GREEN, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.GREEN).boldOff().toString()),
DARK_PURPLE(TextColor.DARK_PURPLE, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.MAGENTA).boldOff().toString()),
DARK_RED(TextColor.DARK_RED, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.RED).boldOff().toString()),
GOLD(TextColor.GOLD, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.YELLOW).boldOff().toString()),
GRAY(TextColor.GRAY, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.WHITE).boldOff().toString()),
GREEN(TextColor.GREEN, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.GREEN).bold().toString()),
ITALIC(TextColor.ITALIC, Ansi.ansi().a(Ansi.Attribute.ITALIC).toString()),
LIGHT_PURPLE(TextColor.LIGHT_PURPLE, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.MAGENTA).bold().toString()),
MAGIC(TextColor.MAGIC, Ansi.ansi().a(Ansi.Attribute.BLINK_SLOW).toString()),
RED(TextColor.RED, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.RED).bold().toString()),
RESET(TextColor.RESET, Ansi.ansi().a(Ansi.Attribute.RESET).toString()),
STRIKETHROUGH(TextColor.STRIKETHROUGH, Ansi.ansi().a(Ansi.Attribute.STRIKETHROUGH_ON).toString()),
UNDERLINE(TextColor.UNDERLINE, Ansi.ansi().a(Ansi.Attribute.UNDERLINE).toString()),
WHITE(TextColor.WHITE, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.WHITE).bold().toString()),
YELLOW(TextColor.YELLOW, Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.YELLOW).bold().toString());
private final TextColor color;
private final String value;
ConsoleColor(TextColor color, String value) {
this.color = color;
this.value = value;
}
@Override
public String toString() {
return getConsoleString();
}
public String getValue() {
return color.getValue();
}
public String getConsoleString() {
return value;
}
public static String parseColor(String str) {
for (ConsoleColor color : Arrays.asList(ConsoleColor.values())) {
str = str.replace(color.getValue(), color.getConsoleString());
}
return str;
}
public static String stripColor(String str) {
for (ConsoleColor color : Arrays.asList(ConsoleColor.values())) {
str = str.replace(color.getValue(), "");
}
return str;
}
}
}