Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 73 additions & 1 deletion HMCL/src/main/java/org/jackhuang/hmcl/java/JavaManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
import org.jackhuang.hmcl.util.CacheRepository;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.platform.*;
import org.jackhuang.hmcl.util.platform.Architecture;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import org.jackhuang.hmcl.util.platform.Platform;
import org.jackhuang.hmcl.util.platform.UnsupportedPlatformException;
import org.jackhuang.hmcl.util.platform.windows.WinReg;
import org.jackhuang.hmcl.util.versioning.GameVersionNumber;
import org.jetbrains.annotations.Nullable;
Expand All @@ -42,6 +45,7 @@
import java.io.IOException;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -174,6 +178,74 @@ public static void refresh() {
}).start();
}

public static Task<List<JavaRuntime>> getSearchAndAddJavaTask(Path directory) {
return new Task<List<JavaRuntime>>() {

private final Path dir = directory;
{ setName("Search Java"); }

@Override
public void execute() throws Exception {
setResult(searchJava());
}

private List<JavaRuntime> searchJava() throws IOException, InterruptedException {
final int maxDepth = 3;

final var binaryList = new ArrayList<JavaRuntime>();
final var queue = new ArrayDeque<Path>(64);
try (final var subDirs = Files.list(dir)) {
subDirs.filter(Files::isDirectory).filter(Files::isReadable).forEach(queue::add);
}
final var relative = Paths.get("bin", OperatingSystem.CURRENT_OS.getJavaExecutable());
queue.add(relative); // relative also as a sign of the end of the layer
int depth = 1;
while (!queue.isEmpty()) {
final Path directory = queue.poll();
if (directory == relative) {
depth++;
if (!queue.isEmpty() && depth < maxDepth)
queue.add(relative);
continue;
}
if (isCancelled())
throw new CancellationException("Cancelled by user");
var binary = directory.resolve(relative);
if (Files.exists(binary)) {
var java = JavaManager.getJava(binary);
if (java.getParsedVersion() <= 8 && java.isJDK()) {
binary = directory.resolve("jre").resolve(relative);
if (Files.exists(binary))
java = JavaManager.getJava(binary);
}
binaryList.add(java);
} else if (depth < maxDepth)
try (final var subDirs = Files.list(directory)) {
subDirs.filter(Files::isDirectory).filter(Files::isReadable).forEach(queue::add);
}
}
return Collections.unmodifiableList(binaryList);
}
}.thenApplyAsync("Add Java", Schedulers.javafx(), javaRuntimes -> {
final var failedJavaRuntimes = new ArrayList<JavaRuntime>();
for (JavaRuntime javaRuntime: javaRuntimes) {
if (!JavaManager.isCompatible(javaRuntime.getPlatform()))
failedJavaRuntimes.add(javaRuntime);
String pathString = javaRuntime.getBinary().toString();
ConfigHolder.globalConfig().getDisabledJava().remove(pathString);
if (ConfigHolder.globalConfig().getUserJava().add(pathString))
addJava(javaRuntime);
}
if (!failedJavaRuntimes.isEmpty()) {
StringBuilder sb = new StringBuilder("Incompatible platform: ");
for (JavaRuntime javaRuntime :javaRuntimes)
sb.append('\n').append(javaRuntime.getPlatform()).append(": ").append(javaRuntime.getBinary());
throw new UnsupportedPlatformException(sb.toString());
}
return javaRuntimes;
});
}

