1
0
mirror of https://github.com/SKCraft/Launcher.git synced 2025-02-19 02:11:37 +01:00

Refactor Java runtime finder (#451)

This commit is contained in:
Henry 2021-12-12 00:30:05 +00:00 committed by GitHub
commit 1ae2993e75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 32 deletions

View File

@ -15,6 +15,7 @@ dependencies {
compile 'com.beust:jcommander:1.32'
compile 'com.miglayout:miglayout:3.7.4'
compile 'com.google.code.findbugs:jsr305:3.0.0'
compile 'com.googlecode.plist:dd-plist:1.23'
implementation 'net.java.dev.jna:jna-platform:5.10.0'
}

View File

@ -6,6 +6,10 @@
package com.skcraft.launcher.launch;
import com.dd.plist.NSArray;
import com.dd.plist.NSDictionary;
import com.dd.plist.NSObject;
import com.dd.plist.PropertyListParser;
import com.skcraft.launcher.model.minecraft.JavaVersion;
import com.skcraft.launcher.util.Environment;
import com.skcraft.launcher.util.EnvironmentParser;
@ -36,29 +40,32 @@ public final class JavaRuntimeFinder {
public static List<JavaRuntime> getAvailableRuntimes() {
Environment env = Environment.getInstance();
Set<JavaRuntime> entries = new HashSet<>();
File launcherDir;
Set<File> launcherDirs = new HashSet<>();
if (env.getPlatform() == Platform.WINDOWS) {
try {
String launcherPath = WinRegistry.readString(WinReg.HKEY_CURRENT_USER,
"SOFTWARE\\Mojang\\InstalledProducts\\Minecraft Launcher", "InstallLocation");
launcherDir = new File(launcherPath);
launcherDirs.add(new File(launcherPath));
} catch (Throwable err) {
log.log(Level.WARNING, "Failed to read launcher location from registry", err);
String programFiles = Objects.equals(env.getArchBits(), "64")
? System.getenv("ProgramFiles(x86)")
: System.getenv("ProgramFiles");
launcherDir = new File(programFiles, "Minecraft Launcher");
}
String programFiles = Objects.equals(env.getArchBits(), "64")
? System.getenv("ProgramFiles(x86)")
: System.getenv("ProgramFiles");
// Mojang likes to move the java runtime directory
launcherDirs.add(new File(programFiles, "Minecraft"));
launcherDirs.add(new File(programFiles, "Minecraft Launcher"));
launcherDirs.add(new File(System.getenv("LOCALAPPDATA"), "Packages\\Microsoft.4297127D64EC6_8wekyb3d8bbwe\\LocalCache\\Local"));
getEntriesFromRegistry(entries, "SOFTWARE\\JavaSoft\\Java Runtime Environment");
getEntriesFromRegistry(entries, "SOFTWARE\\JavaSoft\\Java Development Kit");
getEntriesFromRegistry(entries, "SOFTWARE\\JavaSoft\\JDK");
} else if (env.getPlatform() == Platform.LINUX) {
launcherDir = new File(System.getenv("HOME"), ".minecraft");
launcherDirs.add(new File(System.getenv("HOME"), ".minecraft"));
String javaHome = System.getenv("JAVA_HOME");
if (javaHome != null) {
@ -75,38 +82,57 @@ public final class JavaRuntimeFinder {
}
}).distinct().forEach(file -> entries.add(getRuntimeFromPath(file.getAbsolutePath())));
}
} else if (env.getPlatform() == Platform.MAC_OS_X) {
launcherDirs.add(new File(System.getenv("HOME"), "Library/Application Support/minecraft"));
try {
Process p = Runtime.getRuntime().exec("/usr/libexec/java_home -X");
NSArray root = (NSArray) PropertyListParser.parse(p.getInputStream());
NSObject[] arr = root.getArray();
for (NSObject obj : arr) {
NSDictionary dict = (NSDictionary) obj;
entries.add(new JavaRuntime(
new File(dict.objectForKey("JVMHomePath").toString()).getAbsoluteFile(),
dict.objectForKey("JVMVersion").toString(),
isArch64Bit(dict.objectForKey("JVMArch").toString())
));
}
} catch (Throwable err) {
log.log(Level.WARNING, "Failed to parse java_home command", err);
}
} else {
return Collections.emptyList();
}
File runtimes = new File(launcherDir, "runtime");
File[] runtimeList = runtimes.listFiles();
if (runtimeList != null) {
for (File potential : runtimeList) {
if (potential.getName().startsWith("jre-x")) {
boolean is64Bit = potential.getName().equals("jre-x64");
JavaRuntime runtime = new JavaRuntime(potential.getAbsoluteFile(), readVersionFromRelease(potential), is64Bit);
runtime.setMinecraftBundled(true);
entries.add(runtime);
} else {
for (File install : launcherDirs) {
File runtimes = new File(install, "runtime");
File[] runtimeList = runtimes.listFiles();
if (runtimeList != null) {
for (File potential : runtimeList) {
String runtimeName = potential.getName();
if (runtimeName.startsWith("jre-x")) {
boolean is64Bit = runtimeName.equals("jre-x64");
String[] children = potential.list();
if (children == null || children.length == 0) continue;
String platformName = children[0];
JavaRuntime runtime = new JavaRuntime(potential.getAbsoluteFile(), readVersionFromRelease(potential), is64Bit);
runtime.setMinecraftBundled(true);
entries.add(runtime);
} else {
String[] children = potential.list((dir, name) -> new File(dir, name).isDirectory());
if (children == null || children.length != 1) continue;
String platformName = children[0];
String[] parts = platformName.split("-");
if (parts.length < 2) continue;
File javaDir = new File(potential, String.format("%s/%s", platformName, runtimeName));
if (env.getPlatform() == Platform.MAC_OS_X) {
javaDir = new File(javaDir, "jre.bundle/Contents/Home");
}
String arch = parts[1];
boolean is64Bit = arch.equals("x64");
String arch = readArchFromRelease(javaDir);
boolean is64Bit = isArch64Bit(arch);
File javaDir = new File(potential, String.format("%s/%s", platformName, runtimeName));
JavaRuntime runtime = new JavaRuntime(javaDir.getAbsoluteFile(), readVersionFromRelease(javaDir), is64Bit);
runtime.setMinecraftBundled(true);
entries.add(runtime);
JavaRuntime runtime = new JavaRuntime(javaDir.getAbsoluteFile(), readVersionFromRelease(javaDir), is64Bit);
runtime.setMinecraftBundled(true);
entries.add(runtime);
}
}
}
}
@ -146,6 +172,9 @@ public final class JavaRuntimeFinder {
if (target.isFile()) {
// Probably referring directly to bin/java, back up two levels
target = target.getParentFile().getParentFile();
} else if (target.getName().equals("bin")) {
// Probably copied the bin directory that java.exe is in
target = target.getParentFile();
}
{
@ -193,6 +222,10 @@ public final class JavaRuntimeFinder {
}
}
private static boolean isArch64Bit(String string) {
return string == null || string.matches("x64|x86_64|amd64|aarch64");
}
private static String readVersionFromRelease(File javaPath) {
File releaseFile = new File(javaPath, "release");
if (releaseFile.exists()) {
@ -208,4 +241,20 @@ public final class JavaRuntimeFinder {
return null;
}
private static String readArchFromRelease(File javaPath) {
File releaseFile = new File(javaPath, "release");
if (releaseFile.exists()) {
try {
Map<String, String> releaseDetails = EnvironmentParser.parse(releaseFile);
return releaseDetails.get("OS_ARCH");
} catch (IOException e) {
log.log(Level.WARNING, "Failed to read release file " + releaseFile.getAbsolutePath(), e);
return null;
}
}
return null;
}
}