1
0
mirror of https://github.com/SKCraft/Launcher.git synced 2024-11-23 12:05:44 +01:00

Refactor JavaRuntimeFinder into subclasses & clean up

The getAvailableRuntimes function is now parseable, & the new
PlatformRuntimeFinder interface makes it clear what each stage does.
This commit is contained in:
Henry Le Grys 2021-12-12 02:02:46 +00:00
parent 8c9f903e16
commit 08335637f9
16 changed files with 461 additions and 270 deletions

View File

@ -7,8 +7,8 @@
package com.skcraft.launcher;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.skcraft.launcher.launch.JavaRuntime;
import com.skcraft.launcher.launch.JavaRuntimeFinder;
import com.skcraft.launcher.launch.runtime.JavaRuntime;
import com.skcraft.launcher.launch.runtime.JavaRuntimeFinder;
import lombok.Data;
/**

View File

@ -1,8 +1,8 @@
package com.skcraft.launcher;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.skcraft.launcher.launch.JavaRuntime;
import com.skcraft.launcher.launch.MemorySettings;
import com.skcraft.launcher.launch.runtime.JavaRuntime;
import lombok.Data;
@Data

View File

@ -9,9 +9,9 @@ package com.skcraft.launcher.dialog;
import com.skcraft.launcher.Configuration;
import com.skcraft.launcher.Launcher;
import com.skcraft.launcher.dialog.component.BetterComboBox;
import com.skcraft.launcher.launch.AddJavaRuntime;
import com.skcraft.launcher.launch.JavaRuntime;
import com.skcraft.launcher.launch.JavaRuntimeFinder;
import com.skcraft.launcher.launch.runtime.AddJavaRuntime;
import com.skcraft.launcher.launch.runtime.JavaRuntime;
import com.skcraft.launcher.launch.runtime.JavaRuntimeFinder;
import com.skcraft.launcher.persistence.Persistence;
import com.skcraft.launcher.swing.*;
import com.skcraft.launcher.util.SharedLocale;

View File

@ -3,9 +3,9 @@ package com.skcraft.launcher.dialog;
import com.skcraft.launcher.Instance;
import com.skcraft.launcher.InstanceSettings;
import com.skcraft.launcher.dialog.component.BetterComboBox;
import com.skcraft.launcher.launch.JavaRuntime;
import com.skcraft.launcher.launch.JavaRuntimeFinder;
import com.skcraft.launcher.launch.MemorySettings;
import com.skcraft.launcher.launch.runtime.JavaRuntime;
import com.skcraft.launcher.launch.runtime.JavaRuntimeFinder;
import com.skcraft.launcher.persistence.Persistence;
import com.skcraft.launcher.swing.FormPanel;
import com.skcraft.launcher.swing.LinedBoxPanel;

View File

@ -6,6 +6,7 @@
package com.skcraft.launcher.launch;
import com.skcraft.launcher.launch.runtime.JavaRuntime;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

View File

@ -1,260 +0,0 @@
/*
* SK's Minecraft Launcher
* Copyright (C) 2010-2014 Albert Pham <http://www.sk89q.com> and contributors
* Please see LICENSE.txt for license information.
*/
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;
import com.skcraft.launcher.util.Platform;
import com.skcraft.launcher.util.WinRegistry;
import com.sun.jna.platform.win32.WinReg;
import lombok.extern.java.Log;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.stream.Collectors;
/**
* Finds the best Java runtime to use.
*/
@Log
public final class JavaRuntimeFinder {
private JavaRuntimeFinder() {
}
/**
* Get all available Java runtimes on the system
* @return List of available Java runtimes sorted by newest first
*/
public static List<JavaRuntime> getAvailableRuntimes() {
Environment env = Environment.getInstance();
Set<JavaRuntime> entries = new HashSet<>();
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");
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");
// 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) {
launcherDirs.add(new File(System.getenv("HOME"), ".minecraft"));
String javaHome = System.getenv("JAVA_HOME");
if (javaHome != null) {
entries.add(getRuntimeFromPath(javaHome));
}
File[] runtimesList = new File("/usr/lib/jvm").listFiles();
if (runtimesList != null) {
Arrays.stream(runtimesList).map(file -> {
try {
return file.getCanonicalFile();
} catch (IOException exception) {
return file;
}
}).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();
}
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");
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];
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 = readArchFromRelease(javaDir);
boolean is64Bit = isArch64Bit(arch);
JavaRuntime runtime = new JavaRuntime(javaDir.getAbsoluteFile(), readVersionFromRelease(javaDir), is64Bit);
runtime.setMinecraftBundled(true);
entries.add(runtime);
}
}
}
}
return entries.stream().sorted().collect(Collectors.toList());
}
/**
* Return the path to the best found JVM location.
*
* @return the JVM location, or null
*/
public static File findBestJavaPath() {
List<JavaRuntime> entries = getAvailableRuntimes();
if (entries.size() > 0) {
return new File(entries.get(0).getDir(), "bin");
}
return null;
}
public static Optional<JavaRuntime> findBestJavaRuntime(JavaVersion targetVersion) {
List<JavaRuntime> entries = getAvailableRuntimes();
return entries.stream().sorted()
.filter(runtime -> runtime.getMajorVersion() == targetVersion.getMajorVersion())
.findFirst();
}
public static Optional<JavaRuntime> findAnyJavaRuntime() {
return getAvailableRuntimes().stream().sorted().findFirst();
}
public static JavaRuntime getRuntimeFromPath(String path) {
File target = new File(path);
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();
}
{
File jre = new File(target, "jre/release");
if (jre.isFile()) {
target = jre.getParentFile();
}
}
return new JavaRuntime(target, readVersionFromRelease(target), guessIf64BitWindows(target));
}
private static void getEntriesFromRegistry(Collection<JavaRuntime> entries, String basePath)
throws IllegalArgumentException {
try {
List<String> subKeys = WinRegistry.readStringSubKeys(WinReg.HKEY_LOCAL_MACHINE, basePath);
for (String subKey : subKeys) {
JavaRuntime entry = getEntryFromRegistry(basePath, subKey);
if (entry != null) {
entries.add(entry);
}
}
} catch (Throwable err) {
log.log(Level.INFO, "Failed to read Java locations from registry in " + basePath);
}
}
private static JavaRuntime getEntryFromRegistry(String basePath, String version) {
String regPath = basePath + "\\" + version;
String path = WinRegistry.readString(WinReg.HKEY_LOCAL_MACHINE, regPath, "JavaHome");
File dir = new File(path);
if (dir.exists() && new File(dir, "bin/java.exe").exists()) {
return new JavaRuntime(dir, version, guessIf64BitWindows(dir));
} else {
return null;
}
}
private static boolean guessIf64BitWindows(File path) {
try {
String programFilesX86 = System.getenv("ProgramFiles(x86)");
return programFilesX86 == null || !path.getCanonicalPath().startsWith(new File(programFilesX86).getCanonicalPath());
} catch (IOException ignored) {
return false;
}
}
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()) {
try {
Map<String, String> releaseDetails = EnvironmentParser.parse(releaseFile);
return releaseDetails.get("JAVA_VERSION");
} catch (IOException e) {
log.log(Level.WARNING, "Failed to read release file " + releaseFile.getAbsolutePath(), e);
return null;
}
}
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;
}
}