public static Task<JavaRuntime> getAddJavaTask(Path binary) {
return Task.supplyAsync("Get Java", () -> JavaManager.getJava(binary))
.thenApplyAsync(Schedulers.javafx(), javaRuntime -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import javafx.scene.control.SkinBase;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.FileChooser;
import javafx.stage.DirectoryChooser;
import org.jackhuang.hmcl.java.JavaInfo;
import org.jackhuang.hmcl.java.JavaManager;
import org.jackhuang.hmcl.java.JavaRuntime;
Expand Down Expand Up @@ -107,25 +107,39 @@ protected Skin<?> createDefaultSkin() {
}

void onAddJava() {
FileChooser chooser = new FileChooser();
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS)
chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java", "java.exe"));
final var chooser = new DirectoryChooser();
chooser.setTitle(i18n("settings.game.java_directory.choose"));
Path file = FileUtils.toPath(chooser.showOpenDialog(Controllers.getStage()));
if (file != null) {
JavaManager.getAddJavaTask(file).whenComplete(Schedulers.javafx(), exception -> {
if (exception != null) {
LOG.warning("Failed to add java", exception);
Controllers.dialog(i18n("java.add.failed"), i18n("message.error"), MessageDialogPane.MessageType.ERROR);
}
}).start();
final var dir = FileUtils.toPath(chooser.showDialog(Controllers.getStage()));
if (dir == null) return;

var file = dir.resolve(OperatingSystem.CURRENT_OS.getJavaExecutable());
file = Files.exists(file) ? file
: dir.resolve("bin").resolve(OperatingSystem.CURRENT_OS.getJavaExecutable());
if (Files.exists(file)) {
onAddJavaBinary(file);
return;
}

onSearchAndAddJavaBinary(dir);
}

void onShowRestoreJavaPage() {
Controllers.navigate(new JavaRestorePage(ConfigHolder.globalConfig().getDisabledJava()));
}

private void onSearchAndAddJavaBinary(Path directory) {
Controllers.taskDialog(
JavaManager.getSearchAndAddJavaTask(directory).thenAcceptAsync(Schedulers.javafx(), javaRuntimes -> {
if (javaRuntimes.isEmpty())
Controllers.dialog(i18n("java.add.not_found"), i18n("message.warning"), MessageDialogPane.MessageType.WARNING);
}).whenComplete(Schedulers.javafx(), exception -> {
if (exception instanceof UnsupportedPlatformException) {
LOG.warning("Failed to add java", exception);
Controllers.dialog(i18n("java.add.failed.some"), i18n("message.error"), MessageDialogPane.MessageType.ERROR);
} else if (exception != null) LOG.warning("Other exception when add java", exception);
}), i18n("java.add"), TaskCancellationAction.NORMAL);
}

private void onAddJavaBinary(Path file) {
JavaManager.getAddJavaTask(file).whenComplete(Schedulers.javafx(), exception -> {
if (exception != null) {
Expand Down
2 changes: 2 additions & 0 deletions HMCL/src/main/resources/assets/lang/I18N.properties
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,8 @@ install.success=Successfully installed.

java.add=Add Java
java.add.failed=This Java is invalid or incompatible with the current platform.
java.add.failed.some=Some of the found Java is invalid or incompatible with the current platform.
java.add.not_found=Java not found in specified directory, or the Java directory is too deep.
java.disable=Disable Java
java.disable.confirm=Are you sure you want to disable this Java?
java.disabled.management=Disabled Java
Expand Down
2 changes: 2 additions & 0 deletions HMCL/src/main/resources/assets/lang/I18N_es.properties
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,8 @@ install.success=Instalado con éxito.

java.add=Añadir Java
java.add.failed=Este Java no es válido o es incompatible con la plataforma actual.
java.add.failed.some=Parte del Java encontrado no es válido o es incompatible con la plataforma actual.
java.add.not_found=Java no se encuentra en el directorio especificado, o el directorio Java es demasiado profundo.
java.disable=Deshabilitar este Java
java.disable.confirm=¿Está seguro de que desea desactivar este Java?
java.disabled.management=Java desactivado
Expand Down
2 changes: 2 additions & 0 deletions HMCL/src/main/resources/assets/lang/I18N_ja.properties
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ install.success=正常にインストールされました

java.add=Javaの追加
java.add.failed=このJavaは無効であるか、現在のプラットフォームと互換性がない。
java.add.failed.some=見つかったJavaのいくつかは無効であるか、現在のプラットフォームと互換性がありません。
java.add.not_found=指定されたディレクトリにJavaが見つからないか、Javaディレクトリが深すぎます。
java.disable=無効化
java.disable.confirm=本当にこのJavaを無効にしますか?
java.disabled.management=無効なJava
Expand Down
2 changes: 2 additions & 0 deletions HMCL/src/main/resources/assets/lang/I18N_ru.properties
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,8 @@ install.success=Успешно установлено.

java.add=Добавить Java
java.add.failed=Этот Java недопустим или несовместим с текущей платформой.
java.add.failed.some=Некоторые из найденных Java недопустимы или несовместимы с текущей платформой.
java.add.not_found=Java не найдена в указанном каталоге, или каталог Java находится слишком глубоко.
java.disable=Отключить Java
java.disable.confirm=Вы уверены, что хотите отключить эту Java?
java.disabled.management=Отключенная Java
Expand Down
2 changes: 2 additions & 0 deletions HMCL/src/main/resources/assets/lang/I18N_zh.properties
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,8 @@ install.success=安裝成功

java.add=添加 Java
java.add.failed=Java 無效或與目前平臺不相容
java.add.failed.some=找到的某些 Java 無效或與目前平臺不相容
java.add.not_found=在指定目錄中找不到 Java,或 Java 目錄太深。
java.disable=停用此 Java
java.disable.confirm=你確定要停用此 Java 嗎?
java.disabled.management=管理已停用的 Java
Expand Down
2 changes: 2 additions & 0 deletions HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,8 @@ install.success=安装成功

java.add=添加 Java
java.add.failed=Java 无效或与当前平台不兼容。
java.add.failed.some=找到的部分 Java 无效或与当前平台不兼容。
java.add.not_found=在指定目录中找不到 Java,或 Java 目录太深。
java.disable=禁用此 Java
java.disable.confirm=你确定要禁用此 Java 吗?
java.disabled.management=管理已禁用的 Java
Expand Down