Merge fa6dd7d5e32797907b01b0e6e967955eed167390 into 9969dc60c5278340b6b9a4d7facdde620e99d1f5

This commit is contained in:
ri-fumo 2025-08-02 23:00:10 +08:00 committed by GitHub
commit f952a60223
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 109 additions and 12 deletions

View File

@ -42,8 +42,10 @@ import java.io.File;
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;
import java.util.stream.Stream;
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
@ -173,6 +175,74 @@ public final class JavaManager {
}).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;
List<JavaRuntime> binaryList = new ArrayList<>();
Queue<Path> queue = new ArrayDeque<>(64);
try(Stream<Path> subDirs = Files.list(dir)) {
subDirs.filter(Files::isDirectory).filter(Files::isReadable).forEach(queue::add);
}
final Path 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");
Path binary = directory.resolve(relative);
if(Files.exists(binary)) {
JavaRuntime 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(Stream<Path> subDirs = Files.list(directory)) {
subDirs.filter(Files::isDirectory).filter(Files::isReadable).forEach(queue::add);
}
}
return Collections.unmodifiableList(binaryList);
}
}.thenApplyAsync("Add Java", Schedulers.javafx(), javaRuntimes -> {
ArrayList<JavaRuntime> failedJavaRuntimes = new ArrayList<>();
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 -> {

View File

@ -29,7 +29,7 @@ import javafx.scene.control.Skin;
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;
@ -106,25 +106,40 @@ public final class JavaManagementPage extends ListPageBase<JavaManagementPage.Ja
}
void onAddJava() {
FileChooser chooser = new FileChooser();
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS)
chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Java", "java.exe"));
final DirectoryChooser chooser = new DirectoryChooser();
chooser.setTitle(i18n("settings.game.java_directory.choose"));
File file = chooser.showOpenDialog(Controllers.getStage());
if (file != null) {
JavaManager.getAddJavaTask(file.toPath()).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();
File dir = chooser.showDialog(Controllers.getStage());
if(dir == null) return;
Path directory = dir.toPath();
Path file = directory.resolve(OperatingSystem.CURRENT_OS.getJavaExecutable());
file = Files.exists(file)? file
: directory.resolve("bin").resolve(OperatingSystem.CURRENT_OS.getJavaExecutable());
if(Files.exists(file)) {
onAddJavaBinary(file);
return;
}
onSearchAndAddJavaBinary(directory);
}
void onShowRestoreJavaPage() {
Controllers.navigate(new JavaRestorePage(ConfigHolder.globalConfig().getDisabledJava()));
}
private void onSearchAndAddJavaBinary(Path directory) {
Task<Void> task = 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);
});
Controllers.taskDialog(task, i18n("java.add"), TaskCancellationAction.NORMAL);
}
private void onAddJavaBinary(Path file) {
JavaManager.getAddJavaTask(file).whenComplete(Schedulers.javafx(), exception -> {
if (exception != null) {

View File

@ -725,6 +725,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

View File

@ -730,6 +730,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

View File

@ -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

View File

@ -726,6 +726,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

View File

@ -541,6 +541,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

View File

@ -551,6 +551,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