View File

@ -16,6 +16,8 @@ import com.skcraft.concurrency.ProgressObservable;
import com.skcraft.launcher.*;
import com.skcraft.launcher.auth.Session;
import com.skcraft.launcher.install.ZipExtract;
import com.skcraft.launcher.launch.runtime.JavaRuntime;
import com.skcraft.launcher.launch.runtime.JavaRuntimeFinder;
import com.skcraft.launcher.model.minecraft.*;
import com.skcraft.launcher.persistence.Persistence;
import com.skcraft.launcher.util.Environment;

View File

@ -1,4 +1,4 @@
package com.skcraft.launcher.launch;
package com.skcraft.launcher.launch.runtime;
import java.io.File;

View File

@ -0,0 +1,47 @@
package com.skcraft.launcher.launch.runtime;
import com.skcraft.launcher.util.EnvironmentParser;
import lombok.extern.java.Log;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Level;
@Log
public class JavaReleaseFile {
private Map<String, String> backingMap;
private JavaReleaseFile(Map<String, String> releaseDetails) {
this.backingMap = releaseDetails;
}
public String getVersion() {
return backingMap.get("JAVA_VERSION");
}
public String getArch() {
return backingMap.get("OS_ARCH");
}
public boolean isArch64Bit() {
return getArch() == null || getArch().matches("x64|x86_64|amd64|aarch64");
}
public static JavaReleaseFile parseFromRelease(File javaPath) {
File releaseFile = new File(javaPath, "release");
if (releaseFile.exists()) {
try {
Map<String, String> releaseDetails = EnvironmentParser.parse(releaseFile);
return new JavaReleaseFile(releaseDetails);
} catch (IOException e) {
log.log(Level.WARNING, "Failed to read release file " + releaseFile.getAbsolutePath(), e);
return null;
}
}
return null;
}
}

