From 32d7ca932a5a850eb74d33b36091925c07f4828e Mon Sep 17 00:00:00 2001 From: Gravit Date: Sat, 26 Sep 2020 17:06:51 +0700 Subject: [PATCH] [FIX] Multi-Release --- LaunchServer/build.gradle | 1 + .../socket/response/auth/AuthResponse.java | 2 +- Launcher/build.gradle | 1 + LauncherAPI/build.gradle | 19 ++ LauncherCore/build.gradle | 17 +- .../pro/gravit/launcher/HTTPRequest.java | 56 ++++++ .../pro/gravit/utils/helper/JVMHelper.java | 179 ++++++++++++++++++ 7 files changed, 266 insertions(+), 9 deletions(-) create mode 100644 LauncherCore/src/main/java11/pro/gravit/launcher/HTTPRequest.java create mode 100644 LauncherCore/src/main/java11/pro/gravit/utils/helper/JVMHelper.java diff --git a/LaunchServer/build.gradle b/LaunchServer/build.gradle index 18292b0e..c5c478ec 100644 --- a/LaunchServer/build.gradle +++ b/LaunchServer/build.gradle @@ -33,6 +33,7 @@ from(parent.childProjects.Launcher.tasks.genRuntimeJS) manifest.attributes("Main-Class": mainClassName, "Premain-Class": mainAgentName, + "Multi-Release": "true", "Can-Redefine-Classes": "true", "Can-Retransform-Classes": "true", "Can-Set-Native-Method-Prefix": "true" diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/AuthResponse.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/AuthResponse.java index ed2ec816..7d1debd9 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/AuthResponse.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/AuthResponse.java @@ -58,7 +58,7 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti } } AuthProviderPair pair; - if (auth_id.isEmpty()) pair = server.config.getAuthProviderPair(); + if (auth_id == null || auth_id.isEmpty()) pair = server.config.getAuthProviderPair(); else pair = server.config.getAuthProviderPair(auth_id); if (pair == null) { sendError("auth_id incorrect"); diff --git a/Launcher/build.gradle b/Launcher/build.gradle index 10dbc4b7..43be3243 100644 --- a/Launcher/build.gradle +++ b/Launcher/build.gradle @@ -27,6 +27,7 @@ manifest.attributes("Main-Class": mainClassName, "Premain-Class": mainAgentName, "Can-Redefine-Classes": "true", + "Multi-Release": "true", "Can-Retransform-Classes": "true", "Can-Set-Native-Method-Prefix": "true", "Multi-Release-Jar": "true") diff --git a/LauncherAPI/build.gradle b/LauncherAPI/build.gradle index 724e14f4..88896a32 100644 --- a/LauncherAPI/build.gradle +++ b/LauncherAPI/build.gradle @@ -14,10 +14,29 @@ api project(':LauncherCore') } } +sourceSets { + java11 { + java { + srcDirs = ['src/main/java11'] + } + dependencies { + java11Implementation files(sourceSets.main.output.classesDirs) { builtBy compileJava } + } + } +} + jar { + into('META-INF/versions/11') { + from sourceSets.java11.output + } classifier = 'clean' } +compileJava11Java { + sourceCompatibility = 11 + targetCompatibility = 11 +} + task sourcesJar(type: Jar) { from sourceSets.main.allJava archiveClassifier = 'sources' diff --git a/LauncherCore/build.gradle b/LauncherCore/build.gradle index c30d2be4..04b3b796 100644 --- a/LauncherCore/build.gradle +++ b/LauncherCore/build.gradle @@ -21,24 +21,25 @@ } } sourceSets { - java9 { + java11 { java { - srcDirs = ['src/main/java9'] + srcDirs = ['src/main/java11'] } dependencies { - java9Implementation files(sourceSets.main.output.classesDirs) { builtBy compileJava } + java11Implementation group: 'com.google.code.gson', name: 'gson', version: rootProject['verGson'] + java11Implementation files(sourceSets.main.output.classesDirs) { builtBy compileJava } } } } jar { - into('META-INF/versions/9') { - from sourceSets.java9.output + into('META-INF/versions/11') { + from sourceSets.java11.output } classifier = 'clean' } -compileJava9Java { - sourceCompatibility = 9 - targetCompatibility = 9 +compileJava11Java { + sourceCompatibility = 11 + targetCompatibility = 11 } task sourcesJar(type: Jar) { diff --git a/LauncherCore/src/main/java11/pro/gravit/launcher/HTTPRequest.java b/LauncherCore/src/main/java11/pro/gravit/launcher/HTTPRequest.java new file mode 100644 index 00000000..70923c62 --- /dev/null +++ b/LauncherCore/src/main/java11/pro/gravit/launcher/HTTPRequest.java @@ -0,0 +1,56 @@ +package pro.gravit.launcher; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import pro.gravit.utils.helper.LogHelper; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +public final class HTTPRequest { + private static final int TIMEOUT = 10000; + + private HTTPRequest() { + } + + public static JsonElement jsonRequest(JsonElement request, URL url) throws IOException { + return jsonRequest(request, "POST", url); + } + + public static JsonElement jsonRequest(JsonElement request, String method, URL url) throws IOException { + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoInput(true); + if (request != null) connection.setDoOutput(true); + connection.setRequestMethod(method); + if (request != null) connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); + connection.setRequestProperty("Accept", "application/json"); + if (TIMEOUT > 0) + connection.setConnectTimeout(TIMEOUT); + if (request != null) + try (OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8)) { + writer.write(request.toString()); + writer.flush(); + } + + InputStreamReader reader; + int statusCode = connection.getResponseCode(); + + if (200 <= statusCode && statusCode < 300) + reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8); + else + reader = new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8); + try { + return JsonParser.parseReader(reader); + } catch (Exception e) { + if (200 > statusCode || statusCode > 300) { + LogHelper.error("JsonRequest failed. Server response code %d", statusCode); + throw new IOException(e); + } + return null; + } + } +} diff --git a/LauncherCore/src/main/java11/pro/gravit/utils/helper/JVMHelper.java b/LauncherCore/src/main/java11/pro/gravit/utils/helper/JVMHelper.java new file mode 100644 index 00000000..15e84711 --- /dev/null +++ b/LauncherCore/src/main/java11/pro/gravit/utils/helper/JVMHelper.java @@ -0,0 +1,179 @@ +package pro.gravit.utils.helper; + +import java.io.File; +import java.lang.invoke.MethodHandles; +import java.lang.management.ManagementFactory; +import java.lang.management.OperatingSystemMXBean; +import java.lang.management.RuntimeMXBean; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; +import java.util.Map; + +public final class JVMHelper { + + // MXBeans exports + public static final RuntimeMXBean RUNTIME_MXBEAN = ManagementFactory.getRuntimeMXBean(); + public static final OperatingSystemMXBean OPERATING_SYSTEM_MXBEAN = + ManagementFactory.getOperatingSystemMXBean(); + public static final OS OS_TYPE = OS.byName(OPERATING_SYSTEM_MXBEAN.getName()); + // System properties + public static final String OS_VERSION = OPERATING_SYSTEM_MXBEAN.getVersion(); + public static final int OS_BITS = getCorrectOSArch(); + public static final int JVM_BITS = Integer.parseInt(System.getProperty("sun.arch.data.model")); + public static final SecurityManager SECURITY_MANAGER = System.getSecurityManager(); + // Public static fields + public static final Runtime RUNTIME = Runtime.getRuntime(); + public static final ClassLoader LOADER = ClassLoader.getSystemClassLoader(); + public static final int JVM_VERSION = getVersion(); + + static { + try { + MethodHandles.publicLookup(); // Just to initialize class + } catch (Throwable exc) { + throw new InternalError(exc); + } + } + + private JVMHelper() { + } + + public static int getVersion() { + //System.out.println("[DEBUG] JVMHelper 11 version"); + return Runtime.version().feature(); + } + + public static void appendVars(ProcessBuilder builder, Map vars) { + builder.environment().putAll(vars); + } + + public static Class firstClass(String... names) throws ClassNotFoundException { + for (String name : names) + try { + return Class.forName(name, false, LOADER); + } catch (ClassNotFoundException ignored) { + // Expected + } + throw new ClassNotFoundException(Arrays.toString(names)); + } + + + public static void fullGC() { + RUNTIME.gc(); + RUNTIME.runFinalization(); + LogHelper.debug("Used heap: %d MiB", RUNTIME.totalMemory() - RUNTIME.freeMemory() >> 20); + } + + + public static String[] getClassPath() { + return System.getProperty("java.class.path").split(File.pathSeparator); + } + + + public static URL[] getClassPathURL() { + String[] cp = System.getProperty("java.class.path").split(File.pathSeparator); + URL[] list = new URL[cp.length]; + + for (int i = 0; i < cp.length; i++) { + URL url = null; + try { + url = new URL(cp[i]); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + list[i] = url; + } + return list; + } + + public static X509Certificate[] getCertificates(Class clazz) { + Object[] signers = clazz.getSigners(); + if (signers == null) return null; + return Arrays.stream(signers).filter((c) -> c instanceof X509Certificate).map((c) -> (X509Certificate) c).toArray(X509Certificate[]::new); + } + + public static void checkStackTrace(Class mainClass) { + LogHelper.debug("Testing stacktrace"); + Exception e = new Exception("Testing stacktrace"); + StackTraceElement[] list = e.getStackTrace(); + if (!list[list.length - 1].getClassName().equals(mainClass.getName())) { + throw new SecurityException(String.format("Invalid StackTraceElement: %s", list[list.length - 1].getClassName())); + } + } + + private static int getCorrectOSArch() { + // As always, mustdie must die + if (OS_TYPE == OS.MUSTDIE) + return System.getenv("ProgramFiles(x86)") == null ? 32 : 64; + + // Or trust system property (maybe incorrect) + return System.getProperty("os.arch").contains("64") ? 64 : 32; + } + + + public static String getEnvPropertyCaseSensitive(String name) { + return System.getenv().get(name); + } + + + public static boolean isJVMMatchesSystemArch() { + return JVM_BITS == OS_BITS; + } + + + public static String jvmProperty(String name, String value) { + return String.format("-D%s=%s", name, value); + } + + + public static String systemToJvmProperty(String name) { + return String.format("-D%s=%s", name, System.getProperties().getProperty(name)); + } + + + public static void addSystemPropertyToArgs(Collection args, String name) { + String property = System.getProperty(name); + if (property != null) + args.add(String.format("-D%s=%s", name, property)); + } + + + public static void verifySystemProperties(Class mainClass, boolean requireSystem) { + Locale.setDefault(Locale.US); + // Verify class loader + LogHelper.debug("Verifying class loader"); + if (requireSystem && !mainClass.getClassLoader().equals(LOADER)) + throw new SecurityException("ClassLoader should be system"); + + // Verify system and java architecture + LogHelper.debug("Verifying JVM architecture"); + if (!isJVMMatchesSystemArch()) { + LogHelper.warning("Java and OS architecture mismatch"); + LogHelper.warning("It's recommended to download %d-bit JRE", OS_BITS); + } + } + + public enum OS { + MUSTDIE("mustdie"), LINUX("linux"), MACOSX("macosx"); + + public final String name; + + OS(String name) { + this.name = name; + } + + public static OS byName(String name) { + if (name.startsWith("Windows")) + return MUSTDIE; + if (name.startsWith("Linux")) + return LINUX; + if (name.startsWith("Mac OS X")) + return MACOSX; + throw new RuntimeException(String.format("This shit is not yet supported: '%s'", name)); + } + } + +}