diff --git a/arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/installer/SdkmanGraalVMInstaller.java b/arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/installer/SdkmanGraalVMInstaller.java index cae00b3..db0f84f 100644 --- a/arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/installer/SdkmanGraalVMInstaller.java +++ b/arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/installer/SdkmanGraalVMInstaller.java @@ -16,10 +16,9 @@ */ package org.apache.geronimo.arthur.impl.nativeimage.installer; -import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; -import static java.util.Comparator.comparing; -import static java.util.Objects.requireNonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.geronimo.arthur.impl.nativeimage.process.ProcessExecutor; import java.io.BufferedInputStream; import java.io.IOException; @@ -28,12 +27,13 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Optional; import java.util.stream.Stream; -import org.apache.geronimo.arthur.impl.nativeimage.process.ProcessExecutor; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonMap; +import static java.util.Comparator.comparing; +import static java.util.Objects.requireNonNull; @Slf4j @RequiredArgsConstructor @@ -84,7 +84,7 @@ public Path installNativeImage() { final Path bin = requireNonNull(this.home, "No home, ensure to call install() before installNativeImage()") .resolve("bin"); try { - if (findNativeImage(bin).count() == 0) { // likely only UNIx, windows comes with native-image.cmd + if (!findNativeImage(bin).isPresent()) { // likely only UNIx, windows comes with native-image.cmd log.info("Installing native-image"); new ProcessExecutor( configuration.isInheritIO(), asList(findGu(bin).toAbsolutePath().toString(), "install", "native-image"), @@ -93,20 +93,24 @@ public Path installNativeImage() { log.debug("native-image is already available"); } return findNativeImage(bin) - .min(comparing(p -> p.getFileName().toString().length())) // support windows this way (.cmd) .orElseThrow(() -> new IllegalArgumentException("No native-image found in " + bin)); } catch (final IOException e) { throw new IllegalStateException(e); } } - private Stream findNativeImage(final Path bin) throws IOException { - return Files.list(bin).filter(path -> path.getFileName().toString().startsWith("native-image")); + private Optional findNativeImage(final Path bin) throws IOException { + try (final Stream list = Files.list(bin)) { + return list.filter(path -> { + final String name = path.getFileName().toString(); + return name.equals("native-image") || name.startsWith("native-image.") /*win*/; + }).min(comparing(p -> p.getFileName().toString().length())); // support windows this way (.cmd); + } } private Path findGu(final Path bin) { - try { - return Files.list(bin) + try (final Stream list = Files.list(bin)) { + return list .filter(path -> path.getFileName().toString().startsWith("gu")) .min(comparing(p -> p.getFileName().toString().length())) .orElseThrow(() -> new IllegalStateException("No gu found in " + bin)); diff --git a/arthur-maven-plugin/src/main/java/org/apache/geronimo/arthur/maven/mojo/ArthurMojo.java b/arthur-maven-plugin/src/main/java/org/apache/geronimo/arthur/maven/mojo/ArthurMojo.java index 2a284a6..ff55222 100644 --- a/arthur-maven-plugin/src/main/java/org/apache/geronimo/arthur/maven/mojo/ArthurMojo.java +++ b/arthur-maven-plugin/src/main/java/org/apache/geronimo/arthur/maven/mojo/ArthurMojo.java @@ -71,13 +71,13 @@ public abstract class ArthurMojo extends AbstractMojo { /** * In case Graal must be downloaded to get native-image, where to take it from. */ - @Parameter(property = "arthur.graalDownloadUrl", - defaultValue = "https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-${graalSimpleVersion}/graalvm-ce-java${graalJavaVersion}-${githubPlatform}-${graalSimpleVersion}.tar.gz") + @Parameter(property = "arthur.graalDownloadUrl", defaultValue = "auto") private String graalDownloadUrl; /** * In case Graal must be downloaded to get native-image, which version to download. * It contains the graal version and can be suffixed by the graal java version prefixed with "r" (as on sdkman). + * Alternatively, in more recent version you can use "$javaVersion-graalce" or "$javaVersion-graal-oracle" to use the appropriated mirror. */ @Parameter(property = "arthur.graalVersion", defaultValue = "20.3.0.r8") protected String graalVersion; @@ -192,18 +192,31 @@ private String buildDownloadUrl(final String graalPlatform) { final String graalSimpleVersion = versionIncludesJavaVersion ? Stream.of(versionSegments).limit(versionSegments.length - 1).collect(joining(".")) : graalVersion; - final String graalJavaVersion = versionIncludesJavaVersion ? + String graalJavaVersion = versionIncludesJavaVersion ? versionSegments[versionSegments.length - 1].substring(1) : System.getProperty("java.version", "1.8").startsWith("8") ? "8" : "11"; final String githubPlatform = graalPlatform.toLowerCase(ROOT).contains("win") - ? "windows-amd64" - : (graalPlatform.toLowerCase(ROOT).contains("mac") - ? "darwin-amd64" - : "linux-amd64"); - return graalDownloadUrl + ? "windows-amd64" + : (graalPlatform.toLowerCase(ROOT).contains("mac") + ? "darwin-amd64" + : "linux-amd64"); + + // backward compat + String baseUrl = "auto".equals(graalDownloadUrl) ? + "https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-${graalSimpleVersion}/graalvm-ce-java${graalJavaVersion}-${githubPlatform}-${graalSimpleVersion}.tar.gz" : + graalDownloadUrl; + if (graalVersion.endsWith("-graalce")) { + graalJavaVersion = graalVersion.substring(0, graalVersion.length() - "-graalce".length()); + baseUrl = "https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-" + graalJavaVersion + "/graalvm-community-jdk-" + graalJavaVersion + "_${githubPlatform2}_bin.tar.gz"; + } else if (graalVersion.endsWith("-graal-oracle")) { + graalJavaVersion = graalVersion.substring(0, graalVersion.length() - "-graal-oracle".length()); + baseUrl = "https://download.oracle.com/graalvm/" + graalJavaVersion + "/latest/graalvm-jdk-" + graalJavaVersion + "_${githubPlatform2}_bin.tar.gz"; + } + return baseUrl .replace("${graalSimpleVersion}", graalSimpleVersion) .replace("${graalJavaVersion}", graalJavaVersion) - .replace("${githubPlatform}", githubPlatform); + .replace("${githubPlatform}", githubPlatform) + .replace("${githubPlatform2}", githubPlatform.replace("amd64", "x64")); } private String buildPlatform() { diff --git a/documentation/src/content/maven.adoc b/documentation/src/content/maven.adoc index 681438d..c911535 100644 --- a/documentation/src/content/maven.adoc +++ b/documentation/src/content/maven.adoc @@ -49,6 +49,22 @@ You will find all the details of that feature in the configuration section but i 2. GraalVM version is configurable (note that it relies on SDKMan by default so ensure the last version you want to upgrade immediately is available), 3. The plugin caches the GraalVM archive and its unpack flavor in your local maven repository to avoid to download and explode it each time. +=== Tip on graalVersion + +Apache Arthur is able to deduce the download URL of Graal distribution if it is not explicit configured from `graalVersion`. +This enables to avoid to handle the platform with profiles in your own build. +Here are the supported download flavors: + +* If a download URL is set starting with `https://api.sdkman.io/2/broker/download/java/` it will be used (SDKMan). Note that SDKMan does not guanratee your version will be resolvable after some time so good for tests mainly. `graalVersion` is the SDKMan version, +* Else by default we use `https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-${graalSimpleVersion}/graalvm-ce-java${graalJavaVersion}-${githubPlatform}-${graalSimpleVersion}.tar.gz`. `graalVersion` is `$graalVersion.r$mainJavaVersion`, ex: `22.0.3.r17`, +* Else if `graalVersion` is `$javaVersion-graalce` we use `https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-$javaVersion/graalvm-community-jdk-$javaVersion_${githubPlatform2}_bin.tar.gz`, +* Else if `graalVersion` is `$javaVersion-graal-oracle` we use `https://download.oracle.com/graalvm/$javaVersion/latest/graalvm-jdk-$javaVersion_${githubPlatform2}_bin.tar.gz`, +* Else we use the provided download url which can use the following placeholders: +** `graalSimpleVersion`: if there is a `.r$javaVersion` at the end of the `graalVersion` it is the version without this suffix else `graalVersion`, +** `graalJavaVersion`: `graalVersion` sanitized from its suffix (`.r$javaVersion`, `-graalce`, `-graal-oracle`), +** `githubPlatform`: platform deduced from the running JVM one (build one), it ends with `-amd64`, +** `githubPlatform2`: platform deduced from the running JVM one (build one), it ends with `-x64` - `graalce`/`graal-oracle` cases. + == Execution example Here is a dump of a sample execution: diff --git a/documentation/src/main/java/org/apache/geronimo/arthur/documentation/command/Generate.java b/documentation/src/main/java/org/apache/geronimo/arthur/documentation/command/Generate.java index 05e7f25..3f87b62 100644 --- a/documentation/src/main/java/org/apache/geronimo/arthur/documentation/command/Generate.java +++ b/documentation/src/main/java/org/apache/geronimo/arthur/documentation/command/Generate.java @@ -16,18 +16,25 @@ */ package org.apache.geronimo.arthur.documentation.command; -import static java.util.Comparator.comparing; -import static java.util.Locale.ROOT; -import static java.util.concurrent.TimeUnit.MINUTES; -import static java.util.function.Function.identity; -import static java.util.stream.Collectors.joining; -import static org.asciidoctor.SafeMode.UNSAFE; +import org.apache.geronimo.arthur.documentation.download.Downloads; +import org.apache.geronimo.arthur.documentation.io.FolderConfiguration; +import org.apache.geronimo.arthur.documentation.io.FolderVisitor; +import org.apache.geronimo.arthur.documentation.mojo.MojoParser; +import org.apache.geronimo.arthur.documentation.renderer.AsciidocRenderer; +import org.apache.geronimo.arthur.documentation.renderer.TemplateConfiguration; +import org.asciidoctor.Attributes; +import org.asciidoctor.Options; +import org.tomitribe.crest.api.Command; +import org.tomitribe.crest.api.Default; +import org.tomitribe.crest.api.Defaults.DefaultMapping; +import org.tomitribe.crest.api.Err; +import org.tomitribe.crest.api.Option; +import org.tomitribe.crest.api.Out; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.io.PrintStream; import java.io.Writer; import java.nio.charset.StandardCharsets; @@ -53,22 +60,14 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Stream; -import org.apache.geronimo.arthur.documentation.download.Downloads; -import org.apache.geronimo.arthur.documentation.io.FolderConfiguration; -import org.apache.geronimo.arthur.documentation.io.FolderVisitor; -import org.apache.geronimo.arthur.documentation.mojo.MojoParser; -import org.apache.geronimo.arthur.documentation.renderer.AsciidocRenderer; -import org.apache.geronimo.arthur.documentation.renderer.TemplateConfiguration; -import org.asciidoctor.AttributesBuilder; -import org.asciidoctor.Options; -import org.asciidoctor.OptionsBuilder; -import org.tomitribe.crest.api.Command; -import org.tomitribe.crest.api.Default; -import org.tomitribe.crest.api.Defaults.DefaultMapping; -import org.tomitribe.crest.api.Err; -import org.tomitribe.crest.api.Option; -import org.tomitribe.crest.api.Out; +import static java.util.Comparator.comparing; +import static java.util.Locale.ROOT; +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.joining; +import static org.asciidoctor.SafeMode.UNSAFE; public class Generate { @Command @@ -126,13 +125,14 @@ public void generate( return computedTemplatization.get(); }; - final Options adocOptions = OptionsBuilder.options() + final Options adocOptions = Options.builder() .safe(UNSAFE) // we generated_dir is not safe but locally it is ok - .attributes(AttributesBuilder.attributes() - .showTitle(true) - .icons("font") - .attribute("generated_dir", workdir.toAbsolutePath().toString())) - .get(); + .attributes(Attributes.builder() + .showTitle(true) + .icons("font") + .attribute("generated_dir", workdir.toAbsolutePath().toString()) + .build()) + .build(); final CountDownLatch downloadLatch; if (downloadSource != null) { @@ -197,8 +197,8 @@ public void generate( Files.write( target, templatize.get().apply( - metadata.getOrDefault("title", "Arthur"), - renderer.render(read, adocOptions)) + metadata.getOrDefault("title", "Arthur"), + renderer.render(read, adocOptions)) .getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); } catch (final IOException e) { @@ -271,9 +271,9 @@ private void generateMojoDoc(final String marker, final MojoParser mojoParser, f "|===\n" + "|Name|Type|Description\n\n" + parameters.stream() - .sorted(comparing(MojoParser.Parameter::getName)) - .map(this::toLine) - .collect(joining("\n\n")) + + .sorted(comparing(MojoParser.Parameter::getName)) + .map(this::toLine) + .collect(joining("\n\n")) + "\n|===\n"); } stdout.println("Generated documentation for " + mojo); @@ -288,8 +288,8 @@ private String toLine(final MojoParser.Parameter parameter) { } private String read(final Path file) { - try { - return Files.lines(file).collect(joining("\n")); + try (final Stream lines = Files.lines(file)) { + return lines.collect(joining("\n")); } catch (final IOException e) { throw new IllegalStateException(e); } diff --git a/pom.xml b/pom.xml index 146694d..8bb73c8 100644 --- a/pom.xml +++ b/pom.xml @@ -35,9 +35,9 @@ - 1.7.28 + 1.7.36 8.0.0 - 1.21 + 1.23.0 0.1.55