View File

@ -1,4 +1,4 @@
package com.skcraft.launcher.launch;
package com.skcraft.launcher.launch.runtime;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;

View File

@ -0,0 +1,112 @@
/*
* SK's Minecraft Launcher
* Copyright (C) 2010-2014 Albert Pham <http://www.sk89q.com> and contributors
* Please see LICENSE.txt for license information.
*/
package com.skcraft.launcher.launch.runtime;
import com.skcraft.launcher.model.minecraft.JavaVersion;
import com.skcraft.launcher.util.Environment;
import lombok.extern.java.Log;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
/**
* Finds the best Java runtime to use.
*/
@Log
public final class JavaRuntimeFinder {
private JavaRuntimeFinder() {
}
/**
* Get all available Java runtimes on the system
* @return List of available Java runtimes sorted by newest first
*/
public static List<JavaRuntime> getAvailableRuntimes() {
Environment env = Environment.getInstance();
PlatformRuntimeFinder runtimeFinder = getRuntimeFinder(env);
if (runtimeFinder == null) {
return Collections.emptyList();
}
// Add Minecraft javas
List<JavaRuntime> mcRuntimes = MinecraftJavaFinder.scanLauncherDirectories(env,
runtimeFinder.getLauncherDirectories(env));
Set<JavaRuntime> entries = new HashSet<>(mcRuntimes);
// Add system Javas
runtimeFinder.getCandidateJavaLocations().stream()
.map(JavaRuntimeFinder::getRuntimeFromPath)
.forEach(entries::add);
// Add extra runtimes
entries.addAll(runtimeFinder.getExtraRuntimes());
return entries.stream().sorted().collect(Collectors.toList());
}
/**
* Find the best runtime for a given Java version
* @param targetVersion Version to match
* @return Java runtime if available, empty Optional otherwise
*/
public static Optional<JavaRuntime> findBestJavaRuntime(JavaVersion targetVersion) {
List<JavaRuntime> entries = getAvailableRuntimes();
return entries.stream().sorted()
.filter(runtime -> runtime.getMajorVersion() == targetVersion.getMajorVersion())
.findFirst();
}
public static Optional<JavaRuntime> findAnyJavaRuntime() {
return getAvailableRuntimes().stream().sorted().findFirst();
}
public static JavaRuntime getRuntimeFromPath(String path) {
return getRuntimeFromPath(new File(path));
}
public static JavaRuntime getRuntimeFromPath(File target) {
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();
}
{
File jre = new File(target, "jre/release");
if (jre.isFile()) {
target = jre.getParentFile();
}
}
JavaReleaseFile release = JavaReleaseFile.parseFromRelease(target);
if (release == null) {
// Make some assumptions...
return new JavaRuntime(target, null, true);
}
return new JavaRuntime(target, release.getVersion(), release.isArch64Bit());
}
private static PlatformRuntimeFinder getRuntimeFinder(Environment env) {
switch (env.getPlatform()) {
case WINDOWS:
return new WindowsRuntimeFinder();
case MAC_OS_X:
return new MacRuntimeFinder();
case LINUX:
return new LinuxRuntimeFinder();
default:
return null;
}
}
}

