mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-22 08:31:07 +03:00
[FEATURE] LauncherAgent переделан. (#213)
* [REFACTOR] Рефакторинг. * [FEATURE] LauncherAgent переделан. * [FIX] Подача нужных агенту аргументов. * [FEATURE] Вы можете поставить листы ClientProfile модулем. * [FIX] Скрипты gradle, для работы LauncherTest. * [FEATURE] Система тестов - начало. * [FIX] Perms handler для тестовю
This commit is contained in:
parent
f747ef55d1
commit
0094c3b613
17 changed files with 296 additions and 98 deletions
|
@ -15,6 +15,7 @@
|
|||
import ru.gravit.launchserver.auth.handler.MemoryAuthHandler;
|
||||
import ru.gravit.launchserver.auth.hwid.AcceptHWIDHandler;
|
||||
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.PermissionsHandler;
|
||||
import ru.gravit.launchserver.auth.protect.NoProtectHandler;
|
||||
|
@ -45,6 +46,7 @@
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ProcessBuilder.Redirect;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.file.*;
|
||||
|
@ -308,7 +310,7 @@ public static void main(String... args) throws Throwable {
|
|||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
@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();
|
||||
else { //Обработка команды
|
||||
launchserver.commandHandler.eval(args, false);
|
||||
|
@ -325,6 +327,8 @@ public static void main(String... args) throws Throwable {
|
|||
|
||||
public final Path dir;
|
||||
|
||||
public final boolean testEnv;
|
||||
|
||||
public final Path launcherLibraries;
|
||||
|
||||
public final Path launcherLibrariesCompile;
|
||||
|
@ -354,6 +358,8 @@ public static void main(String... args) throws Throwable {
|
|||
|
||||
public final JARLauncherBinary launcherBinary;
|
||||
|
||||
public Class<? extends LauncherBinary> launcherEXEBinaryClass;
|
||||
|
||||
public final LauncherBinary launcherEXEBinary;
|
||||
// HWID ban + anti-brutforce
|
||||
|
||||
|
@ -397,8 +403,11 @@ public static void main(String... args) throws Throwable {
|
|||
public static Gson gson;
|
||||
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.testEnv = testEnv;
|
||||
taskPool = new Timer("Timered task worker thread", true);
|
||||
launcherLibraries = dir.resolve("launcher-libraries");
|
||||
launcherLibrariesCompile = dir.resolve("launcher-libraries-compile");
|
||||
|
@ -422,16 +431,19 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE
|
|||
|
||||
// Set command handler
|
||||
CommandHandler localCommandHandler;
|
||||
try {
|
||||
Class.forName("jline.Terminal");
|
||||
if (testEnv)
|
||||
localCommandHandler = new StdCommandHandler(false);
|
||||
else
|
||||
try {
|
||||
Class.forName("jline.Terminal");
|
||||
|
||||
// JLine2 available
|
||||
localCommandHandler = new JLineCommandHandler();
|
||||
LogHelper.info("JLine2 terminal enabled");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
localCommandHandler = new StdCommandHandler(true);
|
||||
LogHelper.warning("JLine2 isn't in classpath, using std");
|
||||
}
|
||||
// JLine2 available
|
||||
localCommandHandler = new JLineCommandHandler();
|
||||
LogHelper.info("JLine2 terminal enabled");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
localCommandHandler = new StdCommandHandler(true);
|
||||
LogHelper.warning("JLine2 isn't in classpath, using std");
|
||||
}
|
||||
ru.gravit.launchserver.command.handler.CommandHandler.registerCommands(localCommandHandler);
|
||||
commandHandler = localCommandHandler;
|
||||
|
||||
|
@ -459,6 +471,9 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE
|
|||
crc.update(publicKey.getModulus().toByteArray()); // IDEA говорит, что это Java 9 API. WTF?
|
||||
LogHelper.subInfo("Modulus CRC32: 0x%08x", crc.getValue());
|
||||
|
||||
// Load class bindings.
|
||||
launcherEXEBinaryClass = defaultLauncherEXEBinaryClass;
|
||||
|
||||
// pre init modules
|
||||
modulesManager = new ModulesManager(this);
|
||||
modulesManager.autoload(dir.resolve("modules"));
|
||||
|
@ -466,7 +481,7 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE
|
|||
initGson();
|
||||
|
||||
// Read LaunchServer config
|
||||
generateConfigIfNotExists();
|
||||
generateConfigIfNotExists(testEnv);
|
||||
LogHelper.info("Reading LaunchServer config file");
|
||||
try (BufferedReader reader = IOHelper.newReader(configFile)) {
|
||||
config = Launcher.gson.fromJson(reader, Config.class);
|
||||
|
@ -589,6 +604,14 @@ public static void initGson() {
|
|||
}
|
||||
|
||||
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 {
|
||||
Class.forName("net.sf.launch4j.Builder");
|
||||
if (config.launch4j.enabled) return new EXEL4JLauncherBinary(this);
|
||||
|
@ -614,7 +637,7 @@ public void close() {
|
|||
LogHelper.info("LaunchServer stopped");
|
||||
}
|
||||
|
||||
private void generateConfigIfNotExists() throws IOException {
|
||||
private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
||||
if (IOHelper.isFile(configFile))
|
||||
return;
|
||||
|
||||
|
@ -640,7 +663,8 @@ private void generateConfigIfNotExists() throws IOException {
|
|||
new RequestTextureProvider("http://example.com/skins/%username%.png", "http://example.com/cloaks/%username%.png")
|
||||
, "std")};
|
||||
newConfig.protectHandler = new NoProtectHandler();
|
||||
newConfig.permissionsHandler = new JsonFilePermissionsHandler();
|
||||
if (testEnv) newConfig.permissionsHandler = new DefaultPermissionsHandler();
|
||||
else newConfig.permissionsHandler = new JsonFilePermissionsHandler();
|
||||
newConfig.legacyPort = 7240;
|
||||
newConfig.legacyBindAddress = "0.0.0.0";
|
||||
newConfig.binaryName = "Launcher";
|
||||
|
@ -674,10 +698,15 @@ private void generateConfigIfNotExists() throws IOException {
|
|||
newConfig.components.put("authLimiter", authLimiterComponent);
|
||||
|
||||
// Set server address
|
||||
System.out.println("LaunchServer address: ");
|
||||
newConfig.setLegacyAddress(commandHandler.readLine());
|
||||
System.out.println("LaunchServer projectName: ");
|
||||
newConfig.setProjectName(commandHandler.readLine());
|
||||
if (testEnv) {
|
||||
newConfig.setLegacyAddress("localhost");
|
||||
newConfig.setProjectName("test");
|
||||
} else {
|
||||
System.out.println("LaunchServer address: ");
|
||||
newConfig.setLegacyAddress(commandHandler.readLine());
|
||||
System.out.println("LaunchServer projectName: ");
|
||||
newConfig.setProjectName(commandHandler.readLine());
|
||||
}
|
||||
|
||||
// Write LaunchServer config
|
||||
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;
|
||||
}
|
||||
|
||||
public void setProfiles(List<ClientProfile> profilesList) {
|
||||
this.profilesList = Collections.unmodifiableList(profilesList);
|
||||
}
|
||||
|
||||
public SignedObjectHolder<HashedDir> getUpdateDir(String name) {
|
||||
return updatesDirMap.get(name);
|
||||
|
@ -717,8 +749,10 @@ public void run() {
|
|||
throw new IllegalStateException("LaunchServer has been already started");
|
||||
|
||||
// Add shutdown hook, then start LaunchServer
|
||||
JVMHelper.RUNTIME.addShutdownHook(CommonHelper.newThread(null, false, this::close));
|
||||
CommonHelper.newThread("Command Thread", true, commandHandler).start();
|
||||
if (!this.testEnv) {
|
||||
JVMHelper.RUNTIME.addShutdownHook(CommonHelper.newThread(null, false, this::close));
|
||||
CommonHelper.newThread("Command Thread", true, commandHandler).start();
|
||||
}
|
||||
rebindServerSocket();
|
||||
if (config.netty != null)
|
||||
rebindNettyServerSocket();
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
dependencies {
|
||||
pack project(':LauncherAPI') // Not error on obf.
|
||||
bundle 'com.github.oshi:oshi-core:3.13.0'
|
||||
bundle 'org.ow2.asm:asm-tree:7.1'
|
||||
}
|
||||
|
||||
task genRuntimeJS(type: Zip) {
|
||||
|
|
|
@ -40,7 +40,7 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
|
|||
JVMHelper.addSystemPropertyToArgs(args, DirBridge.USE_OPTDIR_PROPERTY);
|
||||
Collections.addAll(args, MAGIC_ARG);
|
||||
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, pathLauncher);
|
||||
Collections.addAll(args, LauncherEngine.class.getName());
|
||||
|
|
159
Launcher/src/main/java/ru/gravit/launcher/LauncherAgent.java
Normal file
159
Launcher/src/main/java/ru/gravit/launcher/LauncherAgent.java
Normal 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();
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@
|
|||
import ru.gravit.launcher.request.websockets.RequestInterface;
|
||||
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
|
|
@ -8,12 +8,10 @@
|
|||
import ru.gravit.launcher.request.websockets.RequestInterface;
|
||||
|
||||
public class SetProfileRequest extends Request<SetProfileRequestEvent> implements RequestInterface {
|
||||
private transient ClientProfile profile;
|
||||
@LauncherNetworkAPI
|
||||
public String client;
|
||||
|
||||
public SetProfileRequest(ClientProfile profile) {
|
||||
this.profile = profile;
|
||||
this.client = profile.getTitle();
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
import ru.gravit.launcher.hasher.HashedEntry;
|
||||
import ru.gravit.launcher.hasher.HashedFile;
|
||||
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.websockets.LegacyRequestBridge;
|
||||
import ru.gravit.launcher.request.websockets.RequestInterface;
|
||||
|
@ -26,7 +25,6 @@
|
|||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Queue;
|
||||
|
||||
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
|
||||
public UpdateRequestEvent requestDo() throws Exception {
|
||||
LogHelper.debug("Start update request");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
36
LauncherTest/src/test/java/ru/gravit/launcher/StartTest.java
Normal file
36
LauncherTest/src/test/java/ru/gravit/launcher/StartTest.java
Normal 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
2
Radon
|
@ -1 +1 @@
|
|||
Subproject commit e1f7548f97132fa29b01f68bd57ffab32de7b6e7
|
||||
Subproject commit e6974532efc7228a8b826a8cd9e1f1f7b609659f
|
|
@ -37,7 +37,7 @@ public class ServerWrapper extends JsonConfigurable<ServerWrapper.Config> {
|
|||
public ClassLoader loader;
|
||||
public ClientPermissions permissions;
|
||||
public static ServerWrapper wrapper;
|
||||
private static Gson gson;
|
||||
public static Gson gson;
|
||||
private static GsonBuilder gsonBuiler;
|
||||
|
||||
public static Path modulesDir = Paths.get(System.getProperty("serverwrapper.modulesDir", "modules"));
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package ru.gravit.launcher.server.setup;
|
||||
|
||||
import ru.gravit.launcher.LauncherConfig;
|
||||
import ru.gravit.launcher.server.ServerWrapper;
|
||||
import ru.gravit.utils.PublicURLClassLoader;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
@ -24,20 +23,22 @@ public void run() throws IOException {
|
|||
System.out.println("Print jar filename:");
|
||||
String jarName = commands.commandHandler.readLine();
|
||||
Path jarPath = Paths.get(jarName);
|
||||
JarFile file = new JarFile(jarPath.toFile());
|
||||
URL jarURL = jarPath.toUri().toURL();
|
||||
urlClassLoader = new PublicURLClassLoader(new URL[]{jarURL});
|
||||
LogHelper.info("Check jar MainClass");
|
||||
String mainClassName = file.getManifest().getMainAttributes().getValue("Main-Class");
|
||||
if (mainClassName == null) {
|
||||
LogHelper.error("Main-Class not found in MANIFEST");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Class mainClass = Class.forName(mainClassName, false, urlClassLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
LogHelper.error(e);
|
||||
return;
|
||||
String mainClassName = null;
|
||||
try (JarFile file = new JarFile(jarPath.toFile())) {
|
||||
URL jarURL = jarPath.toUri().toURL();
|
||||
urlClassLoader = new PublicURLClassLoader(new URL[]{jarURL});
|
||||
LogHelper.info("Check jar MainClass");
|
||||
mainClassName = file.getManifest().getMainAttributes().getValue("Main-Class");
|
||||
if (mainClassName == null) {
|
||||
LogHelper.error("Main-Class not found in MANIFEST");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Class.forName(mainClassName, false, urlClassLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
LogHelper.error(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LogHelper.info("Found MainClass %s", mainClassName);
|
||||
System.out.println("Print launchserver websocket host:");
|
||||
|
@ -66,7 +67,6 @@ public void run() throws IOException {
|
|||
wrapper.config.password = password;
|
||||
wrapper.config.title = title;
|
||||
wrapper.config.stopOnError = false;
|
||||
LauncherConfig cfg = null;
|
||||
|
||||
if (wrapper.auth()) {
|
||||
break;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -9,8 +9,9 @@
|
|||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class ConfigManager {
|
||||
private final HashMap<String, JsonConfigurable> CONFIGURABLE = new HashMap<>();
|
||||
private final HashMap<String, JsonConfigurable> CONFIGURABLE = new HashMap<>();
|
||||
|
||||
public void registerConfigurable(String name, JsonConfigurable reconfigurable) {
|
||||
VerifyHelper.putIfAbsent(CONFIGURABLE, name.toLowerCase(), Objects.requireNonNull(reconfigurable, "adapter"),
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
include 'ServerWrapper'
|
||||
include 'LaunchServer'
|
||||
include 'LaunchServerConsole'
|
||||
include 'LauncherTest'
|
||||
include 'modules'
|
||||
file('modules').eachDir { sub ->
|
||||
if (sub.name.endsWith('_module')) include 'modules:' + sub.name
|
||||
|
|
Loading…
Reference in a new issue