From 0be45ac581f57041c8862d4f87faaa5c8f9700b5 Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic Date: Tue, 5 Jul 2022 14:14:08 +0200 Subject: [PATCH 01/12] First draft of changes --- .../buildtools/utils/SharedConstants.java | 2 +- docs/src/docs/asciidoc/gradle-plugin.adoc | 35 ++----------------- docs/src/docs/asciidoc/maven-plugin.adoc | 30 +++------------- .../docs/snippets/gradle/groovy/build.gradle | 2 +- .../snippets/gradle/kotlin/build.gradle.kts | 2 +- .../MetadataRepositoryFunctionalTest.groovy | 4 +-- .../native-config-integration/build.gradle | 4 --- samples/native-config-integration/pom.xml | 7 ++-- 8 files changed, 14 insertions(+), 72 deletions(-) diff --git a/common/utils/src/main/java/org/graalvm/buildtools/utils/SharedConstants.java b/common/utils/src/main/java/org/graalvm/buildtools/utils/SharedConstants.java index 11f3d1e48..c64d1ea05 100644 --- a/common/utils/src/main/java/org/graalvm/buildtools/utils/SharedConstants.java +++ b/common/utils/src/main/java/org/graalvm/buildtools/utils/SharedConstants.java @@ -75,5 +75,5 @@ public interface SharedConstants { String AGENT_SESSION_SUBDIR = "session-{pid}-{datetime}"; String AGENT_OUTPUT_DIRECTORY_MARKER = "{output_dir}"; String AGENT_OUTPUT_DIRECTORY_OPTION = "config-output-dir="; - String METADATA_REPO_URL_TEMPLATE = "https://github.com/graalvm/graalvm-reachability-metadata/releases/download/%1$s/graalvm-reachability-metadata-%1$s.zip"; + String METADATA_REPO_URL_TEMPLATE = "https://github.com/oracle/graalvm-reachability-metadata/releases/download/%1$s/graalvm-reachability-metadata-%1$s.zip"; } diff --git a/docs/src/docs/asciidoc/gradle-plugin.adoc b/docs/src/docs/asciidoc/gradle-plugin.adoc index cb22ce530..418393a93 100644 --- a/docs/src/docs/asciidoc/gradle-plugin.adoc +++ b/docs/src/docs/asciidoc/gradle-plugin.adoc @@ -228,37 +228,6 @@ Currently, this feature requires the execution of the tests in the classic "JVM" NOTE: This plugin requires JUnit Platform 1.8 or higher. -[[mockito-bytebuddy-support]] -=== Mockito / Byte Buddy support - -Mockito is supported starting from version 4.5.0 (ByteBuddy >= 1.12.9) with GraalVM >= 22.1. -However, you need to add the following configuration to make it work with GraalVM 22.1: - -.Enabling Mockito / Byte Buddy support on GraalVM 22.1 -[source,groovy,role="multi-language-sample"] ----- -graalvmNative { - binaries { - test { - buildArgs.add("--rerun-class-initialization-at-runtime=net.bytebuddy.ClassFileVersion,net.bytebuddy.utility.dispatcher.JavaDispatcher,net.bytebuddy.utility.Invoker$Dispatcher") - buildArgs.add("--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable,net.bytebuddy.description.type.TypeDescription$AbstractBase,net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic,net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1,net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2,net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2") - } - } -} ----- - -[source,kotlin,role="multi-language-sample"] ----- -graalvmNative { - binaries { - named("test") { - buildArgs.add("--rerun-class-initialization-at-runtime=net.bytebuddy.ClassFileVersion,net.bytebuddy.utility.dispatcher.JavaDispatcher,net.bytebuddy.utility.Invoker$Dispatcher") - buildArgs.add("--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable,net.bytebuddy.description.type.TypeDescription$AbstractBase,net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic,net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1,net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2,net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2") - } - } -} ----- - [[testing-support-disabling]] === Disabling testing support @@ -358,8 +327,8 @@ See <> for the full list of available options. [[metadata-support]] == GraalVM Reachability Metadata Support -Since release 0.9.11, the plugin adds experimental support for the https://github.com/graalvm/graalvm-reachability-metadata/[GraalVM reachability metadata repository]. -This repository provides GraalVM configuration for libraries which do not officially support GraalVM native. +Since release 0.9.11, the plugin adds experimental support for the https://github.com/oracle/graalvm-reachability-metadata/[GraalVM reachability metadata repository]. +This repository provides https://www.graalvm.org/22.2/reference-manual/native-image/ReachabilityMetadata/[reachability metadata] for libraries that do not support GraalVM Native Image. === Enabling the metadata repository diff --git a/docs/src/docs/asciidoc/maven-plugin.adoc b/docs/src/docs/asciidoc/maven-plugin.adoc index d433db118..e12a08b7a 100644 --- a/docs/src/docs/asciidoc/maven-plugin.adoc +++ b/docs/src/docs/asciidoc/maven-plugin.adoc @@ -349,23 +349,6 @@ with an error similar to the following when attempting to run tests in a native [ERROR] Test configuration file wasn't found. Make sure that test execution wasn't skipped. ---- -[[mockito-bytebuddy-support]] -=== Mockito / Byte Buddy support - -Mockito is supported starting from version 4.5.0 (ByteBuddy >= 1.12.9) with GraalVM >= 22.1. -However, you need to add the following configuration to make it work with GraalVM 22.1: - -.Enabling Mockito / Byte Buddy support on GraalVM 22.1 -[source,xml] ----- - - - --rerun-class-initialization-at-runtime=net.bytebuddy.ClassFileVersion,net.bytebuddy.utility.dispatcher.JavaDispatcher,net.bytebuddy.utility.Invoker$Dispatcher - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable,net.bytebuddy.description.type.TypeDescription$AbstractBase,net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic,net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1,net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2,net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 - - ----- - [[testing-support-disabling]] === Disabling testing support @@ -609,25 +592,20 @@ with those configuration files, you then need to execute the following command: mvn -Pnative -Dagent=true -DskipTests package exec:exec@native ``` -WARNING: If the agent is enabled, the `--allow-incomplete-classpath` option is -automatically added to your native build options. - [[metadata-support]] == GraalVM Reachability Metadata Support -Since release 0.9.12, the plugin adds experimental support for the https://github.com/graalvm/graalvm-reachability-metadata/[GraalVM reachability metadata repository]. -This repository provides GraalVM metadata for libraries which do not officially support GraalVM native. - -A metadata repository consists of configuration files for GraalVM. +Since release 0.9.12, the plugin adds experimental support for the https://github.com/oracle/graalvm-reachability-metadata/[GraalVM reachability metadata repository]. +This repository provides https://www.graalvm.org/22.2/reference-manual/native-image/ReachabilityMetadata/[reachability metadata] for libraries that do not support GraalVM Native Image. === Enabling the metadata repository -Support needs to be enabled explicitly:. It is possible to use a _local repository_, in which case you can specify the path to the repository: +Support needs to be enabled explicitly: .Enabling the metadata repository [source,xml,indent=0] ---- -include::../../../../samples/native-config-integration/pom.xml[tag=metadata-local] +include::../../../../samples/native-config-integration/pom.xml[tag=metadata-default] ---- <1> The local path can point to an _exploded_ directory, or to a compressed ZIP file. diff --git a/docs/src/docs/snippets/gradle/groovy/build.gradle b/docs/src/docs/snippets/gradle/groovy/build.gradle index 7f375d323..ff96c78c3 100644 --- a/docs/src/docs/snippets/gradle/groovy/build.gradle +++ b/docs/src/docs/snippets/gradle/groovy/build.gradle @@ -176,7 +176,7 @@ graalvmNative { // tag::specify-metadata-repository-version[] graalvmNative { metadataRepository { - version = "1.0.0" + version = "0.1.0" } } // end::specify-metadata-repository-version[] diff --git a/docs/src/docs/snippets/gradle/kotlin/build.gradle.kts b/docs/src/docs/snippets/gradle/kotlin/build.gradle.kts index a19cf5ba2..e30f416a1 100644 --- a/docs/src/docs/snippets/gradle/kotlin/build.gradle.kts +++ b/docs/src/docs/snippets/gradle/kotlin/build.gradle.kts @@ -189,7 +189,7 @@ graalvmNative { // tag::specify-metadata-repository-version[] graalvmNative { metadataRepository { - version.set("1.0.0") + version.set("0.1.0") } } // end::specify-metadata-repository-version[] diff --git a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/MetadataRepositoryFunctionalTest.groovy b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/MetadataRepositoryFunctionalTest.groovy index 5d5483278..2f0c983aa 100644 --- a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/MetadataRepositoryFunctionalTest.groovy +++ b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/MetadataRepositoryFunctionalTest.groovy @@ -73,7 +73,7 @@ class MetadataRepositoryFunctionalTest extends AbstractGraalVMMavenFunctionalTes withSample("native-config-integration") when: - mvn '-Pnative,metadataLocal', '-DskipTests', 'package', 'exec:exec@native' + mvn '-Pnative,metadataDefault', '-DskipTests', 'package', 'exec:exec@native' then: buildSucceeded @@ -91,7 +91,7 @@ class MetadataRepositoryFunctionalTest extends AbstractGraalVMMavenFunctionalTes withSample("native-config-integration") when: - mvn '-Pnative,metadataLocal,excludeConfigTest', '-DnativeDryRun', 'package' + mvn '-Pnative,metadataDefault,excludeConfigTest', '-DnativeDryRun', 'package' then: buildSucceeded diff --git a/samples/native-config-integration/build.gradle b/samples/native-config-integration/build.gradle index dc38d47af..8919cad54 100644 --- a/samples/native-config-integration/build.gradle +++ b/samples/native-config-integration/build.gradle @@ -70,10 +70,6 @@ tasks.withType(Test).configureEach { graalvmNative { metadataRepository { enabled = true - def extension = System.getProperty("extension", '') - def repo = file("config-directory${extension ? '.' + extension : ''}") - println("Using config repo: $repo") - uri(repo) } binaries.all { verbose = true diff --git a/samples/native-config-integration/pom.xml b/samples/native-config-integration/pom.xml index 959cf5113..be9acdd40 100644 --- a/samples/native-config-integration/pom.xml +++ b/samples/native-config-integration/pom.xml @@ -148,10 +148,10 @@ - metadataLocal + metadataDefault - + org.graalvm.buildtools native-maven-plugin @@ -159,11 +159,10 @@ true - ${project.basedir}/config-directory - + From fccfb8f7cbe2b2ec5c200a12cc6a6a482ab0f3ad Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Tue, 5 Jul 2022 18:20:22 +0200 Subject: [PATCH 02/12] Introduce a default metadata repo version --- .../java/org/graalvm/buildtools/utils/SharedConstants.java | 1 + .../java/org/graalvm/buildtools/gradle/NativeImagePlugin.java | 1 + .../maven/config/MetadataRepositoryConfiguration.java | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/common/utils/src/main/java/org/graalvm/buildtools/utils/SharedConstants.java b/common/utils/src/main/java/org/graalvm/buildtools/utils/SharedConstants.java index c64d1ea05..6498e8d60 100644 --- a/common/utils/src/main/java/org/graalvm/buildtools/utils/SharedConstants.java +++ b/common/utils/src/main/java/org/graalvm/buildtools/utils/SharedConstants.java @@ -76,4 +76,5 @@ public interface SharedConstants { String AGENT_OUTPUT_DIRECTORY_MARKER = "{output_dir}"; String AGENT_OUTPUT_DIRECTORY_OPTION = "config-output-dir="; String METADATA_REPO_URL_TEMPLATE = "https://github.com/oracle/graalvm-reachability-metadata/releases/download/%1$s/graalvm-reachability-metadata-%1$s.zip"; + String METADATA_REPO_DEFAULT_VERSION = "0.1.0"; } diff --git a/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/NativeImagePlugin.java b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/NativeImagePlugin.java index 23a96dc06..70b887e25 100644 --- a/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/NativeImagePlugin.java +++ b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/NativeImagePlugin.java @@ -423,6 +423,7 @@ private GraalVMExtension registerGraalVMExtension(Project project) { private void configureNativeConfigurationRepo(ExtensionAware graalvmNative) { GraalVMReachabilityMetadataRepositoryExtension configurationRepository = graalvmNative.getExtensions().create("metadataRepository", GraalVMReachabilityMetadataRepositoryExtension.class); configurationRepository.getEnabled().convention(false); + configurationRepository.getVersion().convention(SharedConstants.METADATA_REPO_DEFAULT_VERSION); configurationRepository.getUri().convention(configurationRepository.getVersion().map(v -> { try { return new URI(String.format(METADATA_REPO_URL_TEMPLATE, v)); diff --git a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java index d63610721..6dd1b65d2 100644 --- a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java +++ b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java @@ -44,6 +44,7 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Dependency; import org.apache.maven.plugins.annotations.Parameter; +import org.graalvm.buildtools.utils.SharedConstants; import java.io.File; import java.net.URL; @@ -56,7 +57,7 @@ public class MetadataRepositoryConfiguration { @Parameter(defaultValue = "false") private boolean enabled; - @Parameter + @Parameter(defaultValue = SharedConstants.METADATA_REPO_DEFAULT_VERSION) private String version; @Parameter From d522ce77723f8523ff3109326c9ff05019976db5 Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Wed, 6 Jul 2022 02:16:15 +0200 Subject: [PATCH 03/12] Fix extraction of remote metadata repositories --- .../internal/FileSystemRepository.java | 15 +++++++++++++-- .../GraalVMReachabilityMetadataService.java | 18 ++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/common/graalvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/FileSystemRepository.java b/common/graalvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/FileSystemRepository.java index e74b436d5..76dc0e26f 100644 --- a/common/graalvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/FileSystemRepository.java +++ b/common/graalvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/FileSystemRepository.java @@ -73,9 +73,20 @@ public FileSystemRepository(Path rootDirectory, Logger logger) { this.rootDirectory = rootDirectory; } - public static boolean isSupportedArchiveFormat(String path) { + private static final String[] SUPPORTED_FORMATS = {".zip", ".tar.gz", ".tar.bz2"}; + + public static String getArchiveFormat(String path) { String normalizedPath = path.toLowerCase(); - return normalizedPath.endsWith(".zip") || normalizedPath.endsWith(".tar.gz") || normalizedPath.endsWith(".tar.bz2"); + for (String format : SUPPORTED_FORMATS) { + if (normalizedPath.endsWith(format)) { + return format; + } + } + return null; + } + + public static boolean isSupportedArchiveFormat(String path) { + return getArchiveFormat(path) != null; } @Override diff --git a/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/GraalVMReachabilityMetadataService.java b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/GraalVMReachabilityMetadataService.java index f2335e2d4..dc4e8c355 100644 --- a/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/GraalVMReachabilityMetadataService.java +++ b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/GraalVMReachabilityMetadataService.java @@ -122,9 +122,23 @@ private GraalVMReachabilityMetadataRepository newRepository(URI uri) throws URIS } return newRepositoryFromDirectory(localFile.toPath(), logLevel); } - if (FileSystemRepository.isSupportedArchiveFormat(path)) { - File zipped = getParameters().getCacheDir().file(cacheKey + "/archive").get().getAsFile(); + String format = FileSystemRepository.getArchiveFormat(path); + if (format != null) { + File zipped = getParameters().getCacheDir().file(cacheKey + "/archive" + format).get().getAsFile(); if (!zipped.exists()) { + File cacheDirParent = zipped.getParentFile(); + if (cacheDirParent.exists()) { + if (!cacheDirParent.isDirectory()) { + throw new RuntimeException("Cache directory path must not exist or must be a directory: " + cacheDirParent.getAbsolutePath()); + } + } else { + try { + Files.createDirectories(cacheDirParent.toPath()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + try (ReadableByteChannel readableByteChannel = Channels.newChannel(uri.toURL().openStream())) { try (FileOutputStream fileOutputStream = new FileOutputStream(zipped)) { fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE); From 0e41e1976da7c5a5e102913e5c4ee4fe4a3bd37c Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Wed, 6 Jul 2022 02:42:07 +0200 Subject: [PATCH 04/12] Add a remote metadata repository sample --- .../RemoteMetadataRepoFunctionalTest.groovy | 66 +++++++++++++++ samples/metadata-repo-integration/.gitignore | 1 + .../metadata-repo-integration/build.gradle | 68 +++++++++++++++ .../gradle.properties | 2 + .../metadata-repo-integration/settings.gradle | 11 +++ .../java/org/graalvm/example/H2Example.java | 82 +++++++++++++++++++ 6 files changed, 230 insertions(+) create mode 100644 native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/RemoteMetadataRepoFunctionalTest.groovy create mode 100644 samples/metadata-repo-integration/.gitignore create mode 100644 samples/metadata-repo-integration/build.gradle create mode 100644 samples/metadata-repo-integration/gradle.properties create mode 100644 samples/metadata-repo-integration/settings.gradle create mode 100644 samples/metadata-repo-integration/src/main/java/org/graalvm/example/H2Example.java diff --git a/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/RemoteMetadataRepoFunctionalTest.groovy b/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/RemoteMetadataRepoFunctionalTest.groovy new file mode 100644 index 000000000..8ad86e3d6 --- /dev/null +++ b/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/RemoteMetadataRepoFunctionalTest.groovy @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.graalvm.buildtools.gradle + +import org.graalvm.buildtools.gradle.fixtures.AbstractFunctionalTest +import org.gradle.api.logging.LogLevel +import spock.lang.Unroll + +class RemoteMetadataRepoFunctionalTest extends AbstractFunctionalTest { + + def "can build and run a native-image using metadata from the remote repository"() { + given: + withSample("metadata-repo-integration") + + when: + run 'nativeRun', "-D${NativeImagePlugin.CONFIG_REPO_LOGLEVEL}=${LogLevel.LIFECYCLE}" + + then: + tasks { + succeeded ':jar', ':nativeCompile', ':nativeRun' + } + + and: "finds metadata in the remote repository" + outputContains "[graalvm reachability metadata repository for com.h2database:h2:2.1.210]: Configuration directory is com.h2database/h2/2.1.210" + } + +} diff --git a/samples/metadata-repo-integration/.gitignore b/samples/metadata-repo-integration/.gitignore new file mode 100644 index 000000000..249cda967 --- /dev/null +++ b/samples/metadata-repo-integration/.gitignore @@ -0,0 +1 @@ +/data \ No newline at end of file diff --git a/samples/metadata-repo-integration/build.gradle b/samples/metadata-repo-integration/build.gradle new file mode 100644 index 000000000..426b1aae6 --- /dev/null +++ b/samples/metadata-repo-integration/build.gradle @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +plugins { + id 'application' + id 'org.graalvm.buildtools.native' +} + +repositories { + mavenCentral() +} + +application { + mainClass.set('org.graalvm.example.H2Example') +} + +String h2_version = getProperty("h2.version") + + +dependencies { + implementation("com.h2database:h2:$h2_version") +} + +graalvmNative { + agent { + defaultMode = "standard" + } + metadataRepository { + enabled = true + } +} diff --git a/samples/metadata-repo-integration/gradle.properties b/samples/metadata-repo-integration/gradle.properties new file mode 100644 index 000000000..b59b5f944 --- /dev/null +++ b/samples/metadata-repo-integration/gradle.properties @@ -0,0 +1,2 @@ +native.gradle.plugin.version = 0.9.13-SNAPSHOT +h2.version = 2.1.210 diff --git a/samples/metadata-repo-integration/settings.gradle b/samples/metadata-repo-integration/settings.gradle new file mode 100644 index 000000000..5a909b526 --- /dev/null +++ b/samples/metadata-repo-integration/settings.gradle @@ -0,0 +1,11 @@ +pluginManagement { + plugins { + id 'org.graalvm.buildtools.native' version getProperty('native.gradle.plugin.version') + } + repositories { + mavenCentral() + gradlePluginPortal() + } +} + +rootProject.name = 'h2-demo' diff --git a/samples/metadata-repo-integration/src/main/java/org/graalvm/example/H2Example.java b/samples/metadata-repo-integration/src/main/java/org/graalvm/example/H2Example.java new file mode 100644 index 000000000..644981822 --- /dev/null +++ b/samples/metadata-repo-integration/src/main/java/org/graalvm/example/H2Example.java @@ -0,0 +1,82 @@ +package org.graalvm.example; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Moritz Halbritter + */ +public class H2Example { + + public static final String JDBC_CONNECTION_URL = "jdbc:h2:./data/test"; + + public static void main(String[] args) throws Exception { + // Cleanup + withConnection(JDBC_CONNECTION_URL, connection -> { + connection.prepareStatement("DROP TABLE IF EXISTS customers").execute(); + connection.commit(); + }); + + Set customers = Set.of("Lord Archimonde", "Arthur", "Gilbert", "Grug"); + + System.out.println("=== Inserting the following customers in the database: "); + printCustomers(customers); + + // Insert data + withConnection(JDBC_CONNECTION_URL, connection -> { + connection.prepareStatement("CREATE TABLE customers(id INTEGER AUTO_INCREMENT, name VARCHAR)").execute(); + PreparedStatement statement = connection.prepareStatement("INSERT INTO customers(name) VALUES (?)"); + for (String customer : customers) { + statement.setString(1, customer); + statement.executeUpdate(); + } + connection.commit(); + }); + + System.out.println(""); + System.out.println("=== Reading customers from the database."); + System.out.println(""); + + Set savedCustomers = new HashSet<>(); + // Read data + withConnection(JDBC_CONNECTION_URL, connection -> { + try (ResultSet resultSet = connection.prepareStatement("SELECT * FROM customers").executeQuery()) { + while (resultSet.next()) { + savedCustomers.add(resultSet.getObject(2, String.class)); + } + } + }); + + System.out.println("=== Customers in the database: "); + printCustomers(savedCustomers); + } + + private static void printCustomers(Set customers) { + List customerList = new ArrayList<>(customers); + customerList.sort(Comparator.naturalOrder()); + int i = 0; + for (String customer : customerList) { + System.out.println((i + 1) + ". " + customer); + i++; + } + } + + private static void withConnection(String url, ConnectionCallback callback) throws SQLException { + try (Connection connection = DriverManager.getConnection(url)) { + connection.setAutoCommit(false); + callback.run(connection); + } + } + + private interface ConnectionCallback { + void run(Connection connection) throws SQLException; + } +} From ac966eb7c7d700c8f14a961f3f15c8722230325c Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Wed, 6 Jul 2022 03:30:49 +0200 Subject: [PATCH 05/12] Maven: use the default metadata repository URL and version if none is set --- .../buildtools/maven/AbstractNativeMojo.java | 24 ++++++++++++------- .../MetadataRepositoryConfiguration.java | 2 +- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeMojo.java b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeMojo.java index 1d35589a5..88e8a0571 100644 --- a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeMojo.java +++ b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeMojo.java @@ -446,18 +446,24 @@ protected boolean isMetadataRepositoryEnabled() { protected void configureMetadataRepository() { if (isMetadataRepositoryEnabled()) { Path repoPath = null; - if (metadataRepositoryConfiguration.getVersion() != null && metadataRepositoryConfiguration.getUrl() == null) { - String metadataUrl = String.format(METADATA_REPO_URL_TEMPLATE, metadataRepositoryConfiguration.getVersion()); - try { - metadataRepositoryConfiguration.setUrl(new URI(metadataUrl).toURL()); - } catch (URISyntaxException | MalformedURLException e) { - throw new RuntimeException(e); - } - } if (metadataRepositoryConfiguration.getLocalPath() != null) { Path localPath = metadataRepositoryConfiguration.getLocalPath().toPath(); repoPath = unzipLocalMetadata(localPath); - } else if (metadataRepositoryConfiguration.getUrl() != null) { + } else { + URL targetUrl = metadataRepositoryConfiguration.getUrl(); + if (targetUrl == null) { + String version = metadataRepositoryConfiguration.getVersion(); + if (version == null) { + version = SharedConstants.METADATA_REPO_DEFAULT_VERSION; + } + String metadataUrl = String.format(METADATA_REPO_URL_TEMPLATE, version); + try { + targetUrl = new URI(metadataUrl).toURL(); + metadataRepositoryConfiguration.setUrl(targetUrl); + } catch (URISyntaxException | MalformedURLException e) { + throw new RuntimeException(e); + } + } Optional download = downloadMetadata(metadataRepositoryConfiguration.getUrl()); if (download.isPresent()) { logger.info("Downloaded GraalVM reachability metadata repository from " + metadataRepositoryConfiguration.getUrl()); diff --git a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java index 6dd1b65d2..18f8e0791 100644 --- a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java +++ b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java @@ -57,7 +57,7 @@ public class MetadataRepositoryConfiguration { @Parameter(defaultValue = "false") private boolean enabled; - @Parameter(defaultValue = SharedConstants.METADATA_REPO_DEFAULT_VERSION) + @Parameter private String version; @Parameter From cafbc13a39adf8e590fa5d45fb287361cfedae93 Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Wed, 6 Jul 2022 03:57:42 +0200 Subject: [PATCH 06/12] Maven: Add reachability metadata repository caching --- .../graalvm/buildtools/utils/FileUtils.java | 20 ++++++++++ .../GraalVMReachabilityMetadataService.java | 22 +---------- .../buildtools/maven/AbstractNativeMojo.java | 37 ++++++++++++++----- 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/common/utils/src/main/java/org/graalvm/buildtools/utils/FileUtils.java b/common/utils/src/main/java/org/graalvm/buildtools/utils/FileUtils.java index cd731213a..5c8438ecd 100644 --- a/common/utils/src/main/java/org/graalvm/buildtools/utils/FileUtils.java +++ b/common/utils/src/main/java/org/graalvm/buildtools/utils/FileUtils.java @@ -42,11 +42,16 @@ package org.graalvm.buildtools.utils; import java.io.IOException; +import java.math.BigInteger; import java.net.HttpURLConnection; +import java.net.URI; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Optional; import java.util.function.Consumer; import java.util.zip.ZipEntry; @@ -140,4 +145,19 @@ private static Optional sanitizePath(ZipEntry entry, Path destination) { return Optional.empty(); } } + + public static String hashFor(URI uri) { + try { + MessageDigest md = MessageDigest.getInstance("SHA-1"); + byte[] messageDigest = md.digest(md.digest(uri.toString().getBytes(StandardCharsets.UTF_8))); + BigInteger no = new BigInteger(1, messageDigest); + StringBuilder digest = new StringBuilder(no.toString(16)); + while (digest.length() < 32) { + digest.insert(0, "0"); + } + return digest.toString(); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException(e); + } + } } diff --git a/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/GraalVMReachabilityMetadataService.java b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/GraalVMReachabilityMetadataService.java index dc4e8c355..d348f0b31 100644 --- a/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/GraalVMReachabilityMetadataService.java +++ b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/GraalVMReachabilityMetadataService.java @@ -40,6 +40,7 @@ */ package org.graalvm.buildtools.gradle.internal; +import org.graalvm.buildtools.utils.FileUtils; import org.graalvm.reachability.GraalVMReachabilityMetadataRepository; import org.graalvm.reachability.Query; import org.graalvm.reachability.internal.FileSystemRepository; @@ -57,16 +58,12 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.math.BigInteger; import java.net.URI; import java.net.URISyntaxException; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.Collection; import java.util.Set; import java.util.function.Consumer; @@ -96,23 +93,8 @@ public GraalVMReachabilityMetadataService() throws URISyntaxException { this.repository = newRepository(uri); } - private static String hashFor(URI uri) { - try { - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] messageDigest = md.digest(md.digest(uri.toString().getBytes(StandardCharsets.UTF_8))); - BigInteger no = new BigInteger(1, messageDigest); - StringBuilder digest = new StringBuilder(no.toString(16)); - while (digest.length() < 32) { - digest.insert(0, "0"); - } - return digest.toString(); - } catch (NoSuchAlgorithmException e) { - throw new UnsupportedOperationException(e); - } - } - private GraalVMReachabilityMetadataRepository newRepository(URI uri) throws URISyntaxException { - String cacheKey = hashFor(uri); + String cacheKey = FileUtils.hashFor(uri); String path = uri.getPath(); LogLevel logLevel = getParameters().getLogLevel().get(); if (uri.getScheme().equals("file")) { diff --git a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeMojo.java b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeMojo.java index 88e8a0571..b8cc93b9b 100644 --- a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeMojo.java +++ b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeMojo.java @@ -446,9 +446,20 @@ protected boolean isMetadataRepositoryEnabled() { protected void configureMetadataRepository() { if (isMetadataRepositoryEnabled()) { Path repoPath = null; + Path destinationRoot = outputDirectory.toPath().resolve("graalvm-reachability-metadata"); + if (Files.exists(destinationRoot) && !Files.isDirectory(destinationRoot)) { + throw new RuntimeException("Metadata repository must be a directory, please remove regular file at: " + destinationRoot); + } + try { + Files.createDirectories(destinationRoot); + } catch (IOException e) { + throw new RuntimeException(e); + } + if (metadataRepositoryConfiguration.getLocalPath() != null) { Path localPath = metadataRepositoryConfiguration.getLocalPath().toPath(); - repoPath = unzipLocalMetadata(localPath); + Path destination = outputDirectory.toPath().resolve(FileUtils.hashFor(localPath.toUri())); + repoPath = unzipLocalMetadata(localPath, destination); } else { URL targetUrl = metadataRepositoryConfiguration.getUrl(); if (targetUrl == null) { @@ -464,10 +475,20 @@ protected void configureMetadataRepository() { throw new RuntimeException(e); } } - Optional download = downloadMetadata(metadataRepositoryConfiguration.getUrl()); - if (download.isPresent()) { - logger.info("Downloaded GraalVM reachability metadata repository from " + metadataRepositoryConfiguration.getUrl()); - repoPath = unzipLocalMetadata(download.get()); + Path destination; + try { + destination = destinationRoot.resolve(FileUtils.hashFor(targetUrl.toURI())); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + if (Files.exists(destination)) { + repoPath = destination; + } else { + Optional download = downloadMetadata(targetUrl, destination); + if (download.isPresent()) { + logger.info("Downloaded GraalVM reachability metadata repository from " + targetUrl); + repoPath = unzipLocalMetadata(download.get(), destination); + } } } @@ -528,15 +549,13 @@ protected Optional getMetadataVersion(Artifact dependency) { } } - protected Optional downloadMetadata(URL url) { - Path destination = outputDirectory.toPath().resolve("graalvm-reachability-metadata"); + protected Optional downloadMetadata(URL url, Path destination) { return FileUtils.download(url, destination, logger::error); } - protected Path unzipLocalMetadata(Path localPath) { + protected Path unzipLocalMetadata(Path localPath, Path destination) { if (Files.exists(localPath)) { if (FileUtils.isZip(localPath)) { - Path destination = outputDirectory.toPath().resolve("graalvm-reachability-metadata"); if (!Files.exists(destination) && !destination.toFile().mkdirs()) { throw new RuntimeException("Failed creating destination directory"); } From ac7ad4124ca55bc23210e43eb44034bd024d5014 Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Wed, 6 Jul 2022 04:15:32 +0200 Subject: [PATCH 07/12] Build and run the metadata integration sample with Maven --- ...OfficialMetadataRepoFunctionalTest.groovy} | 4 +- ...ialMetadataRepositoryFunctionalTest.groovy | 61 +++++++ samples/metadata-repo-integration/pom.xml | 164 ++++++++++++++++++ 3 files changed, 227 insertions(+), 2 deletions(-) rename native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/{RemoteMetadataRepoFunctionalTest.groovy => OfficialMetadataRepoFunctionalTest.groovy} (94%) create mode 100644 native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/OfficialMetadataRepositoryFunctionalTest.groovy create mode 100644 samples/metadata-repo-integration/pom.xml diff --git a/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/RemoteMetadataRepoFunctionalTest.groovy b/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/OfficialMetadataRepoFunctionalTest.groovy similarity index 94% rename from native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/RemoteMetadataRepoFunctionalTest.groovy rename to native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/OfficialMetadataRepoFunctionalTest.groovy index 8ad86e3d6..2d4c3ae2a 100644 --- a/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/RemoteMetadataRepoFunctionalTest.groovy +++ b/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/OfficialMetadataRepoFunctionalTest.groovy @@ -45,9 +45,9 @@ import org.graalvm.buildtools.gradle.fixtures.AbstractFunctionalTest import org.gradle.api.logging.LogLevel import spock.lang.Unroll -class RemoteMetadataRepoFunctionalTest extends AbstractFunctionalTest { +class OfficialMetadataRepoFunctionalTest extends AbstractFunctionalTest { - def "can build and run a native-image using metadata from the remote repository"() { + def "the application runs when using the official metadata repository"() { given: withSample("metadata-repo-integration") diff --git a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/OfficialMetadataRepositoryFunctionalTest.groovy b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/OfficialMetadataRepositoryFunctionalTest.groovy new file mode 100644 index 000000000..10d152d9b --- /dev/null +++ b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/OfficialMetadataRepositoryFunctionalTest.groovy @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.graalvm.buildtools.maven + +class OfficialMetadataRepositoryFunctionalTest extends AbstractGraalVMMavenFunctionalTest { + void "the application runs when using the official metadata repository"() { + given: + withSample("metadata-repo-integration") + + when: + mvn '-Pnative', '-DskipTests', 'package', 'exec:exec@native' + + then: + buildSucceeded + + and: "the run succeeded and retrieved data from the database" + outputContains "Customers in the database" + + and: "finds metadata in the remote repository" + outputContains "[graalvm reachability metadata repository for com.h2database:h2:2.1.210]: Configuration directory is com.h2database/h2/2.1.210" + } +} diff --git a/samples/metadata-repo-integration/pom.xml b/samples/metadata-repo-integration/pom.xml new file mode 100644 index 000000000..e5af99bd0 --- /dev/null +++ b/samples/metadata-repo-integration/pom.xml @@ -0,0 +1,164 @@ + + + + + 4.0.0 + + org.graalvm.buildtools.examples + maven + 1.0.0-SNAPSHOT + + + 1.8 + UTF-8 + 0.9.13-SNAPSHOT + 0.9.13-SNAPSHOT + 2.1.210 + h2-demo + org.graalvm.example.H2Example + + + + + com.h2database + h2 + ${h2.version} + + + + + + native + + + + org.graalvm.buildtools + native-maven-plugin + ${native.maven.plugin.version} + true + + + build-native + + build + + package + + + + false + ${imageName} + false + + true + + + + + + + + + + ${project.artifactId} + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + 1.8 + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.2 + + + + true + ${mainClass} + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.0.0 + + + java + + java + + + ${mainClass} + + + + native + + exec + + + ${project.build.directory}/${imageName} + ${project.build.directory} + + + + + + + + From 427ab9d892be8e23e24a4c807f31b1b6956ccac3 Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Wed, 6 Jul 2022 05:07:43 +0200 Subject: [PATCH 08/12] Fix checkstyle errors --- .../buildtools/utils/FileUtilsTest.java | 48 ++++++++++++++++++- .../MetadataRepositoryConfiguration.java | 1 - 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/common/utils/src/test/java/org/graalvm/buildtools/utils/FileUtilsTest.java b/common/utils/src/test/java/org/graalvm/buildtools/utils/FileUtilsTest.java index 3cb76d5d9..0af07030f 100644 --- a/common/utils/src/test/java/org/graalvm/buildtools/utils/FileUtilsTest.java +++ b/common/utils/src/test/java/org/graalvm/buildtools/utils/FileUtilsTest.java @@ -1,3 +1,43 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ package org.graalvm.buildtools.utils; import org.junit.jupiter.api.DisplayName; @@ -17,7 +57,9 @@ import java.util.Optional; import java.util.stream.Stream; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; class FileUtilsTest { @@ -97,8 +139,10 @@ void testExtract(@TempDir Path tempDir) throws IOException { assertTrue(Files.isDirectory(tempDir.resolve("org.graalvm.internal/library-with-reflection/1"))); assertTrue(Files.exists(tempDir.resolve("org.graalvm.internal/library-with-reflection/1/reflect-config.json"))); - assertEquals("[ { \"name\": \"org.graalvm.internal.reflect.Message\", \"allDeclaredFields\": true, \"allDeclaredMethods\": true }]", String.join("", Files.readAllLines(tempDir.resolve("org.graalvm.internal/library-with-reflection/1/reflect-config.json")))); + assertEquals("[ { \"name\": \"org.graalvm.internal.reflect.Message\", \"allDeclaredFields\": true, \"allDeclaredMethods\": true }]", + String.join("", Files.readAllLines(tempDir.resolve("org.graalvm.internal/library-with-reflection/1/reflect-config.json")))); } + @Test @DisplayName("It is protected against ZIP slip attacks") void testZipSlip(@TempDir Path tempDir) throws IOException { diff --git a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java index 18f8e0791..d63610721 100644 --- a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java +++ b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java @@ -44,7 +44,6 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Dependency; import org.apache.maven.plugins.annotations.Parameter; -import org.graalvm.buildtools.utils.SharedConstants; import java.io.File; import java.net.URL; From 744d0acd50e311fcf7e238943b64f33b2b312d66 Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Wed, 6 Jul 2022 18:07:40 +0200 Subject: [PATCH 09/12] Revert maven profile change --- .../src/main/java/org/graalvm/example/H2Example.java | 4 +--- samples/native-config-integration/pom.xml | 7 ++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/samples/metadata-repo-integration/src/main/java/org/graalvm/example/H2Example.java b/samples/metadata-repo-integration/src/main/java/org/graalvm/example/H2Example.java index 644981822..b743611ae 100644 --- a/samples/metadata-repo-integration/src/main/java/org/graalvm/example/H2Example.java +++ b/samples/metadata-repo-integration/src/main/java/org/graalvm/example/H2Example.java @@ -11,9 +11,7 @@ import java.util.List; import java.util.Set; -/** - * @author Moritz Halbritter - */ + public class H2Example { public static final String JDBC_CONNECTION_URL = "jdbc:h2:./data/test"; diff --git a/samples/native-config-integration/pom.xml b/samples/native-config-integration/pom.xml index be9acdd40..959cf5113 100644 --- a/samples/native-config-integration/pom.xml +++ b/samples/native-config-integration/pom.xml @@ -148,10 +148,10 @@ - metadataDefault + metadataLocal - + org.graalvm.buildtools native-maven-plugin @@ -159,10 +159,11 @@ true + ${project.basedir}/config-directory - + From a8c0b51fef7038fcb474d048aa816defd1fc9043 Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Wed, 6 Jul 2022 18:20:59 +0200 Subject: [PATCH 10/12] Remove a maven functional test that is now invalid --- .../maven/MetadataRepositoryFunctionalTest.groovy | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/MetadataRepositoryFunctionalTest.groovy b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/MetadataRepositoryFunctionalTest.groovy index 2f0c983aa..6d387b4b4 100644 --- a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/MetadataRepositoryFunctionalTest.groovy +++ b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/MetadataRepositoryFunctionalTest.groovy @@ -55,25 +55,12 @@ class MetadataRepositoryFunctionalTest extends AbstractGraalVMMavenFunctionalTes outputContains "Reflection failed" } - void "it produces a warning if enabled but no repository is configured"() { - given: - withSample("native-config-integration") - - when: - mvn '-Pnative,metadataEnabled', '-DskipTests', 'package', 'exec:exec@native' - - then: - buildSucceeded - outputContains "GraalVM reachability metadata repository is enabled, but no repository has been configured" - outputContains "Reflection failed" - } - void "it can use a metadata repository"() { given: withSample("native-config-integration") when: - mvn '-Pnative,metadataDefault', '-DskipTests', 'package', 'exec:exec@native' + mvn '-Pnative,metadataLocal', '-DskipTests', 'package', 'exec:exec@native' then: buildSucceeded From 3913b1c5bf7c2726805f4c1b650a1372fb3b090d Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic Date: Wed, 6 Jul 2022 22:20:50 +0200 Subject: [PATCH 11/12] mvn: Tests for remote repo and docs --- docs/src/docs/asciidoc/maven-plugin.adoc | 30 +++++++++++----- native-gradle-plugin/README.md | 2 +- ...ialMetadataRepositoryFunctionalTest.groovy | 17 +++++++++ .../build.gradle | 1 - samples/metadata-repo-integration/pom.xml | 36 ++++++++++++++++--- samples/native-config-integration/pom.xml | 16 ++++----- 6 files changed, 80 insertions(+), 22 deletions(-) diff --git a/docs/src/docs/asciidoc/maven-plugin.adoc b/docs/src/docs/asciidoc/maven-plugin.adoc index e12a08b7a..f281e2c52 100644 --- a/docs/src/docs/asciidoc/maven-plugin.adoc +++ b/docs/src/docs/asciidoc/maven-plugin.adoc @@ -556,9 +556,6 @@ command-line argument to Maven as follows. See the documentation for mvn -Pnative -Dagent=true -DagentOptions=periodic-config test ``` -WARNING: If the agent is enabled, the `--allow-incomplete-classpath` option is -automatically added to your native build options. - [[agent-support-running-application]] === Running your application with the agent @@ -595,19 +592,18 @@ mvn -Pnative -Dagent=true -DskipTests package exec:exec@native [[metadata-support]] == GraalVM Reachability Metadata Support -Since release 0.9.12, the plugin adds experimental support for the https://github.com/oracle/graalvm-reachability-metadata/[GraalVM reachability metadata repository]. +Since release 0.9.12, the plugin adds support for the https://github.com/oracle/graalvm-reachability-metadata/[GraalVM reachability metadata repository]. This repository provides https://www.graalvm.org/22.2/reference-manual/native-image/ReachabilityMetadata/[reachability metadata] for libraries that do not support GraalVM Native Image. === Enabling the metadata repository -Support needs to be enabled explicitly: +Support needs to be enabled explicitly by including the following into the `` element: .Enabling the metadata repository [source,xml,indent=0] ---- -include::../../../../samples/native-config-integration/pom.xml[tag=metadata-default] +include::../../../../samples/metadata-repo-integration/pom.xml[tag=metadata-default] ---- -<1> The local path can point to an _exploded_ directory, or to a compressed ZIP file. Alternatively, you can use a _remote repository_, in which case you can specify the URL of the ZIP file: @@ -617,9 +613,27 @@ Alternatively, you can use a _remote repository_, in which case you can specify include::../../../../samples/native-config-integration/pom.xml[tag=metadata-url] ---- +For debugging purposes you can use a local repository: + +.Enabling a local repository +[source,xml,indent=0] +---- +include::../../../../samples/native-config-integration/pom.xml[tag=metadata-local] +---- +<1> The local path can point to an _exploded_ directory, or to a compressed ZIP file. + === Configuring the metadata repository -Once activated, for each library included in the native image, the plugin will automatically search for GraalVM reachability metadata in the repository. +Once activated, for each library included in the native image, the plugin will automatically search for GraalVM reachability metadata in the repository that was released together with the plugin. +In case you want to use another verion of the metadata use: + +.Choosing a version for the metadata repository +[source,xml,indent=0] +---- +include::../../../../samples/metadata-repo-integration/pom.xml[tag=metadata-versioned] +---- + + In some cases, you may need to exclude a particular module from the search. This can be done by configuring that particular dependency: diff --git a/native-gradle-plugin/README.md b/native-gradle-plugin/README.md index 2bb353f1a..a98aae8f5 100644 --- a/native-gradle-plugin/README.md +++ b/native-gradle-plugin/README.md @@ -7,7 +7,7 @@ End-user documentation about the plugins can be found [here](https://graalvm.git ## Building Building of plugin itself should be as simple as: ```bash -./gradlew publishToMavenLocal +./gradlew publishToMavenLocal --no-parallel ``` In order to run testing part of this plugin you need to get (or build) corresponding `junit-platform-native` artifact. diff --git a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/OfficialMetadataRepositoryFunctionalTest.groovy b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/OfficialMetadataRepositoryFunctionalTest.groovy index 10d152d9b..5beb4a0c9 100644 --- a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/OfficialMetadataRepositoryFunctionalTest.groovy +++ b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/OfficialMetadataRepositoryFunctionalTest.groovy @@ -58,4 +58,21 @@ class OfficialMetadataRepositoryFunctionalTest extends AbstractGraalVMMavenFunct and: "finds metadata in the remote repository" outputContains "[graalvm reachability metadata repository for com.h2database:h2:2.1.210]: Configuration directory is com.h2database/h2/2.1.210" } + + void "the application runs when using the versioned official metadata repository"() { + given: + withSample("metadata-repo-integration") + + when: + mvn '-PnativeVersioned', '-DskipTests', 'package', 'exec:exec@native' + + then: + buildSucceeded + + and: "the run succeeded and retrieved data from the database" + outputContains "Customers in the database" + + and: "finds metadata in the remote repository" + outputContains "[graalvm reachability metadata repository for com.h2database:h2:2.1.210]: Configuration directory is com.h2database/h2/2.1.210" + } } diff --git a/samples/java-application-with-reflection/build.gradle b/samples/java-application-with-reflection/build.gradle index c36340782..c5f00982a 100644 --- a/samples/java-application-with-reflection/build.gradle +++ b/samples/java-application-with-reflection/build.gradle @@ -84,7 +84,6 @@ graalvmNative { binaries { test { verbose = true - buildArgs('--allow-incomplete-classpath') } } } diff --git a/samples/metadata-repo-integration/pom.xml b/samples/metadata-repo-integration/pom.xml index e5af99bd0..1f3a0fb70 100644 --- a/samples/metadata-repo-integration/pom.xml +++ b/samples/metadata-repo-integration/pom.xml @@ -86,19 +86,47 @@ - false - ${imageName} - false + true + + + + + + + + nativeVersioned + + + + org.graalvm.buildtools + native-maven-plugin + ${native.maven.plugin.version} + true + + + build-native + + build + + package + + + + + + true + 0.1.0 + + - ${project.artifactId} diff --git a/samples/native-config-integration/pom.xml b/samples/native-config-integration/pom.xml index 959cf5113..f2cff3d5f 100644 --- a/samples/native-config-integration/pom.xml +++ b/samples/native-config-integration/pom.xml @@ -151,19 +151,19 @@ metadataLocal - org.graalvm.buildtools native-maven-plugin ${native.maven.plugin.version} + true ${project.basedir}/config-directory + - @@ -227,12 +227,12 @@ metadataExclude - org.graalvm.buildtools native-maven-plugin ${native.maven.plugin.version} + true ${project.basedir}/config-directory @@ -244,9 +244,9 @@ + - @@ -254,13 +254,13 @@ metadataForceVersion - org.graalvm.buildtools native-maven-plugin ${native.maven.plugin.version} false + true ${project.basedir}/config-directory @@ -272,9 +272,9 @@ + - @@ -341,20 +341,20 @@ - org.graalvm.buildtools native-maven-plugin ${native.maven.plugin.version} false + true ${metadata.url} + - From 9462ee23b80a1734323d289585888a8d5a7b8c0c Mon Sep 17 00:00:00 2001 From: Aleksandar Gradinac Date: Thu, 7 Jul 2022 03:14:49 +0200 Subject: [PATCH 12/12] Revert `native-config-integration` sample changes --- samples/native-config-integration/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/samples/native-config-integration/build.gradle b/samples/native-config-integration/build.gradle index 8919cad54..dc38d47af 100644 --- a/samples/native-config-integration/build.gradle +++ b/samples/native-config-integration/build.gradle @@ -70,6 +70,10 @@ tasks.withType(Test).configureEach { graalvmNative { metadataRepository { enabled = true + def extension = System.getProperty("extension", '') + def repo = file("config-directory${extension ? '.' + extension : ''}") + println("Using config repo: $repo") + uri(repo) } binaries.all { verbose = true