View File

@ -0,0 +1,44 @@
package com.skcraft.launcher.launch.runtime;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.skcraft.launcher.util.Environment;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class LinuxRuntimeFinder implements PlatformRuntimeFinder {
@Override
public Set<File> getLauncherDirectories(Environment env) {
return ImmutableSet.of(new File(System.getenv("HOME"), ".minecraft"));
}
@Override
public List<File> getCandidateJavaLocations() {
ArrayList<File> entries = Lists.newArrayList();
String javaHome = System.getenv("JAVA_HOME");
if (javaHome != null) {
entries.add(new File(javaHome));
}
File[] runtimesList = new File("/usr/lib/jvm").listFiles();
if (runtimesList != null) {
Arrays.stream(runtimesList).map(file -> {
try {
return file.getCanonicalFile();
} catch (IOException exception) {
return file;
}
}).distinct().forEach(entries::add);
}
return entries;
}
@Override
public List<JavaRuntime> getExtraRuntimes() {
return Collections.emptyList();
}
}

View File

@ -0,0 +1,57 @@
package com.skcraft.launcher.launch.runtime;
import com.dd.plist.NSArray;
import com.dd.plist.NSDictionary;
import com.dd.plist.NSObject;
import com.dd.plist.PropertyListParser;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.skcraft.launcher.util.Environment;
import lombok.extern.java.Log;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
@Log
public class MacRuntimeFinder implements PlatformRuntimeFinder {
@Override
public Set<File> getLauncherDirectories(Environment env) {
return ImmutableSet.of(new File(System.getenv("HOME"), "Library/Application Support/minecraft"));
}
@Override
public List<File> getCandidateJavaLocations() {
return Collections.emptyList();
}
@Override
public List<JavaRuntime> getExtraRuntimes() {
ArrayList<JavaRuntime> entries = Lists.newArrayList();
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);
}
return entries;
}
private static boolean isArch64Bit(String string) {
return string == null || string.matches("x64|x86_64|amd64|aarch64");
}
}

View File

@ -0,0 +1,66 @@
package com.skcraft.launcher.launch.runtime;
import com.skcraft.launcher.util.Environment;
import com.skcraft.launcher.util.Platform;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Scans Minecraft bundled Java directories
*/
public class MinecraftJavaFinder {
public static List<JavaRuntime> scanLauncherDirectories(Environment env, Collection<File> launcherDirs) {
ArrayList<JavaRuntime> entries = new ArrayList<>();
for (File install : launcherDirs) {
File runtimes = new File(install, "runtime");
File[] runtimeList = runtimes.listFiles();
if (runtimeList != null) {
for (File potential : runtimeList) {
JavaRuntime runtime = scanPotentialRuntime(env, potential);
if (runtime != null) {
entries.add(runtime);
}
}
}
}
return entries;
}
private static JavaRuntime scanPotentialRuntime(Environment env, File potential) {
String runtimeName = potential.getName();
if (runtimeName.startsWith("jre-x")) {
boolean is64Bit = runtimeName.equals("jre-x64");
JavaReleaseFile release = JavaReleaseFile.parseFromRelease(potential);
String version = release != null ? release.getVersion() : null;
JavaRuntime runtime = new JavaRuntime(potential.getAbsoluteFile(), version, is64Bit);
runtime.setMinecraftBundled(true);
return runtime;
} else {
String[] children = potential.list((dir, name) -> new File(dir, name).isDirectory());
if (children == null || children.length != 1) return null;
String platformName = children[0];
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");
}
JavaReleaseFile release = JavaReleaseFile.parseFromRelease(javaDir);
if (release == null) {
return null;
}
JavaRuntime runtime = new JavaRuntime(javaDir.getAbsoluteFile(), release.getVersion(), release.isArch64Bit());
runtime.setMinecraftBundled(true);
return runtime;
}
}
}

