diff --git a/spawn-local-jdk/src/main/java/build/spawn/platform/local/jdk/JDKDetector.java b/spawn-local-jdk/src/main/java/build/spawn/platform/local/jdk/JDKDetector.java index ff2eb7e..07838c1 100644 --- a/spawn-local-jdk/src/main/java/build/spawn/platform/local/jdk/JDKDetector.java +++ b/spawn-local-jdk/src/main/java/build/spawn/platform/local/jdk/JDKDetector.java @@ -134,8 +134,8 @@ static Exceptional of(final Path path) { home = home.getParent(); } - if (!home.resolve("bin/java").toFile().exists()) { - LOGGER.warn("The JDK Home [{0}] does not contain bin/java", home); + if (!home.resolve("bin/java").toFile().exists() && !home.resolve("bin/java.exe").toFile().exists()) { + LOGGER.warn("The JDK Home [{0}] does not contain bin/java or bin/java.exe", home); return Exceptional.empty(); } diff --git a/spawn-local-jdk/src/main/java/build/spawn/platform/local/jdk/LocalJDKLauncher.java b/spawn-local-jdk/src/main/java/build/spawn/platform/local/jdk/LocalJDKLauncher.java index 92bafad..062f828 100644 --- a/spawn-local-jdk/src/main/java/build/spawn/platform/local/jdk/LocalJDKLauncher.java +++ b/spawn-local-jdk/src/main/java/build/spawn/platform/local/jdk/LocalJDKLauncher.java @@ -34,6 +34,7 @@ import build.spawn.application.option.Orphanable; import build.spawn.jdk.AbstractTemplatedJDKLauncher; import build.spawn.jdk.JDKApplication; +import build.spawn.jdk.OperatingSystem; import build.spawn.jdk.agent.SpawnAgent; import build.spawn.jdk.agent.SpawnAgentArchiveBuilder; import build.spawn.jdk.option.JDKAgent; @@ -74,7 +75,11 @@ public class LocalJDKLauncher @Override public Optional getExecutable(final ConfigurationBuilder options) { - return Optional.of(Executable.of(options.get(JDKHome.class).get() + "/bin/java")); + // the JDK is launched on this LocalMachine, so the host's own OperatingSystem determines + // whether the java executable carries a .exe suffix + final var javaExecutable = OperatingSystem.current() == OperatingSystem.WINDOWS ? "bin/java.exe" : "bin/java"; + + return Optional.of(Executable.of(options.get(JDKHome.class).get() + "/" + javaExecutable)); } @Override diff --git a/spawn-local-jdk/src/main/resources/java.home.properties b/spawn-local-jdk/src/main/resources/java.home.properties index 62c0cbf..7dea22c 100644 --- a/spawn-local-jdk/src/main/resources/java.home.properties +++ b/spawn-local-jdk/src/main/resources/java.home.properties @@ -51,3 +51,12 @@ unix@local-java = /usr/local/*java* unix@sdkman = ${user.home}/.sdkman/candidates/java/* unix@homebrew = /home/linuxbrew/.linuxbrew/opt/openjdk*/libexec unix@github-actions = /opt/hostedtoolcache/Java_*/*/* + +windows@oracle = C:/Program Files/Java/jdk-* +windows@zulu = C:/Program Files/Zulu/zulu-* +windows@adoptium = C:/Program Files/Eclipse Adoptium/jdk-* +windows@microsoft = C:/Program Files/Microsoft/jdk-* +windows@corretto = C:/Program Files/Amazon Corretto/jdk* +windows@sdkman = ${user.home}/.sdkman/candidates/java/* +windows@scoop = ${user.home}/scoop/apps/*jdk*/current +windows@github-actions = C:/hostedtoolcache/windows/Java_*/*/* diff --git a/spawn-local-jdk/src/test/java/build/spawn/platform/local/jdk/JDKDetectorForeignPlatformTests.java b/spawn-local-jdk/src/test/java/build/spawn/platform/local/jdk/JDKDetectorForeignPlatformTests.java index 76d1da5..c85fe7c 100644 --- a/spawn-local-jdk/src/test/java/build/spawn/platform/local/jdk/JDKDetectorForeignPlatformTests.java +++ b/spawn-local-jdk/src/test/java/build/spawn/platform/local/jdk/JDKDetectorForeignPlatformTests.java @@ -62,6 +62,30 @@ void shouldFallBackToHostPlatformWhenReleaseFileOmitsOsInfo(@TempDir final Path assertThat(jdk.architecture()).isEqualTo(Architecture.current()); } + /** + * Ensure a staged Windows JDK — which only ships {@code bin/java.exe}, not {@code bin/java} — is + * still recognized as a valid Java Home rather than rejected outright. + */ + @Test + void shouldDetectWindowsJDKWithOnlyJavaExe(@TempDir final Path tempDir) throws IOException { + final var bin = tempDir.resolve("bin"); + Files.createDirectories(bin); + Files.createFile(bin.resolve("java.exe")); + Files.writeString(tempDir.resolve("release"), """ + JAVA_VERSION="21.0.1" + OS_NAME="Windows Server 2022" + OS_ARCH="x86_64" + """); + + final Exceptional result = JDKDetector.of(tempDir); + + assertThat(result.isPresent()).isTrue(); + + final var jdk = result.orElseThrow(); + assertThat(jdk.operatingSystem()).isEqualTo(OperatingSystem.WINDOWS); + assertThat(jdk.architecture()).isEqualTo(Architecture.X86_64); + } + /** * Stages a minimal, fake JDK home: a {@code bin/java} placeholder (so {@link JDKDetector#of(Path)} * accepts it as a JDK home) and the specified {@code release} file content.