[FEATURE] LauncherAgent переделан. (#213)

* [REFACTOR] Рефакторинг.

* [FEATURE] LauncherAgent переделан.

* [FIX] Подача нужных агенту аргументов.

* [FEATURE] Вы можете поставить листы ClientProfile модулем.

* [FIX] Скрипты gradle, для работы LauncherTest.

* [FEATURE] Система тестов - начало.

* [FIX] Perms handler для тестовю
This commit is contained in:
Zaxar163 2019-04-07 10:53:39 +03:00 committed by Gravit
parent f747ef55d1
commit 0094c3b613
17 changed files with 296 additions and 98 deletions

View file

@ -15,6 +15,7 @@
import ru.gravit.launchserver.auth.handler.MemoryAuthHandler; import ru.gravit.launchserver.auth.handler.MemoryAuthHandler;
import ru.gravit.launchserver.auth.hwid.AcceptHWIDHandler; import ru.gravit.launchserver.auth.hwid.AcceptHWIDHandler;
import ru.gravit.launchserver.auth.hwid.HWIDHandler; import ru.gravit.launchserver.auth.hwid.HWIDHandler;
import ru.gravit.launchserver.auth.permissions.DefaultPermissionsHandler;
import ru.gravit.launchserver.auth.permissions.JsonFilePermissionsHandler; import ru.gravit.launchserver.auth.permissions.JsonFilePermissionsHandler;
import ru.gravit.launchserver.auth.permissions.PermissionsHandler; import ru.gravit.launchserver.auth.permissions.PermissionsHandler;
import ru.gravit.launchserver.auth.protect.NoProtectHandler; import ru.gravit.launchserver.auth.protect.NoProtectHandler;
@ -45,6 +46,7 @@
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.ProcessBuilder.Redirect; import java.lang.ProcessBuilder.Redirect;
import java.lang.reflect.InvocationTargetException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.nio.file.*; import java.nio.file.*;
@ -308,7 +310,7 @@ public static void main(String... args) throws Throwable {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
try { try {
@SuppressWarnings("resource") @SuppressWarnings("resource")
LaunchServer launchserver = new LaunchServer(IOHelper.WORKING_DIR, args); LaunchServer launchserver = new LaunchServer(IOHelper.WORKING_DIR, false, args);
if (args.length == 0) launchserver.run(); if (args.length == 0) launchserver.run();
else { //Обработка команды else { //Обработка команды
launchserver.commandHandler.eval(args, false); launchserver.commandHandler.eval(args, false);
@ -325,6 +327,8 @@ public static void main(String... args) throws Throwable {
public final Path dir; public final Path dir;
public final boolean testEnv;
public final Path launcherLibraries; public final Path launcherLibraries;
public final Path launcherLibrariesCompile; public final Path launcherLibrariesCompile;
@ -354,6 +358,8 @@ public static void main(String... args) throws Throwable {
public final JARLauncherBinary launcherBinary; public final JARLauncherBinary launcherBinary;
public Class<? extends LauncherBinary> launcherEXEBinaryClass;
public final LauncherBinary launcherEXEBinary; public final LauncherBinary launcherEXEBinary;
// HWID ban + anti-brutforce // HWID ban + anti-brutforce
@ -397,8 +403,11 @@ public static void main(String... args) throws Throwable {
public static Gson gson; public static Gson gson;
public static GsonBuilder gsonBuilder; public static GsonBuilder gsonBuilder;
public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecException { public static Class<? extends LauncherBinary> defaultLauncherEXEBinaryClass = null;
public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException, InvalidKeySpecException {
this.dir = dir; this.dir = dir;
this.testEnv = testEnv;
taskPool = new Timer("Timered task worker thread", true); taskPool = new Timer("Timered task worker thread", true);
launcherLibraries = dir.resolve("launcher-libraries"); launcherLibraries = dir.resolve("launcher-libraries");
launcherLibrariesCompile = dir.resolve("launcher-libraries-compile"); launcherLibrariesCompile = dir.resolve("launcher-libraries-compile");
@ -422,6 +431,9 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE
// Set command handler // Set command handler
CommandHandler localCommandHandler; CommandHandler localCommandHandler;
if (testEnv)
localCommandHandler = new StdCommandHandler(false);
else
try { try {
Class.forName("jline.Terminal"); Class.forName("jline.Terminal");
@ -459,6 +471,9 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE
crc.update(publicKey.getModulus().toByteArray()); // IDEA говорит, что это Java 9 API. WTF? crc.update(publicKey.getModulus().toByteArray()); // IDEA говорит, что это Java 9 API. WTF?
LogHelper.subInfo("Modulus CRC32: 0x%08x", crc.getValue()); LogHelper.subInfo("Modulus CRC32: 0x%08x", crc.getValue());
// Load class bindings.
launcherEXEBinaryClass = defaultLauncherEXEBinaryClass;
// pre init modules // pre init modules
modulesManager = new ModulesManager(this); modulesManager = new ModulesManager(this);
modulesManager.autoload(dir.resolve("modules")); modulesManager.autoload(dir.resolve("modules"));
@ -466,7 +481,7 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE
initGson(); initGson();
// Read LaunchServer config // Read LaunchServer config
generateConfigIfNotExists(); generateConfigIfNotExists(testEnv);
LogHelper.info("Reading LaunchServer config file"); LogHelper.info("Reading LaunchServer config file");
try (BufferedReader reader = IOHelper.newReader(configFile)) { try (BufferedReader reader = IOHelper.newReader(configFile)) {
config = Launcher.gson.fromJson(reader, Config.class); config = Launcher.gson.fromJson(reader, Config.class);
@ -589,6 +604,14 @@ public static void initGson() {
} }
private LauncherBinary binary() { private LauncherBinary binary() {
if (launcherEXEBinaryClass != null) {
try {
return (LauncherBinary)launcherEXEBinaryClass.getConstructor(LaunchServer.class).newInstance(this);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
LogHelper.error(e);
}
}
try { try {
Class.forName("net.sf.launch4j.Builder"); Class.forName("net.sf.launch4j.Builder");
if (config.launch4j.enabled) return new EXEL4JLauncherBinary(this); if (config.launch4j.enabled) return new EXEL4JLauncherBinary(this);
@ -614,7 +637,7 @@ public void close() {
LogHelper.info("LaunchServer stopped"); LogHelper.info("LaunchServer stopped");
} }
private void generateConfigIfNotExists() throws IOException { private void generateConfigIfNotExists(boolean testEnv) throws IOException {
if (IOHelper.isFile(configFile)) if (IOHelper.isFile(configFile))
return; return;
@ -640,7 +663,8 @@ private void generateConfigIfNotExists() throws IOException {
new RequestTextureProvider("http://example.com/skins/%username%.png", "http://example.com/cloaks/%username%.png") new RequestTextureProvider("http://example.com/skins/%username%.png", "http://example.com/cloaks/%username%.png")
, "std")}; , "std")};
newConfig.protectHandler = new NoProtectHandler(); newConfig.protectHandler = new NoProtectHandler();
newConfig.permissionsHandler = new JsonFilePermissionsHandler(); if (testEnv) newConfig.permissionsHandler = new DefaultPermissionsHandler();
else newConfig.permissionsHandler = new JsonFilePermissionsHandler();
newConfig.legacyPort = 7240; newConfig.legacyPort = 7240;
newConfig.legacyBindAddress = "0.0.0.0"; newConfig.legacyBindAddress = "0.0.0.0";
newConfig.binaryName = "Launcher"; newConfig.binaryName = "Launcher";
@ -674,10 +698,15 @@ private void generateConfigIfNotExists() throws IOException {
newConfig.components.put("authLimiter", authLimiterComponent); newConfig.components.put("authLimiter", authLimiterComponent);
// Set server address // Set server address
if (testEnv) {
newConfig.setLegacyAddress("localhost");
newConfig.setProjectName("test");
} else {
System.out.println("LaunchServer address: "); System.out.println("LaunchServer address: ");
newConfig.setLegacyAddress(commandHandler.readLine()); newConfig.setLegacyAddress(commandHandler.readLine());
System.out.println("LaunchServer projectName: "); System.out.println("LaunchServer projectName: ");
newConfig.setProjectName(commandHandler.readLine()); newConfig.setProjectName(commandHandler.readLine());
}
// Write LaunchServer config // Write LaunchServer config
LogHelper.info("Writing LaunchServer config file"); LogHelper.info("Writing LaunchServer config file");
@ -686,10 +715,13 @@ private void generateConfigIfNotExists() throws IOException {
} }
} }
public Collection<ClientProfile> getProfiles() { public List<ClientProfile> getProfiles() {
return profilesList; return profilesList;
} }
public void setProfiles(List<ClientProfile> profilesList) {
this.profilesList = Collections.unmodifiableList(profilesList);
}
public SignedObjectHolder<HashedDir> getUpdateDir(String name) { public SignedObjectHolder<HashedDir> getUpdateDir(String name) {
return updatesDirMap.get(name); return updatesDirMap.get(name);
@ -717,8 +749,10 @@ public void run() {
throw new IllegalStateException("LaunchServer has been already started"); throw new IllegalStateException("LaunchServer has been already started");
// Add shutdown hook, then start LaunchServer // Add shutdown hook, then start LaunchServer
if (!this.testEnv) {
JVMHelper.RUNTIME.addShutdownHook(CommonHelper.newThread(null, false, this::close)); JVMHelper.RUNTIME.addShutdownHook(CommonHelper.newThread(null, false, this::close));
CommonHelper.newThread("Command Thread", true, commandHandler).start(); CommonHelper.newThread("Command Thread", true, commandHandler).start();
}
rebindServerSocket(); rebindServerSocket();
if (config.netty != null) if (config.netty != null)
rebindNettyServerSocket(); rebindNettyServerSocket();

View file

@ -28,6 +28,7 @@
dependencies { dependencies {
pack project(':LauncherAPI') // Not error on obf. pack project(':LauncherAPI') // Not error on obf.
bundle 'com.github.oshi:oshi-core:3.13.0' bundle 'com.github.oshi:oshi-core:3.13.0'
bundle 'org.ow2.asm:asm-tree:7.1'
} }
task genRuntimeJS(type: Zip) { task genRuntimeJS(type: Zip) {

View file

@ -40,7 +40,7 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
JVMHelper.addSystemPropertyToArgs(args, DirBridge.USE_OPTDIR_PROPERTY); JVMHelper.addSystemPropertyToArgs(args, DirBridge.USE_OPTDIR_PROPERTY);
Collections.addAll(args, MAGIC_ARG); Collections.addAll(args, MAGIC_ARG);
Collections.addAll(args, "-XX:+DisableAttachMechanism"); Collections.addAll(args, "-XX:+DisableAttachMechanism");
Collections.addAll(args, "-javaagent:".concat(pathLauncher)); Collections.addAll(args, "-javaagent:".concat(pathLauncher).concat("=pr"));
Collections.addAll(args, "-cp"); Collections.addAll(args, "-cp");
Collections.addAll(args, pathLauncher); Collections.addAll(args, pathLauncher);
Collections.addAll(args, LauncherEngine.class.getName()); Collections.addAll(args, LauncherEngine.class.getName());

View file

@ -0,0 +1,159 @@
package ru.gravit.launcher;
import ru.gravit.utils.helper.LogHelper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.instrument.Instrumentation;
import java.util.jar.JarFile;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodNode;
import static org.objectweb.asm.Opcodes.*;
@LauncherAPI
public final class LauncherAgent {
private static boolean isAgentStarted = false;
public static Instrumentation inst;
public static void addJVMClassPath(String path) throws IOException {
LogHelper.debug("Launcher Agent addJVMClassPath");
inst.appendToSystemClassLoaderSearch(new JarFile(path));
}
public boolean isAgentStarted() {
return isAgentStarted;
}
public static void premain(String agentArgument, Instrumentation instrumentation) {
System.out.println("Launcher Agent");
inst = instrumentation;
isAgentStarted = true;
boolean pb = true;
boolean rt = true;
if (agentArgument != null) {
String trimmedArg = agentArgument.trim();
if (!trimmedArg.isEmpty()) {
if (trimmedArg.contains("p")) pb = false;
if (trimmedArg.contains("r")) rt = false;
}
}
replaceClasses(pb, rt);
}
public static boolean isStarted() {
return isAgentStarted;
}
/**
* @author https://github.com/Konloch/JVM-Sandbox
* Replaces the Runtime class via instrumentation, transforms the class via ASM
*/
public static void replaceClasses(boolean pb, boolean rt) {
for(Class<?> c : inst.getAllLoadedClasses()) {
if(rt && c.getName().equals("java.lang.Runtime")) {
try {
inst.redefineClasses(new java.lang.instrument.ClassDefinition(java.lang.Runtime.class, transformClass(c.getName(), getClassFile(c))));
} catch(Exception e) {
e.printStackTrace();
}
}
if(pb && c.getName().equals("java.lang.ProcessBuilder")) {
try {
inst.redefineClasses(new java.lang.instrument.ClassDefinition(java.lang.ProcessBuilder.class, transformClass(c.getName(), getClassFile(c))));
} catch(Exception e) {
e.printStackTrace();
}
}
if(c.getName().equals("java.awt.Robot")) {
try {
inst.redefineClasses(new java.lang.instrument.ClassDefinition(java.lang.ProcessBuilder.class, transformClass(c.getName(), getClassFile(c))));
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
/**
* @author https://github.com/Konloch/JVM-Sandbox
* Use ASM to modify the byte array
*/
public static byte[] transformClass(String className, byte[] classBytes) {
if (className.equals("java.lang.Runtime")) {
ClassReader cr=new ClassReader(classBytes);
ClassNode cn=new ClassNode();
cr.accept(cn,ClassReader.EXPAND_FRAMES);
for (Object o : cn.methods.toArray()) {
MethodNode m = (MethodNode) o;
if(m.name.equals("exec")) {
m.instructions.insert(new InsnNode(ARETURN));
m.instructions.insert(new InsnNode(ACONST_NULL));
}
}
ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
return cw.toByteArray();
} else if (className.equals("java.lang.ProcessBuilder")) {
ClassReader cr=new ClassReader(classBytes);
ClassNode cn=new ClassNode();
cr.accept(cn,ClassReader.EXPAND_FRAMES);
for (Object o : cn.methods.toArray()) {
MethodNode m = (MethodNode) o;
if(m.name.equals("start")) {
m.instructions.insert(new InsnNode(ARETURN));
m.instructions.insert(new InsnNode(ACONST_NULL));
}
}
ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
return cw.toByteArray();
} else if (className.equals("java.awt.Robot")) {
ClassReader cr=new ClassReader(classBytes);
ClassNode cn=new ClassNode();
cr.accept(cn,ClassReader.EXPAND_FRAMES);
for (Object o : cn.methods.toArray()) {
MethodNode m = (MethodNode) o;
if( m.name.equals("createScreenCapture") || m.name.equals("getPixelColor") ||
m.name.equals("keyPress") || m.name.equals("keyRelease") ||
m.name.equals("mouseMove") || m.name.equals("mousePress") ||
m.name.equals("mouseWheel"))
{
m.instructions.insert(new InsnNode(ARETURN));
m.instructions.insert(new InsnNode(ACONST_NULL));
}
}
ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
return cw.toByteArray();
}
return classBytes;
}
/**
* @author https://github.com/Konloch/JVM-Sandbox
* Do not remove this method. Do not to cause classloading!
* Grab the byte array from the loaded Class object
* @param clazz
* @return array, respending this class in bytecode.
* @throws IOException
*/
public static byte[] getClassFile(Class<?> clazz) throws IOException {
InputStream is = clazz.getResourceAsStream( "/" + clazz.getName().replace('.', '/') + ".class");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int r = 0;
byte[] buffer = new byte[8192];
while((r=is.read(buffer))>=0) {
baos.write(buffer, 0, r);
}
return baos.toByteArray();
}
}

View file

@ -14,7 +14,6 @@
import ru.gravit.launcher.request.websockets.RequestInterface; import ru.gravit.launcher.request.websockets.RequestInterface;
import ru.gravit.launcher.serialize.signed.SignedObjectHolder; import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;

View file

@ -8,12 +8,10 @@
import ru.gravit.launcher.request.websockets.RequestInterface; import ru.gravit.launcher.request.websockets.RequestInterface;
public class SetProfileRequest extends Request<SetProfileRequestEvent> implements RequestInterface { public class SetProfileRequest extends Request<SetProfileRequestEvent> implements RequestInterface {
private transient ClientProfile profile;
@LauncherNetworkAPI @LauncherNetworkAPI
public String client; public String client;
public SetProfileRequest(ClientProfile profile) { public SetProfileRequest(ClientProfile profile) {
this.profile = profile;
this.client = profile.getTitle(); this.client = profile.getTitle();
} }

View file

@ -10,7 +10,6 @@
import ru.gravit.launcher.hasher.HashedEntry; import ru.gravit.launcher.hasher.HashedEntry;
import ru.gravit.launcher.hasher.HashedFile; import ru.gravit.launcher.hasher.HashedFile;
import ru.gravit.launcher.request.Request; import ru.gravit.launcher.request.Request;
import ru.gravit.launcher.request.UpdateAction;
import ru.gravit.launcher.request.update.UpdateRequest.State.Callback; import ru.gravit.launcher.request.update.UpdateRequest.State.Callback;
import ru.gravit.launcher.request.websockets.LegacyRequestBridge; import ru.gravit.launcher.request.websockets.LegacyRequestBridge;
import ru.gravit.launcher.request.websockets.RequestInterface; import ru.gravit.launcher.request.websockets.RequestInterface;
@ -26,7 +25,6 @@
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Objects; import java.util.Objects;
import java.util.Queue;
public final class UpdateRequest extends Request<UpdateRequestEvent> implements RequestInterface { public final class UpdateRequest extends Request<UpdateRequestEvent> implements RequestInterface {
@ -168,26 +166,6 @@ public double getTotalSizeMiB() {
} }
} }
private static void fillActionsQueue(Queue<UpdateAction> queue, HashedDir mismatch) {
for (Entry<String, HashedEntry> mapEntry : mismatch.map().entrySet()) {
String name = mapEntry.getKey();
HashedEntry entry = mapEntry.getValue();
HashedEntry.Type entryType = entry.getType();
switch (entryType) {
case DIR: // cd - get - cd ..
queue.add(new UpdateAction(UpdateAction.Type.CD, name, entry));
fillActionsQueue(queue, (HashedDir) entry);
queue.add(UpdateAction.CD_BACK);
break;
case FILE: // get
queue.add(new UpdateAction(UpdateAction.Type.GET, name, entry));
break;
default:
throw new AssertionError("Unsupported hashed entry type: " + entryType.name());
}
}
}
@Override @Override
public UpdateRequestEvent requestDo() throws Exception { public UpdateRequestEvent requestDo() throws Exception {
LogHelper.debug("Start update request"); LogHelper.debug("Start update request");

View file

@ -0,0 +1,23 @@
package ru.gravit.launcher.test.utils;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.launchserver.binary.LauncherBinary;
import ru.gravit.utils.helper.IOHelper;
import java.io.IOException;
import java.nio.file.Files;
public class EXENonWarningLauncherBinary extends LauncherBinary {
public EXENonWarningLauncherBinary(LaunchServer server) {
super(server, server.dir.resolve(server.config.binaryName + ".exe"));
}
@Override
public void build() throws IOException {
if (IOHelper.isFile(syncBinaryFile)) {
Files.delete(syncBinaryFile);
}
}
}

View file

@ -0,0 +1,36 @@
package ru.gravit.launcher;
import java.io.IOException;
import java.nio.file.Path;
import java.security.spec.InvalidKeySpecException;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import ru.gravit.launcher.test.utils.EXENonWarningLauncherBinary;
import ru.gravit.launchserver.LaunchServer;
import ru.gravit.utils.helper.LogHelper;
public class StartTest {
@TempDir
public Path dir;
@BeforeAll
public static void prepare() {
LogHelper.removeStdOutput();
LaunchServer.defaultLauncherEXEBinaryClass = EXENonWarningLauncherBinary.class;
}
@Test
public void checkLaunchServerStarts() {
try {
LaunchServer srv = new LaunchServer(dir, true, new String[] { "checkInstall" });
srv.run();
srv.commandHandler.eval(new String[] { "checkInstall" }, false);
srv.close();
} catch (InvalidKeySpecException | IOException e) {
throw new RuntimeException(e);
}
}
}

2
Radon

@ -1 +1 @@
Subproject commit e1f7548f97132fa29b01f68bd57ffab32de7b6e7 Subproject commit e6974532efc7228a8b826a8cd9e1f1f7b609659f

View file

@ -37,7 +37,7 @@ public class ServerWrapper extends JsonConfigurable<ServerWrapper.Config> {
public ClassLoader loader; public ClassLoader loader;
public ClientPermissions permissions; public ClientPermissions permissions;
public static ServerWrapper wrapper; public static ServerWrapper wrapper;
private static Gson gson; public static Gson gson;
private static GsonBuilder gsonBuiler; private static GsonBuilder gsonBuiler;
public static Path modulesDir = Paths.get(System.getProperty("serverwrapper.modulesDir", "modules")); public static Path modulesDir = Paths.get(System.getProperty("serverwrapper.modulesDir", "modules"));

View file

@ -1,6 +1,5 @@
package ru.gravit.launcher.server.setup; package ru.gravit.launcher.server.setup;
import ru.gravit.launcher.LauncherConfig;
import ru.gravit.launcher.server.ServerWrapper; import ru.gravit.launcher.server.ServerWrapper;
import ru.gravit.utils.PublicURLClassLoader; import ru.gravit.utils.PublicURLClassLoader;
import ru.gravit.utils.helper.IOHelper; import ru.gravit.utils.helper.IOHelper;
@ -24,21 +23,23 @@ public void run() throws IOException {
System.out.println("Print jar filename:"); System.out.println("Print jar filename:");
String jarName = commands.commandHandler.readLine(); String jarName = commands.commandHandler.readLine();
Path jarPath = Paths.get(jarName); Path jarPath = Paths.get(jarName);
JarFile file = new JarFile(jarPath.toFile()); String mainClassName = null;
try (JarFile file = new JarFile(jarPath.toFile())) {
URL jarURL = jarPath.toUri().toURL(); URL jarURL = jarPath.toUri().toURL();
urlClassLoader = new PublicURLClassLoader(new URL[]{jarURL}); urlClassLoader = new PublicURLClassLoader(new URL[]{jarURL});
LogHelper.info("Check jar MainClass"); LogHelper.info("Check jar MainClass");
String mainClassName = file.getManifest().getMainAttributes().getValue("Main-Class"); mainClassName = file.getManifest().getMainAttributes().getValue("Main-Class");
if (mainClassName == null) { if (mainClassName == null) {
LogHelper.error("Main-Class not found in MANIFEST"); LogHelper.error("Main-Class not found in MANIFEST");
return; return;
} }
try { try {
Class mainClass = Class.forName(mainClassName, false, urlClassLoader); Class.forName(mainClassName, false, urlClassLoader);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
LogHelper.error(e); LogHelper.error(e);
return; return;
} }
}
LogHelper.info("Found MainClass %s", mainClassName); LogHelper.info("Found MainClass %s", mainClassName);
System.out.println("Print launchserver websocket host:"); System.out.println("Print launchserver websocket host:");
String address = commands.commandHandler.readLine(); String address = commands.commandHandler.readLine();
@ -66,7 +67,6 @@ public void run() throws IOException {
wrapper.config.password = password; wrapper.config.password = password;
wrapper.config.title = title; wrapper.config.title = title;
wrapper.config.stopOnError = false; wrapper.config.stopOnError = false;
LauncherConfig cfg = null;
if (wrapper.auth()) { if (wrapper.auth()) {
break; break;

View file

@ -1,32 +0,0 @@
package ru.gravit.launcher;
import ru.gravit.utils.helper.LogHelper;
import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.util.jar.JarFile;
@LauncherAPI
public final class LauncherAgent {
private static boolean isAgentStarted = false;
public static Instrumentation inst;
public static void addJVMClassPath(String path) throws IOException {
LogHelper.debug("Launcher Agent addJVMClassPath");
inst.appendToSystemClassLoaderSearch(new JarFile(path));
}
public boolean isAgentStarted() {
return isAgentStarted;
}
public static void premain(String agentArgument, Instrumentation instrumentation) {
System.out.println("Launcher Agent");
inst = instrumentation;
isAgentStarted = true;
}
public static boolean isStarted() {
return isAgentStarted;
}
}

View file

@ -9,6 +9,7 @@
import java.util.HashMap; import java.util.HashMap;
import java.util.Objects; import java.util.Objects;
@SuppressWarnings("rawtypes")
public class ConfigManager { public class ConfigManager {
private final HashMap<String, JsonConfigurable> CONFIGURABLE = new HashMap<>(); private final HashMap<String, JsonConfigurable> CONFIGURABLE = new HashMap<>();

View file

@ -7,6 +7,7 @@
include 'ServerWrapper' include 'ServerWrapper'
include 'LaunchServer' include 'LaunchServer'
include 'LaunchServerConsole' include 'LaunchServerConsole'
include 'LauncherTest'
include 'modules' include 'modules'
file('modules').eachDir { sub -> file('modules').eachDir { sub ->
if (sub.name.endsWith('_module')) include 'modules:' + sub.name if (sub.name.endsWith('_module')) include 'modules:' + sub.name