2017-04-01 07:37:48 +02:00
|
|
|
package net.ME1312.SubServers.Host.Executable;
|
|
|
|
|
2020-06-12 07:45:49 +02:00
|
|
|
import net.ME1312.Galaxi.Library.Container.Container;
|
2018-09-09 00:06:21 +02:00
|
|
|
import net.ME1312.Galaxi.Library.UniversalFile;
|
|
|
|
import net.ME1312.Galaxi.Library.Util;
|
|
|
|
import net.ME1312.Galaxi.Library.Version.Version;
|
2019-05-13 05:28:27 +02:00
|
|
|
import net.ME1312.SubData.Client.SubDataClient;
|
2019-08-30 21:44:54 +02:00
|
|
|
import net.ME1312.SubServers.Host.ExHost;
|
2017-04-01 07:37:48 +02:00
|
|
|
import net.ME1312.SubServers.Host.Library.Exception.InvalidServerException;
|
2019-06-17 05:13:48 +02:00
|
|
|
import net.ME1312.SubServers.Host.Network.Packet.PacketExEditServer;
|
2019-01-06 07:58:13 +01:00
|
|
|
import net.ME1312.SubServers.Host.SubAPI;
|
2017-04-01 07:37:48 +02:00
|
|
|
|
|
|
|
import java.io.*;
|
|
|
|
import java.util.LinkedList;
|
|
|
|
import java.util.UUID;
|
|
|
|
import java.util.jar.JarFile;
|
2018-07-17 09:10:17 +02:00
|
|
|
import java.util.jar.JarInputStream;
|
2017-04-01 07:37:48 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Internal SubServer Class
|
|
|
|
*/
|
2019-08-30 02:01:52 +02:00
|
|
|
public class SubServerImpl {
|
2017-04-16 19:02:14 +02:00
|
|
|
private ExHost host;
|
2017-04-01 07:37:48 +02:00
|
|
|
private String name;
|
|
|
|
private boolean enabled;
|
2018-10-08 01:25:08 +02:00
|
|
|
private int port;
|
2017-04-01 07:37:48 +02:00
|
|
|
private Container<Boolean> log;
|
|
|
|
private String dir;
|
|
|
|
private File directory;
|
2019-01-04 22:51:58 +01:00
|
|
|
private String executable;
|
2017-04-01 07:37:48 +02:00
|
|
|
private Process process;
|
2019-08-30 21:44:54 +02:00
|
|
|
private SubLoggerImpl logger;
|
2017-04-01 07:37:48 +02:00
|
|
|
private Thread thread;
|
|
|
|
private BufferedWriter command;
|
|
|
|
private LinkedList<String> queue;
|
|
|
|
private String stopcmd;
|
|
|
|
private boolean allowrestart;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a SubServer
|
|
|
|
*
|
|
|
|
* @param host SubServers.Host
|
|
|
|
* @param name Name
|
|
|
|
* @param enabled Enabled Status
|
|
|
|
* @param log Logging Status
|
|
|
|
* @param directory Directory
|
|
|
|
* @param executable Executable String
|
|
|
|
* @param stopcmd Stop Command
|
|
|
|
* @throws InvalidServerException
|
|
|
|
*/
|
2019-08-30 02:01:52 +02:00
|
|
|
public SubServerImpl(ExHost host, String name, boolean enabled, int port, boolean log, String directory, String executable, String stopcmd) throws InvalidServerException {
|
2017-04-01 07:37:48 +02:00
|
|
|
if (Util.isNull(host, name, enabled, log, directory, executable)) throw new NullPointerException();
|
|
|
|
this.host = host;
|
|
|
|
this.name = name;
|
|
|
|
this.enabled = enabled;
|
2018-10-08 01:25:08 +02:00
|
|
|
this.port = port;
|
2017-04-01 07:37:48 +02:00
|
|
|
this.log = new Container<Boolean>(log);
|
|
|
|
this.dir = directory;
|
|
|
|
this.directory = new File(host.host.getRawString("Directory"), directory);
|
|
|
|
this.executable = executable;
|
|
|
|
this.process = null;
|
2019-08-30 21:44:54 +02:00
|
|
|
this.logger = new SubLoggerImpl(null, this, name, null, this.log, null);
|
2017-04-01 07:37:48 +02:00
|
|
|
this.thread = null;
|
|
|
|
this.command = null;
|
|
|
|
this.queue = new LinkedList<String>();
|
|
|
|
this.stopcmd = stopcmd;
|
|
|
|
|
|
|
|
if (new UniversalFile(this.directory, "plugins:SubServers.Client.jar").exists()) {
|
|
|
|
try {
|
2018-07-17 09:10:17 +02:00
|
|
|
JarInputStream updated = new JarInputStream(ExHost.class.getResourceAsStream("/net/ME1312/SubServers/Host/Library/Files/client.jar"));
|
|
|
|
JarFile existing = new JarFile(new UniversalFile(this.directory, "plugins:SubServers.Client.jar"));
|
|
|
|
|
2018-07-27 21:36:51 +02:00
|
|
|
if (existing.getManifest().getMainAttributes().getValue("Implementation-Title") != null && existing.getManifest().getMainAttributes().getValue("Implementation-Title").startsWith("SubServers.Client") && existing.getManifest().getMainAttributes().getValue("Specification-Title") != null &&
|
|
|
|
updated.getManifest().getMainAttributes().getValue("Implementation-Title") != null && updated.getManifest().getMainAttributes().getValue("Implementation-Title").startsWith("SubServers.Client") && updated.getManifest().getMainAttributes().getValue("Specification-Title") != null) {
|
2018-07-17 09:10:17 +02:00
|
|
|
if (new Version(existing.getManifest().getMainAttributes().getValue("Specification-Title")).compareTo(new Version(updated.getManifest().getMainAttributes().getValue("Specification-Title"))) < 0) {
|
|
|
|
new UniversalFile(this.directory, "plugins:SubServers.Client.jar").delete();
|
|
|
|
Util.copyFromJar(ExHost.class.getClassLoader(), "net/ME1312/SubServers/Host/Library/Files/client.jar", new UniversalFile(this.directory, "plugins:SubServers.Client.jar").getPath());
|
|
|
|
}
|
2017-04-01 07:37:48 +02:00
|
|
|
}
|
2018-07-17 09:10:17 +02:00
|
|
|
existing.close();
|
|
|
|
updated.close();
|
2018-07-23 05:44:20 +02:00
|
|
|
} catch (Throwable e) {
|
|
|
|
host.log.info.println("Couldn't auto-update SubServers.Client.jar for " + name);
|
|
|
|
host.log.error.println(e);
|
|
|
|
}
|
|
|
|
} else if (new UniversalFile(this.directory, "mods:SubServers.Client.jar").exists()) {
|
|
|
|
try {
|
|
|
|
JarInputStream updated = new JarInputStream(ExHost.class.getResourceAsStream("/net/ME1312/SubServers/Host/Library/Files/client.jar"));
|
|
|
|
JarFile existing = new JarFile(new UniversalFile(this.directory, "mods:SubServers.Client.jar"));
|
|
|
|
|
2018-07-27 21:36:51 +02:00
|
|
|
if (existing.getManifest().getMainAttributes().getValue("Implementation-Title") != null && existing.getManifest().getMainAttributes().getValue("Implementation-Title").startsWith("SubServers.Client") && existing.getManifest().getMainAttributes().getValue("Specification-Title") != null &&
|
|
|
|
updated.getManifest().getMainAttributes().getValue("Implementation-Title") != null && updated.getManifest().getMainAttributes().getValue("Implementation-Title").startsWith("SubServers.Client") && updated.getManifest().getMainAttributes().getValue("Specification-Title") != null) {
|
2018-07-23 05:44:20 +02:00
|
|
|
if (new Version(existing.getManifest().getMainAttributes().getValue("Specification-Title")).compareTo(new Version(updated.getManifest().getMainAttributes().getValue("Specification-Title"))) < 0) {
|
|
|
|
new UniversalFile(this.directory, "mods:SubServers.Client.jar").delete();
|
|
|
|
Util.copyFromJar(ExHost.class.getClassLoader(), "net/ME1312/SubServers/Host/Library/Files/client.jar", new UniversalFile(this.directory, "mods:SubServers.Client.jar").getPath());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
existing.close();
|
|
|
|
updated.close();
|
2017-04-01 07:37:48 +02:00
|
|
|
} catch (Throwable e) {
|
2018-07-17 09:10:17 +02:00
|
|
|
host.log.info.println("Couldn't auto-update SubServers.Client.jar for " + name);
|
2017-04-01 07:37:48 +02:00
|
|
|
host.log.error.println(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void run() {
|
|
|
|
boolean falsestart = true;
|
|
|
|
allowrestart = true;
|
|
|
|
try {
|
2019-01-17 16:39:15 +01:00
|
|
|
ProcessBuilder pb = new ProcessBuilder().command(Executable.parse(host.host.getRawString("Git-Bash"), executable)).directory(directory);
|
2019-12-18 20:15:02 +01:00
|
|
|
pb.environment().put("java", System.getProperty("java.home") + File.separator + "bin" + File.separator + "java");
|
2019-01-17 16:39:15 +01:00
|
|
|
pb.environment().put("name", getName());
|
2019-05-13 05:28:27 +02:00
|
|
|
if (SubAPI.getInstance().getSubDataNetwork()[0] != null) pb.environment().put("host", SubAPI.getInstance().getName());
|
|
|
|
pb.environment().put("address", host.config.get().getMap("Settings").getRawString("Server-Bind"));
|
2019-01-17 16:39:15 +01:00
|
|
|
pb.environment().put("port", Integer.toString(getPort()));
|
|
|
|
process = pb.start();
|
2017-04-01 07:37:48 +02:00
|
|
|
falsestart = false;
|
|
|
|
host.log.info.println("Now starting " + name);
|
|
|
|
logger.process = process;
|
|
|
|
logger.start();
|
|
|
|
command = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
|
|
|
|
for (String command : queue) if (process.isAlive()) {
|
|
|
|
this.command.write(command);
|
|
|
|
this.command.newLine();
|
|
|
|
this.command.flush();
|
|
|
|
}
|
|
|
|
queue.clear();
|
|
|
|
|
|
|
|
if (process.isAlive()) process.waitFor();
|
|
|
|
} catch (IOException | InterruptedException e) {
|
2017-04-03 19:52:28 +02:00
|
|
|
host.log.error.println(e);
|
2017-04-01 07:37:48 +02:00
|
|
|
allowrestart = false;
|
2019-06-17 05:13:48 +02:00
|
|
|
if (falsestart) ((SubDataClient) SubAPI.getInstance().getSubDataNetwork()[0]).sendPacket(new PacketExEditServer(this, PacketExEditServer.UpdateType.LAUNCH_EXCEPTION));
|
2017-04-01 07:37:48 +02:00
|
|
|
}
|
|
|
|
|
2019-08-30 02:01:52 +02:00
|
|
|
if (SubAPI.getInstance().getSubDataNetwork()[0] != null)
|
|
|
|
((SubDataClient) SubAPI.getInstance().getSubDataNetwork()[0]).sendPacket(new PacketExEditServer(this, PacketExEditServer.UpdateType.STOPPED, (Integer) process.exitValue(), (Boolean) allowrestart));
|
2017-04-01 07:37:48 +02:00
|
|
|
host.log.info.println(name + " has stopped");
|
|
|
|
process = null;
|
|
|
|
command = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts the Server
|
|
|
|
*
|
|
|
|
* @param address External Logging Address
|
|
|
|
*/
|
|
|
|
public void start(UUID address) {
|
|
|
|
if (isEnabled() && !(thread != null && thread.isAlive())) {
|
|
|
|
logger.address = address;
|
2019-01-06 07:58:13 +01:00
|
|
|
(thread = new Thread(this::run, SubAPI.getInstance().getAppInfo().getName() + "::Server_Process_Handler(" + name + ')')).start();
|
2017-04-01 07:37:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stops the Server
|
|
|
|
*/
|
|
|
|
public void stop() {
|
|
|
|
if (thread != null && thread.isAlive()) {
|
|
|
|
try {
|
|
|
|
allowrestart = false;
|
|
|
|
if (process != null && process.isAlive()) {
|
|
|
|
command.write(stopcmd);
|
|
|
|
command.newLine();
|
|
|
|
command.flush();
|
|
|
|
}
|
|
|
|
} catch (IOException e) {
|
2017-04-03 19:52:28 +02:00
|
|
|
host.log.error.println(e);
|
2017-04-01 07:37:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Terminates the Server
|
|
|
|
*/
|
|
|
|
public void terminate() {
|
|
|
|
allowrestart = false;
|
2019-01-09 18:37:02 +01:00
|
|
|
if (process != null && process.isAlive()) Executable.terminate(process);
|
2017-04-01 07:37:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Commands the Server
|
|
|
|
*
|
|
|
|
* @param command Command to Send
|
|
|
|
*/
|
|
|
|
public void command(String command) {
|
|
|
|
if (Util.isNull(command)) throw new NullPointerException();
|
|
|
|
if (thread != null && thread.isAlive()) {
|
|
|
|
try {
|
|
|
|
if (command.equalsIgnoreCase(stopcmd)) allowrestart = false;
|
|
|
|
if (process != null && process.isAlive()) {
|
|
|
|
this.command.write(command);
|
|
|
|
this.command.newLine();
|
|
|
|
this.command.flush();
|
|
|
|
}
|
|
|
|
} catch (IOException e) {
|
2017-04-03 19:52:28 +02:00
|
|
|
host.log.error.println(e);
|
2017-04-01 07:37:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Waits for the Server to Stop
|
|
|
|
*
|
|
|
|
* @throws InterruptedException
|
|
|
|
*/
|
|
|
|
public void waitFor() throws InterruptedException {
|
|
|
|
while (thread != null && thread.isAlive()) {
|
|
|
|
Thread.sleep(250);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the name of the Server
|
|
|
|
*
|
|
|
|
* @return Server Name
|
|
|
|
*/
|
|
|
|
public String getName() {
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the Server is Running
|
|
|
|
*
|
|
|
|
* @return Running Status
|
|
|
|
*/
|
|
|
|
public boolean isRunning() {
|
|
|
|
return process != null && process.isAlive();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the Server is Enabled
|
|
|
|
*
|
|
|
|
* @return Enabled Status
|
|
|
|
*/
|
|
|
|
public boolean isEnabled() {
|
|
|
|
return enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set if the Server is Enabled
|
|
|
|
*
|
|
|
|
* @param value Value
|
|
|
|
*/
|
|
|
|
public void setEnabled(boolean value) {
|
|
|
|
if (Util.isNull(value)) throw new NullPointerException();
|
|
|
|
enabled = value;
|
|
|
|
}
|
|
|
|
|
2018-10-08 01:25:08 +02:00
|
|
|
/**
|
|
|
|
* Get the Port of the Server
|
|
|
|
*
|
|
|
|
* @return Server Port Number
|
|
|
|
*/
|
|
|
|
public int getPort() {
|
|
|
|
return port;
|
|
|
|
}
|
|
|
|
|
2017-04-01 07:37:48 +02:00
|
|
|
/**
|
|
|
|
* If the Server is Logging
|
|
|
|
*
|
|
|
|
* @return Logging Status
|
|
|
|
*/
|
|
|
|
public boolean isLogging() {
|
|
|
|
return log.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set if the Server is Logging
|
|
|
|
*
|
|
|
|
* @param value Value
|
|
|
|
*/
|
|
|
|
public void setLogging(boolean value) {
|
|
|
|
if (Util.isNull(value)) throw new NullPointerException();
|
|
|
|
log.set(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get Process Logger
|
|
|
|
*/
|
2019-08-30 21:44:54 +02:00
|
|
|
public SubLoggerImpl getLogger() {
|
2017-04-01 07:37:48 +02:00
|
|
|
return logger;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the Server Directory
|
|
|
|
*
|
|
|
|
* @return Server Directory
|
|
|
|
*/
|
|
|
|
public String getDirectory() {
|
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
2019-08-30 02:01:52 +02:00
|
|
|
/**
|
|
|
|
* Get the Server's Executable String
|
|
|
|
*
|
|
|
|
* @return Executable String
|
|
|
|
*/
|
|
|
|
public String getExecutable() {
|
|
|
|
return executable;
|
|
|
|
}
|
|
|
|
|
2017-04-01 07:37:48 +02:00
|
|
|
/**
|
|
|
|
* Grab the Command to Stop the Server
|
|
|
|
*
|
|
|
|
* @return Stop Command
|
|
|
|
*/
|
|
|
|
public String getStopCommand() {
|
|
|
|
return stopcmd;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the Command that Stops the Server
|
|
|
|
*
|
|
|
|
* @param value Value
|
|
|
|
*/
|
|
|
|
public void setStopCommand(String value) {
|
|
|
|
if (Util.isNull(value)) throw new NullPointerException();
|
|
|
|
stopcmd = value;
|
|
|
|
}
|
|
|
|
}
|