View File

@ -0,0 +1,31 @@
package com.skcraft.launcher.launch.runtime;
import com.skcraft.launcher.util.Environment;
import java.io.File;
import java.util.List;
import java.util.Set;
public interface PlatformRuntimeFinder {
/**
* Get the list of possible launcher locations for this platform
* @return List of possible launcher locations
*/
Set<File> getLauncherDirectories(Environment env);
/**
* Get a list of candidate folders to check for Java runtimes.
* The returned folders will be checked for "release" files which describe the version and architecture.
*
* @return List of folders that may contain Java runtimes
*/
List<File> getCandidateJavaLocations();
/**
* Get a list of extra runtimes obtained using platform-specific logic.
* e.g. on Windows, registry entries are returned
*
* @return List of extra Java runtimes
*/
List<JavaRuntime> getExtraRuntimes();
}

View File

@ -0,0 +1,91 @@
package com.skcraft.launcher.launch.runtime;
import com.google.common.collect.Lists;
import com.skcraft.launcher.util.Environment;
import com.skcraft.launcher.util.WinRegistry;
import com.sun.jna.platform.win32.WinReg;
import lombok.extern.java.Log;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
@Log
public class WindowsRuntimeFinder implements PlatformRuntimeFinder {
@Override
public Set<File> getLauncherDirectories(Environment env) {
HashSet<File> launcherDirs = new HashSet<>();
try {
String launcherPath = WinRegistry.readString(WinReg.HKEY_CURRENT_USER,
"SOFTWARE\\Mojang\\InstalledProducts\\Minecraft Launcher", "InstallLocation");
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");
// 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"));
return launcherDirs;
}
@Override
public List<File> getCandidateJavaLocations() {
return Collections.emptyList();
}
@Override
public List<JavaRuntime> getExtraRuntimes() {
ArrayList<JavaRuntime> entries = Lists.newArrayList();
getEntriesFromRegistry(entries, "SOFTWARE\\JavaSoft\\Java Runtime Environment");
getEntriesFromRegistry(entries, "SOFTWARE\\JavaSoft\\Java Development Kit");
getEntriesFromRegistry(entries, "SOFTWARE\\JavaSoft\\JDK");
return entries;
}
private static void getEntriesFromRegistry(Collection<JavaRuntime> entries, String basePath)
throws IllegalArgumentException {
try {
List<String> subKeys = WinRegistry.readStringSubKeys(WinReg.HKEY_LOCAL_MACHINE, basePath);
for (String subKey : subKeys) {
JavaRuntime entry = getEntryFromRegistry(basePath, subKey);
if (entry != null) {
entries.add(entry);
}
}
} catch (Throwable err) {
log.log(Level.INFO, "Failed to read Java locations from registry in " + basePath);
}
}
private static JavaRuntime getEntryFromRegistry(String basePath, String version) {
String regPath = basePath + "\\" + version;
String path = WinRegistry.readString(WinReg.HKEY_LOCAL_MACHINE, regPath, "JavaHome");
File dir = new File(path);
if (dir.exists() && new File(dir, "bin/java.exe").exists()) {
return new JavaRuntime(dir, version, guessIf64BitWindows(dir));
} else {
return null;
}
}
private static boolean guessIf64BitWindows(File path) {
try {
String programFilesX86 = System.getenv("ProgramFiles(x86)");
return programFilesX86 == null || !path.getCanonicalPath().startsWith(new File(programFilesX86).getCanonicalPath());
} catch (IOException ignored) {
return false;
}
}
}