diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..aaa63565b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,44 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. +**Make sure that you have read [the documentation](https://graalvm.github.io/native-build-tools) and that you are using the latest plugin version.** + +**To Reproduce** +Steps to reproduce the behavior: +```xml + +``` +```bash +$ # command invocation +``` +Please use backticks to [properly format code](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlighting). +If possible please attach a complete reproducer here (either as [a zip file](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/attaching-files) or as a link to public repository/branch). + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Logs** +Add logs to help explain your problem. +Please use backticks to [properly format big logs](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks). Example: +```` +``` + +``` +```` + +**System Info (please complete the following information):** + - OS: [e.g. `Windows`] + - GraalVM Version [e.g. `22.0 CE`] + - Java Version [e.g. `17`] + - Plugin version [e.g. `native-gradle-plugin:0.9.10`] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..ae4f9ce6c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,21 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] +**Please make sure that you are using the latest plugin version, and that similar feature hasn't been [requested before](https://github.com/graalvm/native-build-tools/issues).** + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/support-ticket.md b/.github/ISSUE_TEMPLATE/support-ticket.md new file mode 100644 index 000000000..109bf595e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/support-ticket.md @@ -0,0 +1,24 @@ +--- +name: Support ticket +about: Ask a question about proper usage +title: "[QUESTION]" +labels: question +assignees: '' + +--- + +**Describe the problem** +A clear and concise description of what the problem is. +**Make sure that you have read [the documentation](https://graalvm.github.io/native-build-tools) and that you are using the latest plugin version.** + +**Additional context** +Add any other context about the problem here. + +**System Info (please complete the following information):** + - OS: [e.g. `Windows`] + - GraalVM Version [e.g. `22.0 CE`] + - Java Version [e.g. `17`] + - Plugin version [e.g. `native-gradle-plugin:0.9.10`] + +**To Reproduce** +If possible please attach a complete reproducer here (either as [a zip file](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/attaching-files) or as a link to public repository/branch). diff --git a/.github/workflows/deploy-snapshots.yml b/.github/workflows/deploy-snapshots.yml.disabled similarity index 100% rename from .github/workflows/deploy-snapshots.yml rename to .github/workflows/deploy-snapshots.yml.disabled diff --git a/.github/workflows/junit-platform-native-feature.yml b/.github/workflows/junit-platform-native-feature.yml index 328fe7908..d1bf9c2f4 100644 --- a/.github/workflows/junit-platform-native-feature.yml +++ b/.github/workflows/junit-platform-native-feature.yml @@ -26,21 +26,11 @@ jobs: echo "JAVA_HOME=$JAVA_HOME" >> $GITHUB_ENV echo "GRAALVM_HOME=$GRAALVM_HOME" >> $GITHUB_ENV - name: Checkstyle - run: | - pushd common/junit-platform-native - ./gradlew checkstyleMain - ./gradlew checkstyleTest - popd + run: ./gradlew :junit-platform-native:checkstyleMain :junit-platform-native:checkstyleTest - name: JVM test - run: | - pushd common/junit-platform-native - ./gradlew test - popd + run: ./gradlew :junit-platform-native:test - name: Feature test - run: | - pushd common/junit-platform-native - ./gradlew nativeTest - popd + run: ./gradlew :junit-platform-native:nativeTest - name: Tests results if: always() uses: actions/upload-artifact@v2 diff --git a/.github/workflows/jvm-metadata-config.yml b/.github/workflows/jvm-metadata-config.yml new file mode 100644 index 000000000..8df508868 --- /dev/null +++ b/.github/workflows/jvm-metadata-config.yml @@ -0,0 +1,37 @@ +name: JVM Reachability Metadata Repository + +on: + push: + paths: + - 'common/jvm-reachability-metadata/**' + pull_request: + paths: + - 'common/jvm-reachability-metadata/**' + workflow_dispatch: + +jobs: + test-jvm-reachability-metadata: + name: + runs-on: ubuntu-18.04 + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 1 + - name: Get GraalVM Nightly + run: | + source common/scripts/downloadGraalVM.sh + echo "$GRAALVM_HOME/bin" >> $GITHUB_PATH + echo "JAVA_HOME=$JAVA_HOME" >> $GITHUB_ENV + echo "GRAALVM_HOME=$GRAALVM_HOME" >> $GITHUB_ENV + - name: Checkstyle + run: ./gradlew :jvm-reachability-metadata:checkstyleMain :jvm-reachability-metadata:checkstyleTest + - name: JVM test + run: ./gradlew :jvm-reachability-metadata:test + - name: Tests results + if: always() + uses: actions/upload-artifact@v2 + with: + name: tests-results + path: common/jvm-reachability-metadata/build/reports/tests/ diff --git a/.github/workflows/native-gradle-plugin.yml b/.github/workflows/native-gradle-plugin.yml index f23a97cb4..b459b42ac 100644 --- a/.github/workflows/native-gradle-plugin.yml +++ b/.github/workflows/native-gradle-plugin.yml @@ -30,10 +30,7 @@ jobs: echo "JAVA_HOME=$JAVA_HOME" >> $GITHUB_ENV echo "GRAALVM_HOME=$GRAALVM_HOME" >> $GITHUB_ENV - name: Unit tests and inspections - run: | - pushd native-gradle-plugin - ./gradlew test inspections - popd + run: ./gradlew :native-gradle-plugin:test :native-gradle-plugin:inspections - name: Unit tests results uses: actions/upload-artifact@v1 with: @@ -57,10 +54,7 @@ jobs: echo "JAVA_HOME=$JAVA_HOME" >> $GITHUB_ENV echo "GRAALVM_HOME=$GRAALVM_HOME" >> $GITHUB_ENV - name: Check and test the plugin - run: | - pushd native-gradle-plugin - ./gradlew functionalTest -DgradleVersion=${{ matrix.gradle-version }} - popd + run: ./gradlew :native-gradle-plugin:functionalTest -DgradleVersion=${{ matrix.gradle-version }} - name: Functional tests results if: always() uses: actions/upload-artifact@v2 diff --git a/.github/workflows/native-maven-plugin.yml b/.github/workflows/native-maven-plugin.yml index 80bcb70f3..9c7761ddf 100644 --- a/.github/workflows/native-maven-plugin.yml +++ b/.github/workflows/native-maven-plugin.yml @@ -30,10 +30,7 @@ jobs: echo "JAVA_HOME=$JAVA_HOME" >> $GITHUB_ENV echo "GRAALVM_HOME=$GRAALVM_HOME" >> $GITHUB_ENV - name: Check and test the plugin - run: | - pushd native-maven-plugin - ./gradlew check --no-daemon - popd + run: ./gradlew :native-maven-plugin:check --no-daemon - name: Tests results if: always() uses: actions/upload-artifact@v2 diff --git a/buildSrc/build.gradle.kts b/build-logic/aggregator/build.gradle.kts similarity index 100% rename from buildSrc/build.gradle.kts rename to build-logic/aggregator/build.gradle.kts diff --git a/buildSrc/settings.gradle.kts b/build-logic/aggregator/settings.gradle.kts similarity index 91% rename from buildSrc/settings.gradle.kts rename to build-logic/aggregator/settings.gradle.kts index 7c698df20..fa0b001d6 100644 --- a/buildSrc/settings.gradle.kts +++ b/build-logic/aggregator/settings.gradle.kts @@ -39,13 +39,12 @@ * SOFTWARE. */ +pluginManagement { + includeBuild("../settings-plugins") +} -enableFeaturePreview("VERSION_CATALOGS") - -dependencyResolutionManagement { - versionCatalogs { - create("libs") { - from(files("../gradle/libs.versions.toml")) - } - } +plugins { + id("org.graalvm.build.common") } + +rootProject.name = "aggregator" diff --git a/build-logic/aggregator/src/main/kotlin/org.graalvm.build.aggregator.gradle.kts b/build-logic/aggregator/src/main/kotlin/org.graalvm.build.aggregator.gradle.kts new file mode 100644 index 000000000..d6fc7c607 --- /dev/null +++ b/build-logic/aggregator/src/main/kotlin/org.graalvm.build.aggregator.gradle.kts @@ -0,0 +1,180 @@ +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.api.publish.plugins.PublishingPlugin +import org.gradle.api.tasks.Delete +import org.gradle.api.tasks.bundling.Zip +import org.gradle.kotlin.dsl.* + +/* + * 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. + */ + +plugins { + base +} + +tasks.named("clean") { + gradle.includedBuilds.forEach { + dependsOn(it.task(":clean")) + } +} + +tasks.register("test") { + gradle.includedBuilds.forEach { + dependsOn(it.task(":test")) + } +} + +tasks.register("inspections") { + gradle.includedBuilds.forEach { + dependsOn(it.task(":inspections")) + } +} + +tasks.named("check") { + gradle.includedBuilds.forEach { + dependsOn(it.task(":check")) + } +} + +listOf( + "publishTo" to "MavenLocal", + "publishAllPublicationsTo" to "CommonRepository", + "publishAllPublicationsTo" to "SnapshotsRepository", +).forEach { entry -> + val (taskPrefix, repo) = entry + tasks.register("$taskPrefix$repo") { + description = "Publishes all artifacts to the ${repo.decapitalize()} repository" + group = PublishingPlugin.PUBLISH_TASK_GROUP + gradle.includedBuilds.forEach { + if (it.name != "docs" && !it.projectDir.path.contains("build-logic")) { + dependsOn(it.task(":$taskPrefix$repo")) + } + } + doFirst { + if (gradle.startParameter.isParallelProjectExecutionEnabled) { + throw RuntimeException("Publishing should be done using --no-parallel") + } + } + } +} + +val commonRepo = layout.buildDirectory.dir("common-repo") +val snapshotsRepo = layout.buildDirectory.dir("snapshots") + +val pruneCommonRepo = tasks.register("pruneCommonRepository") { + delete(commonRepo) +} + +val catalogs = extensions.getByType() +val libs = catalogs.named("libs") + +val nativeBuildToolsVersion = libs.findVersion("nativeBuildTools").get().requiredVersion +val junitJupiterVersion = libs.findVersion("junitJupiter").get().requiredVersion +val junitPlatformVersion = libs.findVersion("junitPlatform").get().requiredVersion + +tasks.register("releaseZip") { + archiveVersion.set(nativeBuildToolsVersion) + dependsOn(pruneCommonRepo, "publishAllPublicationsToCommonRepository") + from(commonRepo) { + exclude("**/*.sha256") + exclude("**/*.sha512") + } +} + +val updateSamples by tasks.registering + +mapOf( + "updateSamplesDir" to "samples", + "updateMavenReprosDir" to "native-maven-plugin/reproducers" +).forEach { taskName, dir -> + val t = tasks.register(taskName) { + inputDirectory.set(layout.projectDirectory.dir(dir)) + versions.put("native.gradle.plugin.version", nativeBuildToolsVersion) + versions.put("native.maven.plugin.version", nativeBuildToolsVersion) + versions.put("junit.jupiter.version", junitJupiterVersion) + versions.put("junit.platform.version", junitPlatformVersion) + versions.put("junit.platform.native.version", nativeBuildToolsVersion) + } + updateSamples.configure { + dependsOn(t) + } +} + + +val cloneSnapshots = tasks.register("cloneSnapshotRepository") { + repositoryUri.set("git@github.com:graalvm/native-build-tools.git") +// repositoryUri.set(file(".").absolutePath) + repositoryDirectory.set(layout.buildDirectory.dir("snapshots")) + branch.set("snapshots") +} + +val prepareRepository = tasks.register("resetHead") { + dependsOn(cloneSnapshots) + repositoryDirectory.set(layout.buildDirectory.dir("snapshots")) + mode.set(org.eclipse.jgit.api.ResetCommand.ResetType.HARD) + ref.set("25ecdec020f57dbe980eeb052c71659ccd0d9bcc") +} + +val addSnapshots = tasks.register("addSnapshots") { + dependsOn(prepareRepository) + repositoryDirectory.set(layout.buildDirectory.dir("snapshots")) + pattern.set("org/") +} + +val commitSnapshots = tasks.register("commitSnapshots") { + dependsOn(addSnapshots) + repositoryDirectory.set(layout.buildDirectory.dir("snapshots")) + message.set("Publishing new snapshot") + amend.set(false) +} + +val pushSnapshots = tasks.register("pushSnapshots") { + dependsOn(commitSnapshots) + repositoryDirectory.set(layout.buildDirectory.dir("snapshots")) + force.set(true) +} + +tasks.named("publishAllPublicationsToSnapshotsRepository") { + dependsOn(prepareRepository) + finalizedBy(pushSnapshots) + onlyIf { + nativeBuildToolsVersion.endsWith("-SNAPSHOT") + } +} diff --git a/buildSrc/src/main/kotlin/org/graalvm/build/samples/SamplesUpdateTask.kt b/build-logic/aggregator/src/main/kotlin/org/graalvm/build/samples/SamplesUpdateTask.kt similarity index 100% rename from buildSrc/src/main/kotlin/org/graalvm/build/samples/SamplesUpdateTask.kt rename to build-logic/aggregator/src/main/kotlin/org/graalvm/build/samples/SamplesUpdateTask.kt diff --git a/buildSrc/src/main/kotlin/org/graalvm/build/tasks/AbstractGitTask.kt b/build-logic/aggregator/src/main/kotlin/org/graalvm/build/tasks/AbstractGitTask.kt similarity index 100% rename from buildSrc/src/main/kotlin/org/graalvm/build/tasks/AbstractGitTask.kt rename to build-logic/aggregator/src/main/kotlin/org/graalvm/build/tasks/AbstractGitTask.kt diff --git a/buildSrc/src/main/kotlin/org/graalvm/build/tasks/GitAdd.kt b/build-logic/aggregator/src/main/kotlin/org/graalvm/build/tasks/GitAdd.kt similarity index 100% rename from buildSrc/src/main/kotlin/org/graalvm/build/tasks/GitAdd.kt rename to build-logic/aggregator/src/main/kotlin/org/graalvm/build/tasks/GitAdd.kt diff --git a/buildSrc/src/main/kotlin/org/graalvm/build/tasks/GitClone.kt b/build-logic/aggregator/src/main/kotlin/org/graalvm/build/tasks/GitClone.kt similarity index 100% rename from buildSrc/src/main/kotlin/org/graalvm/build/tasks/GitClone.kt rename to build-logic/aggregator/src/main/kotlin/org/graalvm/build/tasks/GitClone.kt diff --git a/buildSrc/src/main/kotlin/org/graalvm/build/tasks/GitCommit.kt b/build-logic/aggregator/src/main/kotlin/org/graalvm/build/tasks/GitCommit.kt similarity index 100% rename from buildSrc/src/main/kotlin/org/graalvm/build/tasks/GitCommit.kt rename to build-logic/aggregator/src/main/kotlin/org/graalvm/build/tasks/GitCommit.kt diff --git a/buildSrc/src/main/kotlin/org/graalvm/build/tasks/GitPush.kt b/build-logic/aggregator/src/main/kotlin/org/graalvm/build/tasks/GitPush.kt similarity index 100% rename from buildSrc/src/main/kotlin/org/graalvm/build/tasks/GitPush.kt rename to build-logic/aggregator/src/main/kotlin/org/graalvm/build/tasks/GitPush.kt diff --git a/buildSrc/src/main/kotlin/org/graalvm/build/tasks/GitReset.kt b/build-logic/aggregator/src/main/kotlin/org/graalvm/build/tasks/GitReset.kt similarity index 100% rename from buildSrc/src/main/kotlin/org/graalvm/build/tasks/GitReset.kt rename to build-logic/aggregator/src/main/kotlin/org/graalvm/build/tasks/GitReset.kt diff --git a/build-logic/README.md b/build-logic/common-plugins/README.md similarity index 100% rename from build-logic/README.md rename to build-logic/common-plugins/README.md diff --git a/build-logic/build.gradle.kts b/build-logic/common-plugins/build.gradle.kts similarity index 100% rename from build-logic/build.gradle.kts rename to build-logic/common-plugins/build.gradle.kts diff --git a/common/utils/buildSrc/build.gradle.kts b/build-logic/common-plugins/settings.gradle.kts similarity index 98% rename from common/utils/buildSrc/build.gradle.kts rename to build-logic/common-plugins/settings.gradle.kts index fb014c67e..f1a9e711e 100644 --- a/common/utils/buildSrc/build.gradle.kts +++ b/build-logic/common-plugins/settings.gradle.kts @@ -39,6 +39,4 @@ * SOFTWARE. */ -plugins { - `java-gradle-plugin` -} +rootProject.name = "common-plugins" diff --git a/build-logic/src/main/kotlin/org.graalvm.build.java.gradle.kts b/build-logic/common-plugins/src/main/kotlin/org.graalvm.build.java.gradle.kts similarity index 88% rename from build-logic/src/main/kotlin/org.graalvm.build.java.gradle.kts rename to build-logic/common-plugins/src/main/kotlin/org.graalvm.build.java.gradle.kts index bbef2d9df..f7d4ae4d3 100644 --- a/build-logic/src/main/kotlin/org.graalvm.build.java.gradle.kts +++ b/build-logic/common-plugins/src/main/kotlin/org.graalvm.build.java.gradle.kts @@ -61,15 +61,16 @@ repositories { mavenCentral() } -val versionFromCatalog = extensions.getByType() - .named("libs") - .findVersion("nativeBuildTools") - group = "org.graalvm.buildtools" -if (versionFromCatalog.isPresent()) { - version = versionFromCatalog.get().requiredVersion -} else { - throw GradleException("Version catalog doesn't define project version 'nativeBuildTools'") + +extensions.findByType()?.also { catalogs -> + val versionFromCatalog = catalogs.named("libs") + .findVersion("nativeBuildTools") + if (versionFromCatalog.isPresent()) { + version = versionFromCatalog.get().requiredVersion + } else { + throw GradleException("Version catalog doesn't define project version 'nativeBuildTools'") + } } tasks.javadoc { diff --git a/build-logic/src/main/kotlin/org.graalvm.build.publishing.gradle.kts b/build-logic/common-plugins/src/main/kotlin/org.graalvm.build.publishing.gradle.kts similarity index 100% rename from build-logic/src/main/kotlin/org.graalvm.build.publishing.gradle.kts rename to build-logic/common-plugins/src/main/kotlin/org.graalvm.build.publishing.gradle.kts diff --git a/build-logic/src/main/kotlin/org/graalvm/build/MavenExtension.kt b/build-logic/common-plugins/src/main/kotlin/org/graalvm/build/MavenExtension.kt similarity index 100% rename from build-logic/src/main/kotlin/org/graalvm/build/MavenExtension.kt rename to build-logic/common-plugins/src/main/kotlin/org/graalvm/build/MavenExtension.kt diff --git a/build-logic/src/main/kotlin/utils.kt b/build-logic/common-plugins/src/main/kotlin/utils.kt similarity index 100% rename from build-logic/src/main/kotlin/utils.kt rename to build-logic/common-plugins/src/main/kotlin/utils.kt diff --git a/docs/buildSrc/build.gradle.kts b/build-logic/documentation-plugins/build.gradle.kts similarity index 100% rename from docs/buildSrc/build.gradle.kts rename to build-logic/documentation-plugins/build.gradle.kts diff --git a/build-logic/documentation-plugins/settings.gradle.kts b/build-logic/documentation-plugins/settings.gradle.kts new file mode 100644 index 000000000..28cc07a6a --- /dev/null +++ b/build-logic/documentation-plugins/settings.gradle.kts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +rootProject.name = "documentation-plugins" diff --git a/docs/buildSrc/src/main/kotlin/org.graalvm.build.documentation.gradle.kts b/build-logic/documentation-plugins/src/main/kotlin/org.graalvm.build.documentation.gradle.kts similarity index 100% rename from docs/buildSrc/src/main/kotlin/org.graalvm.build.documentation.gradle.kts rename to build-logic/documentation-plugins/src/main/kotlin/org.graalvm.build.documentation.gradle.kts diff --git a/native-gradle-plugin/buildSrc/build.gradle b/build-logic/gradle-functional-testing/build.gradle similarity index 100% rename from native-gradle-plugin/buildSrc/build.gradle rename to build-logic/gradle-functional-testing/build.gradle diff --git a/build-logic/gradle-functional-testing/settings.gradle b/build-logic/gradle-functional-testing/settings.gradle new file mode 100644 index 000000000..210a9caaf --- /dev/null +++ b/build-logic/gradle-functional-testing/settings.gradle @@ -0,0 +1 @@ +rootProject.name = "gradle-functional-testing" diff --git a/native-gradle-plugin/buildSrc/src/main/groovy/org.graalvm.build.functional-testing.gradle b/build-logic/gradle-functional-testing/src/main/groovy/org.graalvm.build.functional-testing.gradle similarity index 99% rename from native-gradle-plugin/buildSrc/src/main/groovy/org.graalvm.build.functional-testing.gradle rename to build-logic/gradle-functional-testing/src/main/groovy/org.graalvm.build.functional-testing.gradle index 54e4c8078..459302f56 100644 --- a/native-gradle-plugin/buildSrc/src/main/groovy/org.graalvm.build.functional-testing.gradle +++ b/build-logic/gradle-functional-testing/src/main/groovy/org.graalvm.build.functional-testing.gradle @@ -49,6 +49,7 @@ */ plugins { + id 'java-gradle-plugin' id 'groovy' } diff --git a/build-logic/settings-plugins/README.md b/build-logic/settings-plugins/README.md new file mode 100644 index 000000000..6f840b1f3 --- /dev/null +++ b/build-logic/settings-plugins/README.md @@ -0,0 +1,3 @@ +## Settings build logic + +This folder contains settings plugins used by the different Gradle builds in this repository. diff --git a/build-logic/settings-plugins/build.gradle.kts b/build-logic/settings-plugins/build.gradle.kts new file mode 100644 index 000000000..e1fc239a9 --- /dev/null +++ b/build-logic/settings-plugins/build.gradle.kts @@ -0,0 +1,49 @@ +/* + * 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. + */ + +plugins { + `kotlin-dsl` +} + +repositories { + mavenCentral() + gradlePluginPortal() +} diff --git a/build-logic/settings.gradle.kts b/build-logic/settings-plugins/settings.gradle.kts similarity index 98% rename from build-logic/settings.gradle.kts rename to build-logic/settings-plugins/settings.gradle.kts index 6ff2fa7b1..4522ec5a5 100644 --- a/build-logic/settings.gradle.kts +++ b/build-logic/settings-plugins/settings.gradle.kts @@ -39,4 +39,4 @@ * SOFTWARE. */ -rootProject.name = "shared-build-logic" +rootProject.name = "settings-plugins" diff --git a/build-logic/src/main/kotlin/org.graalvm.build.common.settings.gradle.kts b/build-logic/settings-plugins/src/main/kotlin/org.graalvm.build.common.settings.gradle.kts similarity index 98% rename from build-logic/src/main/kotlin/org.graalvm.build.common.settings.gradle.kts rename to build-logic/settings-plugins/src/main/kotlin/org.graalvm.build.common.settings.gradle.kts index 41f936f11..c95cca3b1 100644 --- a/build-logic/src/main/kotlin/org.graalvm.build.common.settings.gradle.kts +++ b/build-logic/settings-plugins/src/main/kotlin/org.graalvm.build.common.settings.gradle.kts @@ -39,8 +39,6 @@ * SOFTWARE. */ -enableFeaturePreview("VERSION_CATALOGS") - val catalogFile = file(".").let { var baseDir = it var cur = File(baseDir, "gradle/libs.versions.toml") diff --git a/build-logic/utils-plugins/build.gradle.kts b/build-logic/utils-plugins/build.gradle.kts new file mode 100644 index 000000000..9b5dc2dd0 --- /dev/null +++ b/build-logic/utils-plugins/build.gradle.kts @@ -0,0 +1,54 @@ +/* + * 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. + */ + +plugins { + java + `kotlin-dsl` +} + +repositories { + mavenCentral() + gradlePluginPortal() +} + +dependencies { + implementation(":common-plugins") +} diff --git a/build-logic/utils-plugins/settings.gradle.kts b/build-logic/utils-plugins/settings.gradle.kts new file mode 100644 index 000000000..3d2a504db --- /dev/null +++ b/build-logic/utils-plugins/settings.gradle.kts @@ -0,0 +1,52 @@ +/* + * 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. + */ + +rootProject.name = "utils-plugins" + +pluginManagement { + includeBuild("../settings-plugins") +} + +includeBuild("../common-plugins") + +plugins { + id("org.graalvm.build.common") +} diff --git a/common/utils/buildSrc/src/main/java/org/graalvm/build/GenerateVersionClass.java b/build-logic/utils-plugins/src/main/java/org/graalvm/build/GenerateVersionClass.java similarity index 100% rename from common/utils/buildSrc/src/main/java/org/graalvm/build/GenerateVersionClass.java rename to build-logic/utils-plugins/src/main/java/org/graalvm/build/GenerateVersionClass.java diff --git a/build-logic/utils-plugins/src/main/kotlin/org.graalvm.build.utils-module.gradle.kts b/build-logic/utils-plugins/src/main/kotlin/org.graalvm.build.utils-module.gradle.kts new file mode 100644 index 000000000..1eca1254c --- /dev/null +++ b/build-logic/utils-plugins/src/main/kotlin/org.graalvm.build.utils-module.gradle.kts @@ -0,0 +1,83 @@ +import org.gradle.api.plugins.quality.Checkstyle +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.api.tasks.testing.Test +import org.gradle.kotlin.dsl.* + +/* + * 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. + */ + +plugins { + checkstyle + id("org.graalvm.build.java") + id("org.graalvm.build.publishing") +} + +tasks.withType().configureEach { + useJUnitPlatform() +} + +extensions.findByType()?.also { catalogs -> + val libs = catalogs.named("libs") + val generateVersionInfo = tasks.register("generateVersionInfo", org.graalvm.build.GenerateVersionClass::class.java) { + versions.put("junitPlatformNative", libs.findVersion("nativeBuildTools").get().requiredVersion) + outputDirectory.set(layout.buildDirectory.dir("generated/sources/versions")) + } + + sourceSets { + main { + java { + srcDir(generateVersionInfo) + } + } + } +} + +publishing { + publications { + create("maven") { + from(components["java"]) + } + } +} + +tasks.withType().configureEach { + setConfigFile(layout.projectDirectory.dir("../../config/checkstyle.xml").asFile) +} diff --git a/common/utils/buildSrc/src/main/resources/org/graalvm/build/header.txt b/build-logic/utils-plugins/src/main/resources/org/graalvm/build/header.txt similarity index 100% rename from common/utils/buildSrc/src/main/resources/org/graalvm/build/header.txt rename to build-logic/utils-plugins/src/main/resources/org/graalvm/build/header.txt diff --git a/build.gradle.kts b/build.gradle.kts index fa5b53ee5..eb56a0a89 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -40,128 +40,5 @@ */ plugins { - base -} - -tasks.named("clean") { - gradle.includedBuilds.forEach { - dependsOn(it.task(":clean")) - } -} - -tasks.register("test") { - gradle.includedBuilds.forEach { - dependsOn(it.task(":test")) - } -} - -tasks.register("inspections") { - gradle.includedBuilds.forEach { - dependsOn(it.task(":inspections")) - } -} - -tasks.named("check") { - gradle.includedBuilds.forEach { - dependsOn(it.task(":check")) - } -} - -listOf( - "publishTo" to "MavenLocal", - "publishAllPublicationsTo" to "CommonRepository", - "publishAllPublicationsTo" to "SnapshotsRepository", -).forEach { entry -> - val (taskPrefix, repo) = entry - tasks.register("$taskPrefix$repo") { - description = "Publishes all artifacts to the ${repo.decapitalize()} repository" - group = PublishingPlugin.PUBLISH_TASK_GROUP - gradle.includedBuilds.forEach { - if (it.name != "docs") { - dependsOn(it.task(":$taskPrefix$repo")) - } - } - doFirst { - if (gradle.startParameter.isParallelProjectExecutionEnabled) { - throw RuntimeException("Publishing should be done using --no-parallel") - } - } - } -} - -val commonRepo = layout.buildDirectory.dir("common-repo") -val snapshotsRepo = layout.buildDirectory.dir("snapshots") - -val pruneCommonRepo = tasks.register("pruneCommonRepository") { - delete(commonRepo) -} - -tasks.register("releaseZip") { - archiveVersion.set(libs.versions.nativeBuildTools) - dependsOn(pruneCommonRepo, "publishAllPublicationsToCommonRepository") - from(commonRepo) { - exclude("**/*.sha256") - exclude("**/*.sha512") - } -} - -val updateSamples by tasks.registering - -mapOf( - "updateSamplesDir" to "samples", - "updateMavenReprosDir" to "native-maven-plugin/reproducers" -).forEach { taskName, dir -> - val t = tasks.register(taskName) { - inputDirectory.set(layout.projectDirectory.dir(dir)) - versions.put("native.gradle.plugin.version", libs.versions.nativeBuildTools.get()) - versions.put("native.maven.plugin.version", libs.versions.nativeBuildTools.get()) - versions.put("junit.jupiter.version", libs.versions.junitJupiter.get()) - versions.put("junit.platform.version", libs.versions.junitPlatform.get()) - versions.put("junit.platform.native.version", libs.versions.nativeBuildTools.get()) - } - updateSamples.configure { - dependsOn(t) - } -} - - -val cloneSnapshots = tasks.register("cloneSnapshotRepository") { - repositoryUri.set("git@github.com:graalvm/native-build-tools.git") -// repositoryUri.set(file(".").absolutePath) - repositoryDirectory.set(layout.buildDirectory.dir("snapshots")) - branch.set("snapshots") -} - -val prepareRepository = tasks.register("resetHead") { - dependsOn(cloneSnapshots) - repositoryDirectory.set(layout.buildDirectory.dir("snapshots")) - mode.set(org.eclipse.jgit.api.ResetCommand.ResetType.HARD) - ref.set("25ecdec020f57dbe980eeb052c71659ccd0d9bcc") -} - -val addSnapshots = tasks.register("addSnapshots") { - dependsOn(prepareRepository) - repositoryDirectory.set(layout.buildDirectory.dir("snapshots")) - pattern.set("org/") -} - -val commitSnapshots = tasks.register("commitSnapshots") { - dependsOn(addSnapshots) - repositoryDirectory.set(layout.buildDirectory.dir("snapshots")) - message.set("Publishing new snapshot") - amend.set(false) -} - -val pushSnapshots = tasks.register("pushSnapshots") { - dependsOn(commitSnapshots) - repositoryDirectory.set(layout.buildDirectory.dir("snapshots")) - force.set(true) -} - -tasks.named("publishAllPublicationsToSnapshotsRepository") { - dependsOn(prepareRepository) - finalizedBy(pushSnapshots) - onlyIf { - libs.versions.nativeBuildTools.get().endsWith("-SNAPSHOT") - } + id("org.graalvm.build.aggregator") } diff --git a/common/junit-platform-native/settings.gradle b/common/junit-platform-native/settings.gradle index b035f2ddd..2282a95b7 100644 --- a/common/junit-platform-native/settings.gradle +++ b/common/junit-platform-native/settings.gradle @@ -40,7 +40,8 @@ */ pluginManagement { - includeBuild("../../build-logic") + includeBuild("../../build-logic/settings-plugins") + includeBuild("../../build-logic/common-plugins") } plugins { diff --git a/common/jvm-reachability-metadata/LICENSE b/common/jvm-reachability-metadata/LICENSE new file mode 100644 index 000000000..33bafe109 --- /dev/null +++ b/common/jvm-reachability-metadata/LICENSE @@ -0,0 +1,38 @@ +Copyright (c) 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. \ No newline at end of file diff --git a/common/jvm-reachability-metadata/build.gradle.kts b/common/jvm-reachability-metadata/build.gradle.kts new file mode 100644 index 000000000..432b4210c --- /dev/null +++ b/common/jvm-reachability-metadata/build.gradle.kts @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020, 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 { + checkstyle + id("org.graalvm.build.java") + id("org.graalvm.build.publishing") +} + +maven { + name.set("GraalVM JVM Reachability Metadata support") + description.set("A library to help dealing with the GraaVM JVM Reachability Metadata repository") +} + +dependencies { + implementation(libs.jackson.databind) + testImplementation(platform(libs.test.junit.bom)) + testImplementation(libs.test.junit.jupiter.core) +} + +tasks.withType().configureEach { + useJUnitPlatform() +} + +publishing { + publications { + create("maven") { + from(components["java"]) + } + } +} + +tasks.withType().configureEach { + setConfigFile(layout.projectDirectory.dir("../../config/checkstyle.xml").asFile) +} diff --git a/common/jvm-reachability-metadata/gradle/native-image-testing.gradle b/common/jvm-reachability-metadata/gradle/native-image-testing.gradle new file mode 100644 index 000000000..b7de78a52 --- /dev/null +++ b/common/jvm-reachability-metadata/gradle/native-image-testing.gradle @@ -0,0 +1,147 @@ +/* + * 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. + */ + +import org.gradle.util.GFileUtils + +def agentOutput = layout.buildDirectory.dir("agent") + +ext { + testIdsDir = layout.buildDirectory.dir("test_ids") +} + +tasks.register("testConsoleLauncher", JavaExec) { + outputs.dir(agentOutput) + classpath = test.classpath + main = "org.junit.platform.console.ConsoleLauncher" + args = ["--scan-class-path"] + doFirst { + def agentOutputDir = agentOutput.get().asFile + if (agentOutputDir.exists()) { + GFileUtils.deleteDirectory(agentOutputDir) + } + if (project.hasProperty("agent")) { + mkdir "${agentOutputDir}" + new File("${agentOutputDir}", "agent-filter.json").text = """ + { + "rules":[ + { + "excludeClasses":"org.gradle.**" + }, + { + "excludeClasses":"java.**" + } + ] + } + """ + jvmArgs = [ + "-agentlib:native-image-agent=access-filter-file=${agentOutputDir}/agent-filter.json,experimental-class-loader-support,config-output-dir=${agentOutputDir}/agentOutput", + "-Dorg.graalvm.nativeimage.imagecode=agent" + ] + } + } +} + +abstract class NativeTestArgumentProvider implements CommandLineArgumentProvider { + @InputFiles + abstract ConfigurableFileCollection getClasspath() + + @InputDirectory + abstract DirectoryProperty getTestIdsDir() + + @InputDirectory + @Optional + abstract DirectoryProperty getAgentOutputDir() + + @Input + abstract Property getDiscovery() + + @Override + Iterable asArguments() { + def args = [ + "-cp", classpath.asPath, + "--no-fallback", + "--features=org.graalvm.junit.platform.JUnitPlatformFeature", + "-H:Name=native-image-tests", + "-H:Class=org.graalvm.junit.platform.NativeImageJUnitLauncher", + "-Djunit.platform.listeners.uid.tracking.output.dir=${testIdsDir.get().asFile.absolutePath}" + ] + if (agentOutputDir.isPresent()) { + def outputDir = agentOutputDir.get().asFile + if (!outputDir.exists()) { + throw new GradleException("Agent output missing when -Pagent is set.\n" + + "You need to run `gradle -Pagent test` first.") + } + + args << "-H:ConfigurationFileDirectories=${outputDir.absolutePath}/agentOutput" + args << "-H:+AllowIncompleteClasspath" + } + + if (discovery.get()) { + args << "-DtestDiscovery" + } + args.collect { it.toString() } + } +} + +tasks.named("test") { + doFirst { + agentOutput.get().asFile.mkdirs() + } +} + +tasks.register("nativeTestCompile", Exec) { + dependsOn(test) + inputs.files(test.classpath) + workingDir "${buildDir}" + executable = System.getenv("GRAALVM_HOME") + "/bin/native-image" + def argsProvider = objects.newInstance(NativeTestArgumentProvider) + argsProvider.classpath.from(test.classpath) + argsProvider.testIdsDir.set(testIdsDir) + argsProvider.agentOutputDir.set(agentOutput) + argsProvider.discovery.set(providers.systemProperty("testDiscovery").forUseAtConfigurationTime().map(v -> Boolean.valueOf(v)).orElse(false)) + argumentProviders.add(argsProvider) +} + +tasks.register("nativeTest", Exec) { + dependsOn nativeTestCompile + workingDir = "${buildDir}" + executable = "${buildDir}/native-image-tests" +} diff --git a/common/jvm-reachability-metadata/gradle/wrapper/gradle-wrapper.jar b/common/jvm-reachability-metadata/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..e708b1c02 Binary files /dev/null and b/common/jvm-reachability-metadata/gradle/wrapper/gradle-wrapper.jar differ diff --git a/common/jvm-reachability-metadata/gradle/wrapper/gradle-wrapper.properties b/common/jvm-reachability-metadata/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..41dfb8790 --- /dev/null +++ b/common/jvm-reachability-metadata/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/common/jvm-reachability-metadata/gradlew b/common/jvm-reachability-metadata/gradlew new file mode 100755 index 000000000..4f906e0c8 --- /dev/null +++ b/common/jvm-reachability-metadata/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/common/jvm-reachability-metadata/gradlew.bat b/common/jvm-reachability-metadata/gradlew.bat new file mode 100644 index 000000000..107acd32c --- /dev/null +++ b/common/jvm-reachability-metadata/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/common/jvm-reachability-metadata/settings.gradle.kts b/common/jvm-reachability-metadata/settings.gradle.kts new file mode 100644 index 000000000..39c0f4fe5 --- /dev/null +++ b/common/jvm-reachability-metadata/settings.gradle.kts @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020, 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. + */ + +pluginManagement { + includeBuild("../../build-logic/settings-plugins") + includeBuild("../../build-logic/common-plugins") +} + +plugins { + id("org.graalvm.build.common") +} + +rootProject.name = "jvm-reachability-metadata" diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/JvmReachabilityMetadataRepository.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/JvmReachabilityMetadataRepository.java new file mode 100644 index 000000000..6d10e91ea --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/JvmReachabilityMetadataRepository.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2020, 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.reachability; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.Set; +import java.util.function.Consumer; + +/** + * Interface for accessing a reachability metadata repository. + * The goal of this repository is to answer questions like: + * "give me the configuration files for this artifact", where + * an artifact is represented by its GAV coordinates. + * + * The repository query may be configured for multiple artifacts + * and provide overrides for cases where configuration files + * are missing. + */ +public interface JvmReachabilityMetadataRepository { + /** + * Performs a generic query on the repository, returning a list of + * configuration directories. The query may be parameterized with + * a number of artifacts, and can be used to refine behavior, for + * example if a configuration directory isn't available for a + * particular artifact version. + * @param queryBuilder the query builder + * @return the set of configuration directories matching the query + */ + Set findConfigurationDirectoriesFor(Consumer queryBuilder); + + /** + * Returns a list of configuration directories for the specified artifact. + * There may be more than one configuration directory for a given artifact, + * but the list may also be empty if the repository doesn't contain any. + * Never null. + * @param gavCoordinates the artifact GAV coordinates (group:artifact:version) + * @return a list of configuration directories + */ + default Set findConfigurationDirectoriesFor(String gavCoordinates) { + return findConfigurationDirectoriesFor(q -> q.forArtifacts(gavCoordinates)); + } + + /** + * Returns the set of configuration directories for all the modules supplied + * as an argument. + * @param modules the list of modules + * @return the set of configuration directories + */ + default Set findConfigurationDirectoriesFor(Collection modules) { + return findConfigurationDirectoriesFor(q -> q.forArtifacts(modules)); + } +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/Query.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/Query.java new file mode 100644 index 000000000..17232d684 --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/Query.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020, 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.reachability; + +import java.util.Collection; +import java.util.function.Consumer; + +public interface Query { + void forArtifacts(String... gavCoordinates); + + default void forArtifacts(Collection gavCoordinates) { + forArtifacts(gavCoordinates.toArray(new String[0])); + } + + void forArtifact(Consumer config); + void useLatestConfigWhenVersionIsUntested(); + + interface ArtifactQuery { + void gav(String gavCoordinates); + void useLatestConfigWhenVersionIsUntested(); + void doNotUseLatestConfigWhenVersionIsUntested(); + void forceConfigVersion(String version); + } +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/DefaultArtifactQuery.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/DefaultArtifactQuery.java new file mode 100644 index 000000000..2af118e70 --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/DefaultArtifactQuery.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2020, 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.reachability.internal; + +import org.graalvm.reachability.Query; + +import java.util.Optional; + +public class DefaultArtifactQuery implements Query.ArtifactQuery { + + private String groupId; + private String artifactId; + private String version; + + private boolean useLatestVersion = false; + private String forcedConfig = null; + + @Override + public void gav(String gavCoordinates) { + String[] gav = gavCoordinates.split(":"); + if (gav.length != 3) { + throw new IllegalArgumentException("Invalid GAV coordinates: " + gavCoordinates + " (expected format: groupId:artifactId:version)"); + } + groupId = gav[0]; + artifactId = gav[1]; + version = gav[2]; + } + + @Override + public void useLatestConfigWhenVersionIsUntested() { + useLatestVersion = true; + forcedConfig = null; + } + + @Override + public void doNotUseLatestConfigWhenVersionIsUntested() { + useLatestVersion = false; + } + + @Override + public void forceConfigVersion(String version) { + useLatestVersion = false; + forcedConfig = version; + } + + public String getGroupId() { + return groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public String getVersion() { + return version; + } + + public boolean isUseLatestVersion() { + return useLatestVersion; + } + + public Optional getForcedConfig() { + return Optional.ofNullable(forcedConfig); + } +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/DefaultQuery.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/DefaultQuery.java new file mode 100644 index 000000000..cb4fad4fb --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/DefaultQuery.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2020, 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.reachability.internal; + +import org.graalvm.reachability.Query; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public class DefaultQuery implements Query { + private boolean useLatest = false; + private final List> artifactsQueries = new ArrayList<>(); + + @Override + public void forArtifacts(String... gavCoordinates) { + for (String coordinates : gavCoordinates) { + forArtifact(q -> q.gav(coordinates)); + } + } + + @Override + public void forArtifact(Consumer config) { + artifactsQueries.add(config); + } + + @Override + public void useLatestConfigWhenVersionIsUntested() { + useLatest = true; + } + + List getArtifacts() { + return artifactsQueries.stream() + .map(spec -> { + DefaultArtifactQuery query = new DefaultArtifactQuery(); + if (useLatest) { + query.useLatestConfigWhenVersionIsUntested(); + } + spec.accept(query); + return query; + }) + .collect(Collectors.toList()); + } +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/FileSystemRepository.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/FileSystemRepository.java new file mode 100644 index 000000000..e848e70fd --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/FileSystemRepository.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2020, 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.reachability.internal; + +import org.graalvm.reachability.JvmReachabilityMetadataRepository; +import org.graalvm.reachability.Query; +import org.graalvm.reachability.internal.index.artifacts.SingleModuleJsonVersionToConfigDirectoryIndex; +import org.graalvm.reachability.internal.index.artifacts.VersionToConfigDirectoryIndex; +import org.graalvm.reachability.internal.index.modules.FileSystemModuleToConfigDirectoryIndex; + +import java.nio.file.Path; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +public class FileSystemRepository implements JvmReachabilityMetadataRepository { + private final FileSystemModuleToConfigDirectoryIndex moduleIndex; + private final Logger logger; + private final Map artifactIndexes; + private final Path rootDirectory; + + public FileSystemRepository(Path rootDirectory) { + this(rootDirectory, new Logger() {}); + } + + public FileSystemRepository(Path rootDirectory, Logger logger) { + this.moduleIndex = new FileSystemModuleToConfigDirectoryIndex(rootDirectory); + this.logger = logger; + this.artifactIndexes = new ConcurrentHashMap<>(); + this.rootDirectory = rootDirectory; + } + + @Override + public Set findConfigurationDirectoriesFor(Consumer queryBuilder) { + DefaultQuery query = new DefaultQuery(); + queryBuilder.accept(query); + return query.getArtifacts() + .stream() + .flatMap(artifactQuery -> { + String groupId = artifactQuery.getGroupId(); + String artifactId = artifactQuery.getArtifactId(); + String version = artifactQuery.getVersion(); + return moduleIndex.findConfigurationDirectories(groupId, artifactId) + .stream() + .map(dir -> { + VersionToConfigDirectoryIndex index = artifactIndexes.computeIfAbsent(dir, SingleModuleJsonVersionToConfigDirectoryIndex::new); + if (artifactQuery.getForcedConfig().isPresent()) { + String configVersion = artifactQuery.getForcedConfig().get(); + logger.log(groupId, artifactId, version, "Configuration is forced to version " + configVersion); + return index.findForcedConfiguration(configVersion); + } + Optional configurationDirectory = index.findConfigurationDirectory(groupId, artifactId, version); + if (!configurationDirectory.isPresent() && artifactQuery.isUseLatestVersion()) { + logger.log(groupId, artifactId, version, "Configuration directory not found. Trying latest version."); + configurationDirectory = index.findLatestConfigurationFor(groupId, artifactId); + if (!configurationDirectory.isPresent()) { + logger.log(groupId, artifactId, version, "Latest version not found!"); + } + } + Optional finalConfigurationDirectory = configurationDirectory; + logger.log(groupId, artifactId, version, () -> { + if (finalConfigurationDirectory.isPresent()) { + Path path = finalConfigurationDirectory.get(); + return "Configuration directory is " + rootDirectory.relativize(path); + } + return "missing."; + }); + return configurationDirectory; + }) + .filter(Optional::isPresent) + .map(Optional::get); + }) + .collect(Collectors.toSet()); + } + + /** + * Allows getting insights about how configuration is picked. + */ + public interface Logger { + default void log(String groupId, String artifactId, String version, String message) { + log(groupId, artifactId, version, () -> message); + } + + default void log(String groupId, String artifactId, String version, Supplier message) { + + } + } +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/UncheckedIOException.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/UncheckedIOException.java new file mode 100644 index 000000000..021bccc0a --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/UncheckedIOException.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020, 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.reachability.internal; + +import java.io.IOException; + +public class UncheckedIOException extends RuntimeException { + public UncheckedIOException(IOException e) { + super(e); + } +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/artifacts/Artifact.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/artifacts/Artifact.java new file mode 100644 index 000000000..3641a67a7 --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/artifacts/Artifact.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2020, 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.reachability.internal.index.artifacts; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Set; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Artifact { + private final String module; + private final Set versions; + private final String directory; + private final boolean latest; + + @JsonCreator + public Artifact(@JsonProperty("module") String module, + @JsonProperty("tested-versions") Set versions, + @JsonProperty("metadata-version") String directory, + @JsonProperty(value = "latest", defaultValue = "false") boolean latest) { + this.module = module; + this.versions = versions; + this.directory = directory; + this.latest = latest; + } + + public String getModule() { + return module; + } + + public Set getVersions() { + return versions; + } + + public String getDirectory() { + return directory; + } + + public boolean isLatest() { + return latest; + } +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/artifacts/SingleModuleJsonVersionToConfigDirectoryIndex.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/artifacts/SingleModuleJsonVersionToConfigDirectoryIndex.java new file mode 100644 index 000000000..25709d50c --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/artifacts/SingleModuleJsonVersionToConfigDirectoryIndex.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2020, 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.reachability.internal.index.artifacts; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.TypeFactory; +import org.graalvm.reachability.internal.UncheckedIOException; + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public class SingleModuleJsonVersionToConfigDirectoryIndex implements VersionToConfigDirectoryIndex { + private final Path moduleRoot; + private final Map> index; + + public SingleModuleJsonVersionToConfigDirectoryIndex(Path moduleRoot) { + this.moduleRoot = moduleRoot; + this.index = parseIndexFile(moduleRoot); + } + + private Map> parseIndexFile(Path rootPath) { + Path indexFile = rootPath.resolve("index.json"); + ObjectMapper objectMapper = new ObjectMapper(); + TypeFactory typeFactory = objectMapper.getTypeFactory(); + try (BufferedReader reader = Files.newBufferedReader(indexFile)) { + List entries = objectMapper.readValue( + reader, + typeFactory.constructCollectionType(List.class, Artifact.class) + ); + return entries.stream() + .collect(Collectors.groupingBy(Artifact::getModule)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + } + + @Override + public Optional findForcedConfiguration(String version) { + Path configDir = moduleRoot.resolve(version); + return Files.isDirectory(configDir) ? Optional.of(configDir) : Optional.empty(); + } + + /** + * Returns the configuration directory for the requested artifact. + * + * @param groupId the group ID of the artifact + * @param artifactId the artifact ID of the artifact + * @param version the version of the artifact + * @return a configuration directory, or empty if no configuration directory is available + */ + @Override + public Optional findConfigurationDirectory(String groupId, String artifactId, String version) { + return findConfigurationFor(groupId, artifactId, artifact -> artifact.getVersions().contains(version)); + } + + /** + * Returns the latest configuration directory for the requested artifact. + * + * @param groupId the group ID of the artifact + * @param artifactId the artifact ID of the artifact + * @return a configuration directory, or empty if no configuration directory is available + */ + @Override + public Optional findLatestConfigurationFor(String groupId, String artifactId) { + return findConfigurationFor(groupId, artifactId, Artifact::isLatest); + } + + private Optional findConfigurationFor(String groupId, String artifactId, Predicate predicate) { + String module = groupId + ":" + artifactId; + List artifacts = index.get(module); + if (artifacts == null) { + return Optional.empty(); + } + return artifacts.stream() + .filter(artifact -> artifact.getModule().equals(module)) + .filter(predicate) + .findFirst() + .map(artifact -> moduleRoot.resolve(artifact.getDirectory())); + } +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/artifacts/VersionToConfigDirectoryIndex.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/artifacts/VersionToConfigDirectoryIndex.java new file mode 100644 index 000000000..3a712265d --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/artifacts/VersionToConfigDirectoryIndex.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020, 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.reachability.internal.index.artifacts; + +import java.nio.file.Path; +import java.util.Optional; + +public interface VersionToConfigDirectoryIndex { + + /** + * Returns the specified configuration directory version, ignoring + * any existing configuration. + * @param version the requested version + * @return the configuration directory + */ + Optional findForcedConfiguration(String version); + + /** + * Returns the configuration directory for the requested artifact. + * @param groupId the group ID of the artifact + * @param artifactId the artifact ID of the artifact + * @param version the version of the artifact + * @return a configuration directory, or empty if no configuration directory is available + */ + Optional findConfigurationDirectory(String groupId, String artifactId, String version); + + /** + * Returns the latest configuration directory for the requested artifact. + * @param groupId the group ID of the artifact + * @param artifactId the artifact ID of the artifact + * @return a configuration directory, or empty if no configuration directory is available + */ + Optional findLatestConfigurationFor(String groupId, String artifactId); +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/FileSystemModuleToConfigDirectoryIndex.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/FileSystemModuleToConfigDirectoryIndex.java new file mode 100644 index 000000000..78d6a8604 --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/FileSystemModuleToConfigDirectoryIndex.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020, 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.reachability.internal.index.modules; + +import java.nio.file.Path; +import java.util.Set; + +/** + * This is the default index from module to configuration directory, which first + * looks into the JSON index file, and if a module isn't found there, would try + * to find it in the standard FS location. + */ +public class FileSystemModuleToConfigDirectoryIndex implements ModuleToConfigDirectoryIndex { + private final JsonModuleToConfigDirectoryIndex jsonIndex; + private final StandardLocationModuleToConfigDirectoryIndex fsIndex; + + public FileSystemModuleToConfigDirectoryIndex(Path rootPath) { + this.jsonIndex = new JsonModuleToConfigDirectoryIndex(rootPath); + this.fsIndex = new StandardLocationModuleToConfigDirectoryIndex(rootPath); + } + + /** + * Returns the directory containing the candidate configurations for the given module. + * + * @param groupId the group of the module + * @param artifactId the artifact of the module + * @return the configuration directory + */ + @Override + public Set findConfigurationDirectories(String groupId, String artifactId) { + Set fromIndex = jsonIndex.findConfigurationDirectories(groupId, artifactId); + if (!fromIndex.isEmpty()) { + return fromIndex; + } + return fsIndex.findConfigurationDirectories(groupId, artifactId); + } +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/JsonModuleToConfigDirectoryIndex.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/JsonModuleToConfigDirectoryIndex.java new file mode 100644 index 000000000..c072de033 --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/JsonModuleToConfigDirectoryIndex.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2020, 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.reachability.internal.index.modules; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.TypeFactory; +import org.graalvm.reachability.internal.UncheckedIOException; + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class JsonModuleToConfigDirectoryIndex implements ModuleToConfigDirectoryIndex { + private final Path rootPath; + private final Map> index; + + public JsonModuleToConfigDirectoryIndex(Path rootPath) { + this.rootPath = rootPath; + this.index = parseIndexFile(rootPath); + } + + private Map> parseIndexFile(Path rootPath) { + Path indexFile = rootPath.resolve("index.json"); + ObjectMapper objectMapper = new ObjectMapper(); + TypeFactory typeFactory = objectMapper.getTypeFactory(); + try (BufferedReader reader = Files.newBufferedReader(indexFile)) { + List entries = objectMapper.readValue( + reader, + typeFactory.constructCollectionType(List.class, ModuleEntry.class) + ); + Map> moduleToEntries = entries.stream() + .collect(Collectors.groupingBy(ModuleEntry::getModule)); + Map> index = new HashMap<>(moduleToEntries.size()); + for (Map.Entry> entry : moduleToEntries.entrySet()) { + String key = entry.getKey(); + Set dirs = entry.getValue() + .stream() + .flatMap(module -> Stream.concat( + Stream.of(module.getModuleDirectory()), + module.getRequires().stream().flatMap(e -> { + List moduleEntries = moduleToEntries.get(e); + if (moduleEntries == null) { + throw new IllegalStateException("Module " + module.getModule() + " requires module " + e + " which is not found in index"); + } + return moduleEntries.stream().map(ModuleEntry::getModuleDirectory); + }) + )) + .filter(Objects::nonNull) + .map(rootPath::resolve) + .collect(Collectors.toSet()); + index.put(key, dirs); + } + return index; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + } + + /** + * Returns the directory containing the candidate configurations for the given module. + * + * @param groupId the group of the module + * @param artifactId the artifact of the module + * @return the configuration directory + */ + @Override + public Set findConfigurationDirectories(String groupId, String artifactId) { + String key = groupId + ":" + artifactId; + if (!index.containsKey(key)) { + return Collections.emptySet(); + } + return index.get(key); + } +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/ModuleEntry.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/ModuleEntry.java new file mode 100644 index 000000000..7093eae97 --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/ModuleEntry.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020, 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.reachability.internal.index.modules; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Collections; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ModuleEntry { + private final String module; + private final String moduleDirectory; + private final List requires; + + @JsonCreator + public ModuleEntry(@JsonProperty("module") String module, + @JsonProperty("directory") String moduleDirectory, + @JsonProperty("requires") List requires) { + this.module = module; + this.moduleDirectory = moduleDirectory; + this.requires = requires == null ? Collections.emptyList() : requires; + } + + public String getModule() { + return module; + } + + public String getModuleDirectory() { + return moduleDirectory; + } + + public List getRequires() { + return requires; + } +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/ModuleToConfigDirectoryIndex.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/ModuleToConfigDirectoryIndex.java new file mode 100644 index 000000000..ab4dce7b4 --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/ModuleToConfigDirectoryIndex.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020, 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.reachability.internal.index.modules; + +import java.nio.file.Path; +import java.util.Set; + +public interface ModuleToConfigDirectoryIndex { + /** + * Returns the directories containing the candidate configurations for the given module. + * @param groupId the group of the module + * @param artifactId the artifact of the module + * @return the configuration directory + */ + Set findConfigurationDirectories(String groupId, String artifactId); +} diff --git a/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/StandardLocationModuleToConfigDirectoryIndex.java b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/StandardLocationModuleToConfigDirectoryIndex.java new file mode 100644 index 000000000..d8d8a82a0 --- /dev/null +++ b/common/jvm-reachability-metadata/src/main/java/org/graalvm/reachability/internal/index/modules/StandardLocationModuleToConfigDirectoryIndex.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020, 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.reachability.internal.index.modules; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Set; + +public class StandardLocationModuleToConfigDirectoryIndex implements ModuleToConfigDirectoryIndex { + private final Path rootPath; + + public StandardLocationModuleToConfigDirectoryIndex(Path rootPath) { + this.rootPath = rootPath; + } + + @Override + public Set findConfigurationDirectories(String groupId, String artifactId) { + Path candidate = rootPath.resolve(groupId.replace('.', '/') + "/" + artifactId); + if (Files.isDirectory(candidate)) { + return Collections.singleton(candidate); + } + return Collections.emptySet(); + } +} diff --git a/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/FileSystemRepositoryTest.java b/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/FileSystemRepositoryTest.java new file mode 100644 index 000000000..60ac40d20 --- /dev/null +++ b/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/FileSystemRepositoryTest.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2020, 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.reachability.internal; + +import org.graalvm.reachability.Query; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.util.Set; +import java.util.function.Consumer; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class FileSystemRepositoryTest { + private FileSystemRepository repository; + private Path repoPath; + private Result result; + + @Test + void testRepo1() { + // when: + withRepo("repo1"); + lookup("org:foo:1.0"); + + // then: + result.hasSinglePath("org/foo/1"); + + // when: + lookup("org:foo:1.1"); + + // then: + result.hasSinglePath("org/foo/2"); + + // when: + lookup("org:foo:1.2"); + + // then: + result.isEmpty(); + } + + @Test + void testRepo2() { + // when: + withRepo("repo2"); + lookup("org:bar:2.1"); + + // then: + result.hasSinglePath("org/foo/2"); + } + + @Test + void canDefaultToLatestConfigDir() { + // when: + withRepo("repo1"); + lookup(q -> { + q.useLatestConfigWhenVersionIsUntested(); + q.forArtifacts("org:foo:1.2"); + }); + + // then: + result.hasSinglePath("org/foo/2"); + + //when: "order of spec shouldn't matter" + lookup(q -> { + q.forArtifacts("org:foo:1.2"); + q.useLatestConfigWhenVersionIsUntested(); + }); + + // then: + result.hasSinglePath("org/foo/2"); + } + + @Test + void canForceToParticularConfigVersion() { + // when: + withRepo("repo1"); + + lookup(q -> q.forArtifact(artifact -> { + artifact.gav("org:foo:1.2"); + artifact.forceConfigVersion("1"); + })); + + // then: + result.hasSinglePath("org/foo/1"); + } + + @Test + void forcingToNonExistentDirectoryReturnsEmpty() { + // when: + withRepo("repo1"); + + lookup(q -> q.forArtifact(artifact -> { + artifact.gav("org:foo:1.2"); + artifact.forceConfigVersion("123"); + })); + + // then: + result.isEmpty(); + } + + @Test + void canUseLatestConfigDir() { + // when: + withRepo("repo1"); + lookup(q -> q.forArtifact(artifact -> { + artifact.gav("org:foo:1.2"); + artifact.useLatestConfigWhenVersionIsUntested(); + })); + + // then: + result.hasSinglePath("org/foo/2"); + + // when: + lookup(q -> { + q.useLatestConfigWhenVersionIsUntested(); + q.forArtifact(artifact -> { + artifact.gav("org:foo:1.2"); + // Can override default global + artifact.doNotUseLatestConfigWhenVersionIsUntested(); + }); + }); + + // then: + result.isEmpty(); + } + + private void lookup(Consumer builder) { + result = new Result(repository.findConfigurationDirectoriesFor(builder), repoPath); + } + + private void lookup(String gav) { + result = new Result(repository.findConfigurationDirectoriesFor(gav), repoPath); + } + + private void withRepo(String id) { + try { + repoPath = new File(FileSystemRepositoryTest.class.getResource("/repos/" + id).toURI()).toPath(); + repository = new FileSystemRepository(repoPath); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + private static final class Result { + private final Path repoPath; + private final Set configDirs; + + private Result(Set configDirs, Path repoPath) { + this.configDirs = configDirs; + this.repoPath = repoPath; + } + + public void isEmpty() { + assertEquals(0, configDirs.size()); + } + + public void hasSinglePath(String path) { + assertEquals(1, configDirs.size()); + assertEquals(repoPath.resolve(path), configDirs.iterator().next()); + } + } +} diff --git a/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/index/artifacts/SingleModuleJsonVersionToConfigDirectoryIndexTest.java b/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/index/artifacts/SingleModuleJsonVersionToConfigDirectoryIndexTest.java new file mode 100644 index 000000000..38f806e21 --- /dev/null +++ b/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/index/artifacts/SingleModuleJsonVersionToConfigDirectoryIndexTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2020, 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.reachability.internal.index.artifacts; + +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.util.Optional; + +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 SingleModuleJsonVersionToConfigDirectoryIndexTest { + private Path repoPath; + + private SingleModuleJsonVersionToConfigDirectoryIndex index; + + @Test + void checkIndex() throws URISyntaxException { + withIndex("artifact-1"); + + Optional configDir = index.findConfigurationDirectory("com.foo", "bar", "1.0"); + assertTrue(configDir.isPresent()); + assertEquals(repoPath.resolve("1"), configDir.get()); + + configDir = index.findConfigurationDirectory("com.foo", "bar", "1.3"); + assertTrue(configDir.isPresent()); + assertEquals(repoPath.resolve("1"), configDir.get()); + + configDir = index.findConfigurationDirectory("com.foo", "bar", "2.0"); + assertTrue(configDir.isPresent()); + assertEquals(repoPath.resolve("2"), configDir.get()); + + configDir = index.findConfigurationDirectory("com.foo", "bar", "2.5"); + assertFalse(configDir.isPresent()); + + configDir = index.findConfigurationDirectory("com.foo", "bar-all", "2.0"); + assertTrue(configDir.isPresent()); + assertEquals(repoPath.resolve("2"), configDir.get()); + + configDir = index.findConfigurationDirectory("com.foo", "nope", "1.0"); + assertFalse(configDir.isPresent()); + + Optional latest = index.findLatestConfigurationFor("com.foo", "bar"); + assertTrue(latest.isPresent()); + assertEquals(repoPath.resolve("2"), latest.get()); + + } + + private void withIndex(String json) throws URISyntaxException { + repoPath = new File(SingleModuleJsonVersionToConfigDirectoryIndexTest.class.getResource("/json/" + json).toURI()).toPath(); + index = new SingleModuleJsonVersionToConfigDirectoryIndex(repoPath); + } + +} diff --git a/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/index/modules/FileSystemModuleToConfigDirectoryIndexTest.java b/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/index/modules/FileSystemModuleToConfigDirectoryIndexTest.java new file mode 100644 index 000000000..11102b826 --- /dev/null +++ b/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/index/modules/FileSystemModuleToConfigDirectoryIndexTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2020, 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.reachability.internal.index.modules; + +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Set; + +import static java.util.Arrays.asList; +import static java.util.Collections.singleton; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class FileSystemModuleToConfigDirectoryIndexTest { + private Path repoPath; + + private FileSystemModuleToConfigDirectoryIndex index; + + @Test + void returnsSingleDirectory() throws IOException, URISyntaxException { + writeIndex("single-dir"); + Set configurationDirectories = index.findConfigurationDirectories("io.netty", "netty-core"); + assertEquals(singleton(repoPath.resolve("io/netty/netty-core")), configurationDirectories); + + configurationDirectories = index.findConfigurationDirectories("io.netty", "netty-all"); + assertEquals(singleton(repoPath.resolve("io/netty/netty-core")), configurationDirectories); + + configurationDirectories = index.findConfigurationDirectories("org", "bar"); + assertEquals(singleton(repoPath.resolve("org/bar")), configurationDirectories); + } + + @Test + void returnsMultipleDirectories() throws IOException, URISyntaxException { + writeIndex("multi-dirs"); + Set configurationDirectories = index.findConfigurationDirectories("io.netty", "netty-all"); + assertEquals(new HashSet<>(asList( + repoPath.resolve("io/netty/netty-core"), + repoPath.resolve("jline") + )), configurationDirectories); + + configurationDirectories = index.findConfigurationDirectories("org", "bar"); + assertEquals(singleton(repoPath.resolve("org/bar")), configurationDirectories); + } + + private void writeIndex(String json) throws URISyntaxException { + repoPath = new File(FileSystemModuleToConfigDirectoryIndexTest.class.getResource("/json/modules/" + json).toURI()).toPath(); + index = new FileSystemModuleToConfigDirectoryIndex(repoPath); + } + +} diff --git a/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/index/modules/JsonModuleToConfigDirectoryIndexTest.java b/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/index/modules/JsonModuleToConfigDirectoryIndexTest.java new file mode 100644 index 000000000..eca5987d8 --- /dev/null +++ b/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/index/modules/JsonModuleToConfigDirectoryIndexTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020, 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.reachability.internal.index.modules; + +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Set; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptySet; +import static java.util.Collections.singleton; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class JsonModuleToConfigDirectoryIndexTest { + private Path repoPath; + + private JsonModuleToConfigDirectoryIndex index; + + @Test + void returnsSingleDirectory() throws URISyntaxException { + writeIndex("single-dir"); + Set configurationDirectories = index.findConfigurationDirectories("io.netty", "netty-core"); + assertEquals(singleton(repoPath.resolve("io/netty/netty-core")), configurationDirectories); + + configurationDirectories = index.findConfigurationDirectories("io.netty", "netty-all"); + assertEquals(singleton(repoPath.resolve("io/netty/netty-core")), configurationDirectories); + + configurationDirectories = index.findConfigurationDirectories("org", "bar"); + assertEquals(emptySet(), configurationDirectories); + } + + @Test + void returnsMultipleDirectories() throws URISyntaxException { + writeIndex("multi-dirs"); + Set configurationDirectories = index.findConfigurationDirectories("io.netty", "netty-all"); + assertEquals(new HashSet<>(asList( + repoPath.resolve("io/netty/netty-core"), + repoPath.resolve("jline") + )), configurationDirectories); + + } + + private void writeIndex(String json) throws URISyntaxException { + repoPath = new File(FileSystemModuleToConfigDirectoryIndexTest.class.getResource("/json/modules/" + json).toURI()).toPath(); + index = new JsonModuleToConfigDirectoryIndex(repoPath); + } +} diff --git a/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/index/modules/StandardLocationModuleToConfigDirectoryIndexTest.java b/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/index/modules/StandardLocationModuleToConfigDirectoryIndexTest.java new file mode 100644 index 000000000..8b866066c --- /dev/null +++ b/common/jvm-reachability-metadata/src/test/java/org/graalvm/reachability/internal/index/modules/StandardLocationModuleToConfigDirectoryIndexTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020, 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.reachability.internal.index.modules; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Set; + +import static java.util.Collections.emptySet; +import static java.util.Collections.singleton; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class StandardLocationModuleToConfigDirectoryIndexTest { + @TempDir + private Path tempDir; + + private StandardLocationModuleToConfigDirectoryIndex index; + + @BeforeEach + void setUp() { + index = new StandardLocationModuleToConfigDirectoryIndex(tempDir); + } + + @Test + void returnsConventionalConfigLocation() throws IOException { + Path localDir = tempDir.resolve("org/module/foo"); + Files.createDirectories(localDir); + Set configurationDirectories = index.findConfigurationDirectories("org.module", "foo"); + assertEquals(singleton(localDir), configurationDirectories); + + configurationDirectories = index.findConfigurationDirectories("org", "bar"); + assertEquals(emptySet(), configurationDirectories); + } +} diff --git a/common/jvm-reachability-metadata/src/test/resources/json/artifact-1/index.json b/common/jvm-reachability-metadata/src/test/resources/json/artifact-1/index.json new file mode 100644 index 000000000..ad650cfc3 --- /dev/null +++ b/common/jvm-reachability-metadata/src/test/resources/json/artifact-1/index.json @@ -0,0 +1,5 @@ +[ + { "module": "com.foo:bar", "tested-versions": ["1.0", "1.1", "1.2", "1.3"], "metadata-version": "1" }, + { "module": "com.foo:bar", "tested-versions": ["2.0", "2.1"], "metadata-version": "2", "latest": true }, + { "module": "com.foo:bar-all", "tested-versions": ["2.0", "2.1"], "metadata-version": "2" } +] diff --git a/common/jvm-reachability-metadata/src/test/resources/json/modules/multi-dirs/index.json b/common/jvm-reachability-metadata/src/test/resources/json/modules/multi-dirs/index.json new file mode 100644 index 000000000..b6e62fcce --- /dev/null +++ b/common/jvm-reachability-metadata/src/test/resources/json/modules/multi-dirs/index.json @@ -0,0 +1,7 @@ +[ + { "module": "io.netty:netty-core", "directory": "io/netty/netty-core"}, + { "module": "org.jline:jline", "directory": "jline"}, + { + "module": "io.netty:netty-all", "requires": ["io.netty:netty-core", "org.jline:jline"] + } +] diff --git a/common/jvm-reachability-metadata/src/test/resources/json/modules/multi-dirs/jline/placeholder.txt b/common/jvm-reachability-metadata/src/test/resources/json/modules/multi-dirs/jline/placeholder.txt new file mode 100644 index 000000000..e69de29bb diff --git a/common/jvm-reachability-metadata/src/test/resources/json/modules/multi-dirs/netty-core/placeholder.txt b/common/jvm-reachability-metadata/src/test/resources/json/modules/multi-dirs/netty-core/placeholder.txt new file mode 100644 index 000000000..e69de29bb diff --git a/common/jvm-reachability-metadata/src/test/resources/json/modules/multi-dirs/org/bar/placeholder.txt b/common/jvm-reachability-metadata/src/test/resources/json/modules/multi-dirs/org/bar/placeholder.txt new file mode 100644 index 000000000..e69de29bb diff --git a/common/jvm-reachability-metadata/src/test/resources/json/modules/single-dir/index.json b/common/jvm-reachability-metadata/src/test/resources/json/modules/single-dir/index.json new file mode 100644 index 000000000..12872860b --- /dev/null +++ b/common/jvm-reachability-metadata/src/test/resources/json/modules/single-dir/index.json @@ -0,0 +1,7 @@ +[ + { "module": "io.netty:netty-core", "directory": "io/netty/netty-core"}, + { "module": "org.jline:jline", "directory": "jline"}, + { + "module": "io.netty:netty-all", "requires": ["io.netty:netty-core"] + } +] diff --git a/common/jvm-reachability-metadata/src/test/resources/json/modules/single-dir/io/netty/netty-core/placeholder.txt b/common/jvm-reachability-metadata/src/test/resources/json/modules/single-dir/io/netty/netty-core/placeholder.txt new file mode 100644 index 000000000..e69de29bb diff --git a/common/jvm-reachability-metadata/src/test/resources/json/modules/single-dir/jline/placeholder.txt b/common/jvm-reachability-metadata/src/test/resources/json/modules/single-dir/jline/placeholder.txt new file mode 100644 index 000000000..e69de29bb diff --git a/common/jvm-reachability-metadata/src/test/resources/json/modules/single-dir/org/bar/placeholder.txt b/common/jvm-reachability-metadata/src/test/resources/json/modules/single-dir/org/bar/placeholder.txt new file mode 100644 index 000000000..e69de29bb diff --git a/common/jvm-reachability-metadata/src/test/resources/repos/repo1/index.json b/common/jvm-reachability-metadata/src/test/resources/repos/repo1/index.json new file mode 100644 index 000000000..41b42e677 --- /dev/null +++ b/common/jvm-reachability-metadata/src/test/resources/repos/repo1/index.json @@ -0,0 +1,3 @@ +[ + +] diff --git a/common/jvm-reachability-metadata/src/test/resources/repos/repo1/org/foo/1/reflect-config.json b/common/jvm-reachability-metadata/src/test/resources/repos/repo1/org/foo/1/reflect-config.json new file mode 100644 index 000000000..e69de29bb diff --git a/common/jvm-reachability-metadata/src/test/resources/repos/repo1/org/foo/2/reflect-config.json b/common/jvm-reachability-metadata/src/test/resources/repos/repo1/org/foo/2/reflect-config.json new file mode 100644 index 000000000..e69de29bb diff --git a/common/jvm-reachability-metadata/src/test/resources/repos/repo1/org/foo/index.json b/common/jvm-reachability-metadata/src/test/resources/repos/repo1/org/foo/index.json new file mode 100644 index 000000000..cef1cc778 --- /dev/null +++ b/common/jvm-reachability-metadata/src/test/resources/repos/repo1/org/foo/index.json @@ -0,0 +1,17 @@ +[ + { + "module": "org:foo", + "tested-versions": [ + "1.0" + ], + "metadata-version": "1" + }, + { + "module": "org:foo", + "tested-versions": [ + "1.1" + ], + "metadata-version": "2", + "latest": true + } +] diff --git a/common/jvm-reachability-metadata/src/test/resources/repos/repo2/index.json b/common/jvm-reachability-metadata/src/test/resources/repos/repo2/index.json new file mode 100644 index 000000000..5ffe83bb0 --- /dev/null +++ b/common/jvm-reachability-metadata/src/test/resources/repos/repo2/index.json @@ -0,0 +1,6 @@ +[ + { + "module": "org:bar", + "directory": "org/foo" + } +] diff --git a/common/jvm-reachability-metadata/src/test/resources/repos/repo2/org/foo/1/reflect-config.json b/common/jvm-reachability-metadata/src/test/resources/repos/repo2/org/foo/1/reflect-config.json new file mode 100644 index 000000000..e69de29bb diff --git a/common/jvm-reachability-metadata/src/test/resources/repos/repo2/org/foo/2/reflect-config.json b/common/jvm-reachability-metadata/src/test/resources/repos/repo2/org/foo/2/reflect-config.json new file mode 100644 index 000000000..e69de29bb diff --git a/common/jvm-reachability-metadata/src/test/resources/repos/repo2/org/foo/index.json b/common/jvm-reachability-metadata/src/test/resources/repos/repo2/org/foo/index.json new file mode 100644 index 000000000..82b6277d0 --- /dev/null +++ b/common/jvm-reachability-metadata/src/test/resources/repos/repo2/org/foo/index.json @@ -0,0 +1,5 @@ +[ + { "module": "org:foo", "tested-versions": ["1.0"], "metadata-version": "1" }, + { "module": "org:foo", "tested-versions": ["1.1"], "metadata-version": "2" }, + { "module": "org:bar", "tested-versions": ["2.1"], "metadata-version": "2" } +] diff --git a/common/utils/build.gradle.kts b/common/utils/build.gradle.kts index c13ecad8f..d13cf9137 100644 --- a/common/utils/build.gradle.kts +++ b/common/utils/build.gradle.kts @@ -40,9 +40,7 @@ */ plugins { - checkstyle - id("org.graalvm.build.java") - id("org.graalvm.build.publishing") + id("org.graalvm.build.utils-module") } maven { @@ -55,32 +53,3 @@ dependencies { implementation(platform(libs.test.junit.bom)) implementation(libs.test.junit.jupiter.core) } - -tasks.withType().configureEach { - useJUnitPlatform() -} - -val generateVersionInfo = tasks.register("generateVersionInfo", org.graalvm.build.GenerateVersionClass::class.java) { - versions.put("junitPlatformNative", libs.versions.nativeBuildTools) - outputDirectory.set(layout.buildDirectory.dir("generated/sources/versions")) -} - -sourceSets { - main { - java { - srcDir(generateVersionInfo) - } - } -} - -publishing { - publications { - create("maven") { - from(components["java"]) - } - } -} - -tasks.withType().configureEach { - setConfigFile(layout.projectDirectory.dir("../../config/checkstyle.xml").asFile) -} diff --git a/common/utils/settings.gradle.kts b/common/utils/settings.gradle.kts index 71f4aa2c0..47bad796b 100644 --- a/common/utils/settings.gradle.kts +++ b/common/utils/settings.gradle.kts @@ -40,7 +40,9 @@ */ pluginManagement { - includeBuild("../../build-logic") + includeBuild("../../build-logic/settings-plugins") + includeBuild("../../build-logic/common-plugins") + includeBuild("../../build-logic/utils-plugins") } plugins { diff --git a/common/utils/src/main/java/org/graalvm/buildtools/model/resources/ClassPathDirectoryAnalyzer.java b/common/utils/src/main/java/org/graalvm/buildtools/model/resources/ClassPathDirectoryAnalyzer.java index b7c016516..39a7f7bbf 100644 --- a/common/utils/src/main/java/org/graalvm/buildtools/model/resources/ClassPathDirectoryAnalyzer.java +++ b/common/utils/src/main/java/org/graalvm/buildtools/model/resources/ClassPathDirectoryAnalyzer.java @@ -68,8 +68,7 @@ protected List initialize() throws IOException { DirectoryVisitor visitor = new DirectoryVisitor(); Files.walkFileTree(root, visitor); return visitor.hasNativeImageResourceFile && !ignoreExistingResourcesConfig ? Collections.emptyList() : visitor.resources; - } - else { + } else { return Collections.emptyList(); } } diff --git a/common/utils/src/main/java/org/graalvm/buildtools/utils/NativeImageUtils.java b/common/utils/src/main/java/org/graalvm/buildtools/utils/NativeImageUtils.java index d2a83c588..ce3045c25 100644 --- a/common/utils/src/main/java/org/graalvm/buildtools/utils/NativeImageUtils.java +++ b/common/utils/src/main/java/org/graalvm/buildtools/utils/NativeImageUtils.java @@ -48,6 +48,7 @@ import java.nio.file.StandardOpenOption; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import static org.graalvm.buildtools.utils.SharedConstants.GRAALVM_EXE_EXTENSION; @@ -75,6 +76,7 @@ public static List convertToArgsFile(List cliArgs) { try { File tmpFile = File.createTempFile("native-image", "args"); tmpFile.deleteOnExit(); + cliArgs = cliArgs.stream().map(NativeImageUtils::escapeArg).collect(Collectors.toList()); Files.write(tmpFile.toPath(), cliArgs, StandardCharsets.UTF_8, StandardOpenOption.CREATE); return Collections.singletonList("@" + tmpFile.getAbsolutePath()); } catch (IOException e) { @@ -82,4 +84,12 @@ public static List convertToArgsFile(List cliArgs) { return Collections.unmodifiableList(cliArgs); } } + + public static String escapeArg(String arg) { + arg = arg.replace("\\", "\\\\"); + if (arg.contains(" ")) { + arg = "\"" + arg + "\""; + } + return arg; + } } diff --git a/docs/settings.gradle.kts b/docs/settings.gradle.kts index f322595fe..97a4660ea 100644 --- a/docs/settings.gradle.kts +++ b/docs/settings.gradle.kts @@ -39,16 +39,16 @@ * SOFTWARE. */ -rootProject.name = "docs" - -enableFeaturePreview("VERSION_CATALOGS") +pluginManagement { + includeBuild("../build-logic/settings-plugins") + includeBuild("../build-logic/documentation-plugins") +} -dependencyResolutionManagement { - versionCatalogs { - create("libs") { - from(files("../gradle/libs.versions.toml")) - } - } +plugins { + id("org.graalvm.build.common") } +rootProject.name = "docs" + includeBuild("../native-gradle-plugin") +includeBuild("../native-maven-plugin") diff --git a/docs/src/docs/asciidoc/gradle-plugin.adoc b/docs/src/docs/asciidoc/gradle-plugin.adoc index 1a23caa6a..d864ea551 100644 --- a/docs/src/docs/asciidoc/gradle-plugin.adoc +++ b/docs/src/docs/asciidoc/gradle-plugin.adoc @@ -335,6 +335,85 @@ include::../snippets/gradle/groovy/build.gradle[tags=add-agent-options-individua include::../snippets/gradle/kotlin/build.gradle.kts[tags=add-agent-options-individual] ---- +[[metadata-support]] +== JVM Reachability Metadata support + +Since release 0.9.11, the plugin adds experimental support for the https://github.com/graalvm/jvm-reachability-metadata/[JVM reachability metadata repository]. +This repository provides GraalVM configuration for libraries which do not officially support GraalVM native. + +=== Enabling the metadata repository + +Support needs to be enabled explicitly: + +.Enabling the metadata repository +[source, groovy, role="multi-language-sample"] +---- +include::../snippets/gradle/groovy/build.gradle[tags=enable-metadata-repository] +---- + +[source, kotlin, role="multi-language-sample"] +---- +include::../snippets/gradle/kotlin/build.gradle.kts[tags=enable-metadata-repository] +---- + +A metadata repository consists of configuration files for GraalVM. +The plugin will automatically download the configuration metadata from the official repository if you supply the version of the repository you want to use: + +.Enabling the metadata repository +[source, groovy, role="multi-language-sample"] +---- +include::../snippets/gradle/groovy/build.gradle[tags=specify-metadata-repository-version] +---- + +[source, kotlin, role="multi-language-sample"] +---- +include::../snippets/gradle/kotlin/build.gradle.kts[tags=specify-metadata-repository-version] +---- + +Alternatively, it is possible to use a _local repository_, in which case you can specify the path to the repository: + +.Using a local repository +[source, groovy, role="multi-language-sample"] +---- +include::../snippets/gradle/groovy/build.gradle[tags=specify-metadata-repository-file] +---- + +[source, kotlin, role="multi-language-sample"] +---- +include::../snippets/gradle/kotlin/build.gradle.kts[tags=specify-metadata-repository-file] +---- + +=== Configuring the metadata repository + +Once activated, for each library included in the native image, the plugin will automatically search for GraalVM JVM reachability metadata in the repository. +In some cases, you may need to exclude a particular module from the search. +This can be done by adding it to the exclude list: + +.Excluding a module from search +[source, groovy, role="multi-language-sample"] +---- +include::../snippets/gradle/groovy/build.gradle[tags=exclude-module-from-metadata-repo] +---- + +[source, kotlin, role="multi-language-sample"] +---- +include::../snippets/gradle/kotlin/build.gradle.kts[tags=exclude-module-from-metadata-repo] +---- + +Last, it is possible for you to override the _metadata version_ of a particular module. +This may be interesting if there's no specific metadata available for the particular version of the library that you use, but that you know that a version works: + +.Specifying the metadata version to use for a particular library +[source, groovy, role="multi-language-sample"] +---- +include::../snippets/gradle/groovy/build.gradle[tags=specify-metadata-version-for-library] +---- + +[source, kotlin, role="multi-language-sample"] +---- +include::../snippets/gradle/kotlin/build.gradle.kts[tags=specify-metadata-version-for-library] +---- + [[plugin-configurations]] == Configurations defined by the plugin diff --git a/docs/src/docs/asciidoc/index.adoc b/docs/src/docs/asciidoc/index.adoc index 911b6a123..d25f3bdb0 100644 --- a/docs/src/docs/asciidoc/index.adoc +++ b/docs/src/docs/asciidoc/index.adoc @@ -14,6 +14,19 @@ If you are interested in contributing, please refer to our https://github.com/gr [[changelog]] == Changelog +=== Release 0.9.11 + +==== Maven plugin + +* Fix long classpath issue under Windows when running native tests +* Inherit environment variables and system properties from the surefire plugin configuration when executing tests +* Fix invocation of `native-image` when classpath contains spaces + +==== Gradle plugin + +* Add support for environment variables in native test execution +* Fix invocation of `native-image` when classpath contains spaces +* Add experimental support for the JVM reachability metadata repository === Release 0.9.10 diff --git a/docs/src/docs/snippets/gradle/groovy/build.gradle b/docs/src/docs/snippets/gradle/groovy/build.gradle index c7ba25b7e..91c9f9fbd 100644 --- a/docs/src/docs/snippets/gradle/groovy/build.gradle +++ b/docs/src/docs/snippets/gradle/groovy/build.gradle @@ -149,3 +149,46 @@ graalvmNative { } } // end::add-agent-options-individual[] + +// tag::enable-metadata-repository[] +graalvmNative { + metadataRepository { + enabled = true + } +} +// end::enable-metadata-repository[] + +// tag::specify-metadata-repository-version[] +graalvmNative { + metadataRepository { + version = "1.0.0" + } +} +// end::specify-metadata-repository-version[] + +// tag::specify-metadata-repository-file[] +graalvmNative { + metadataRepository { + uri(file("metadata-repository")) + } +} +// end::specify-metadata-repository-file[] + +// tag::exclude-module-from-metadata-repo[] +graalvmNative { + metadataRepository { + // Exclude this library from automatic metadata + // repository search + excludes.add("com.company:some-library") + } +} +// end::exclude-module-from-metadata-repo[] + +// tag::specify-metadata-version-for-library[] +graalvmNative { + metadataRepository { + // Force the version of the metadata for a particular library + moduleToConfigVersion.put("com.company:some-library", "3") + } +} +// end::specify-metadata-version-for-library[] diff --git a/docs/src/docs/snippets/gradle/kotlin/build.gradle.kts b/docs/src/docs/snippets/gradle/kotlin/build.gradle.kts index 7d26539d0..78db3e99a 100644 --- a/docs/src/docs/snippets/gradle/kotlin/build.gradle.kts +++ b/docs/src/docs/snippets/gradle/kotlin/build.gradle.kts @@ -162,3 +162,47 @@ graalvmNative { } } // end::add-agent-options-individual[] + +// tag::enable-metadata-repository[] +graalvmNative { + metadataRepository { + enabled.set(true) + } +} +// end::enable-metadata-repository[] + +// tag::specify-metadata-repository-version[] +graalvmNative { + metadataRepository { + version.set("1.0.0") + } +} +// end::specify-metadata-repository-version[] + + +// tag::specify-metadata-repository-file[] +graalvmNative { + metadataRepository { + uri(file("metadata-repository")) + } +} +// end::specify-metadata-repository-file[] + +// tag::exclude-module-from-metadata-repo[] +graalvmNative { + metadataRepository { + // Exclude this library from automatic metadata + // repository search + excludes.add("com.company:some-library") + } +} +// end::exclude-module-from-metadata-repo[] + +// tag::specify-metadata-version-for-library[] +graalvmNative { + metadataRepository { + // Force the version of the metadata for a particular library + moduleToConfigVersion.put("com.company:some-library", "3") + } +} +// end::specify-metadata-version-for-library[] diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2aa0b3259..de4a759ab 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] # Project versions -nativeBuildTools = "0.9.10" +nativeBuildTools = "0.9.11" # External dependencies spock = "2.0-groovy-3.0" @@ -23,6 +23,7 @@ nativeGradlePlugin = { module = "org.graalvm.buildtools:native-gradle-plugin", v nativeMavenPlugin = { module = "org.graalvm.buildtools:native-maven-plugin", version.ref = "nativeBuildTools" } junitPlatformNative = { module = "org.graalvm.buildtools:junit-platform-native", version.ref = "nativeBuildTools" } utils = { module = "org.graalvm.buildtools:utils", version.ref = "nativeBuildTools" } +jvmReachabilityMetadata = { module = "org.graalvm.buildtools:jvm-reachability-metadata", version.ref = "nativeBuildTools" } # External dependencies test-junit-platform-console = { module = "org.junit.platform:junit-platform-console", version.ref = "junitPlatform" } diff --git a/native-gradle-plugin/build.gradle b/native-gradle-plugin/build.gradle index 65aa34a80..fd6bbde0e 100644 --- a/native-gradle-plugin/build.gradle +++ b/native-gradle-plugin/build.gradle @@ -56,10 +56,12 @@ maven { dependencies { implementation libs.utils + implementation libs.jvmReachabilityMetadata testImplementation libs.test.spock testFixturesImplementation libs.test.spock testFixturesImplementation gradleTestKit() functionalTestCommonRepository(libs.junitPlatformNative) + functionalTestCommonRepository("org.graalvm.internal:library-with-reflection") } pluginBundle { diff --git a/native-gradle-plugin/settings.gradle b/native-gradle-plugin/settings.gradle index 5200113e3..a26690df8 100644 --- a/native-gradle-plugin/settings.gradle +++ b/native-gradle-plugin/settings.gradle @@ -40,7 +40,9 @@ */ pluginManagement { - includeBuild("../build-logic") + includeBuild("../build-logic/settings-plugins") + includeBuild("../build-logic/common-plugins") + includeBuild("../build-logic/gradle-functional-testing") } plugins { @@ -51,3 +53,4 @@ rootProject.name = 'native-gradle-plugin' includeBuild("../common/junit-platform-native") includeBuild("../common/utils") +includeBuild("../test-support/library-with-reflection") diff --git a/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/JavaApplicationFunctionalTest.groovy b/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/JavaApplicationFunctionalTest.groovy index 4876c7fd3..4af8aadc2 100644 --- a/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/JavaApplicationFunctionalTest.groovy +++ b/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/JavaApplicationFunctionalTest.groovy @@ -155,4 +155,37 @@ class JavaApplicationFunctionalTest extends AbstractFunctionalTest { } + @Issue("https://github.com/graalvm/native-build-tools/issues/224") + def "handles spaces in file names"() { + given: + withSpacesInProjectDir() + withSample("java-application") + + buildFile << """ + // force realization of the run task to verify that it + // doesn't accidentally introduce a dependency + tasks.getByName('run') + """.stripIndent() + + when: + run 'nativeCompile' + + then: + tasks { + succeeded ':jar', ':nativeCompile' + doesNotContain ':build', ':run' + } + + and: + def nativeApp = file("build/native/nativeCompile/java-application") + nativeApp.exists() + + when: + def process = execute(nativeApp) + + then: + process.output.contains "Hello, native!" + + } + } diff --git a/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/JavaApplicationWithTestsFunctionalTest.groovy b/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/JavaApplicationWithTestsFunctionalTest.groovy index 1b16caea8..733ff48bd 100644 --- a/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/JavaApplicationWithTestsFunctionalTest.groovy +++ b/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/JavaApplicationWithTestsFunctionalTest.groovy @@ -143,6 +143,38 @@ class JavaApplicationWithTestsFunctionalTest extends AbstractFunctionalTest { junitVersion = System.getProperty('versions.junit') } + @Issue("https://github.com/graalvm/native-build-tools/issues/215") + @Unroll("can pass environment variables to native test execution with JUnit Platform #junitVersion") + def "can pass environment variables to native test execution"() { + given: + withSample("java-application-with-tests") + buildFile << """ + tasks.named("nativeTest") { + environment.put("TEST_ENV", "test-value") + } + + """ + + when: + run 'nativeTest' + + then: + tasks { + succeeded ':testClasses', + ':nativeTestCompile', + ':test', // there should probably not be a dependency here + ':nativeTest' + doesNotContain ':build' + } + + then: + outputDoesNotContain "Running in 'test discovery' mode. Note that this is a fallback mode." + outputContains "TEST_ENV = test-value" + + where: + junitVersion = System.getProperty('versions.junit') + } + @Issue("https://github.com/graalvm/native-build-tools/issues/133") @Unroll("can disable test support with JUnit Platform #junitVersion") def "can disable test support"() { @@ -221,4 +253,38 @@ class JavaApplicationWithTestsFunctionalTest extends AbstractFunctionalTest { where: junitVersion = System.getProperty('versions.junit') } + + @Issue("https://github.com/graalvm/native-build-tools/issues/218") + def "test list directory output is properly configured"() { + given: + withSample("java-application-with-tests") + + buildFile << """ + tasks.register("otherTest", Test) { + classpath = tasks.test.classpath + testClassesDirs = tasks.test.testClassesDirs + } + """ + + when: + run 'test' + + then: + file("build/test-results/test/testlist").isDirectory() + !file("build/test-results/otherTest/testlist").isDirectory() + + when: + run 'otherTest' + + then: + !file("build/test-results/otherTest/testlist").isDirectory() + + when: + run 'test' + + then: + tasks { + upToDate(':test') + } + } } diff --git a/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/NativeConfigRepoFunctionalTest.groovy b/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/NativeConfigRepoFunctionalTest.groovy new file mode 100644 index 000000000..ef1b0af0e --- /dev/null +++ b/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/NativeConfigRepoFunctionalTest.groovy @@ -0,0 +1,145 @@ +/* + * Copyright (c) 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.gradle + +import org.graalvm.buildtools.gradle.fixtures.AbstractFunctionalTest +import org.gradle.api.logging.LogLevel +import spock.lang.Unroll + +class NativeConfigRepoFunctionalTest extends AbstractFunctionalTest { + + @Unroll + def "can build a native image using native configuration from a #label"() { + given: + withSample("native-config-integration") + + switch (format) { + case 'dir': + break + case 'zip': + run 'configZip' + break + default: + run "config${format.split('[.]').collect {it.capitalize()}.join("")}" + } + + when: + def extension = format == 'dir' ? '' : format + run 'nativeRun', "-D${NativeImagePlugin.CONFIG_REPO_LOGLEVEL}=${LogLevel.LIFECYCLE}", "-Dextension=$extension" + + then: + tasks { + succeeded ':jar', ':nativeCompile', ':nativeRun' + } + + then: + outputContains "Hello, from reflection!" + + and: "doesn't find a configuration directory for the current version" + outputContains "[jvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration directory not found. Trying latest version." + + and: "but finds one thanks to the latest configuration field" + outputContains "[jvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration directory is org/graalvm/internal/library-with-reflection/1" + + where: + format | label + 'dir' | "flat directory" + 'zip' | 'zip file' + 'tar.gz' | 'tar.gz file' + 'tar.bz2' | 'tar.bz2 file' + } + + def "can exclude a dependency from native configuration"() { + given: + withSample("native-config-integration") + + buildFile << """ +graalvmNative { + metadataRepository { + excludedModules.add("org.graalvm.internal:library-with-reflection") + } +} + """ + + when: + run 'nativeRun', "-D${NativeImagePlugin.CONFIG_REPO_LOGLEVEL}=${LogLevel.LIFECYCLE}" + + then: + tasks { + succeeded ':jar', ':nativeCompile', ':nativeRun' + } + + then: + outputContains "Reflection failed" + + and: "doesn't look for a configuration directory for the current version" + outputDoesNotContain "[jvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration directory not found. Trying latest version." + } + + def "can force a dependency to a specific config version"() { + given: + withSample("native-config-integration") + + buildFile << """ +graalvmNative { + metadataRepository { + moduleToConfigVersion.put("org.graalvm.internal:library-with-reflection", "2") + } +} + """ + + when: + run 'nativeRun', "-D${NativeImagePlugin.CONFIG_REPO_LOGLEVEL}=${LogLevel.LIFECYCLE}" + + then: + tasks { + succeeded ':jar', ':nativeCompile', ':nativeRun' + } + + then: + outputContains "Reflection failed" + + and: "looks for specific configuration version" + outputContains "[jvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration is forced to version 2" + } + +} 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 72ff61bd3..e35e67179 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 @@ -44,6 +44,7 @@ import org.graalvm.buildtools.VersionInfo; import org.graalvm.buildtools.gradle.dsl.AgentConfiguration; import org.graalvm.buildtools.gradle.dsl.GraalVMExtension; +import org.graalvm.buildtools.gradle.dsl.JvmReachabilityMetadataRepositoryExtension; import org.graalvm.buildtools.gradle.dsl.NativeImageOptions; import org.graalvm.buildtools.gradle.internal.AgentCommandLineProvider; import org.graalvm.buildtools.gradle.internal.BaseNativeImageOptions; @@ -52,6 +53,7 @@ import org.graalvm.buildtools.gradle.internal.DeprecatedNativeImageOptions; import org.graalvm.buildtools.gradle.internal.GraalVMLogger; import org.graalvm.buildtools.gradle.internal.GradleUtils; +import org.graalvm.buildtools.gradle.internal.JvmReachabilityMetadataService; import org.graalvm.buildtools.gradle.internal.NativeConfigurations; import org.graalvm.buildtools.gradle.internal.ProcessGeneratedGraalResourceFiles; import org.graalvm.buildtools.gradle.tasks.BuildNativeImageTask; @@ -65,6 +67,7 @@ import org.gradle.api.Task; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationContainer; +import org.gradle.api.artifacts.ModuleVersionIdentifier; import org.gradle.api.attributes.Attribute; import org.gradle.api.attributes.AttributeContainer; import org.gradle.api.file.ArchiveOperations; @@ -75,18 +78,18 @@ import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileSystemLocation; import org.gradle.api.file.FileSystemOperations; +import org.gradle.api.logging.LogLevel; import org.gradle.api.model.ObjectFactory; import org.gradle.api.plugins.ApplicationPlugin; +import org.gradle.api.plugins.ExtensionAware; import org.gradle.api.plugins.JavaApplication; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; -import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.JavaExec; -import org.gradle.api.tasks.PathSensitive; -import org.gradle.api.tasks.PathSensitivity; +import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSetContainer; import org.gradle.api.tasks.TaskContainer; @@ -96,17 +99,21 @@ import org.gradle.api.tasks.testing.Test; import org.gradle.jvm.toolchain.JavaToolchainService; import org.gradle.language.base.plugins.LifecycleBasePlugin; -import org.gradle.process.ExecOperations; import org.gradle.process.CommandLineArgumentProvider; +import org.gradle.process.ExecOperations; import org.gradle.process.JavaForkOptions; import org.gradle.util.GFileUtils; import javax.inject.Inject; import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.concurrent.Callable; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -136,6 +143,8 @@ public class NativeImagePlugin implements Plugin { public static final String DEPRECATED_NATIVE_BUILD_TASK = "nativeBuild"; public static final String DEPRECATED_NATIVE_TEST_BUILD_TASK = "nativeTestBuild"; + public static final String CONFIG_REPO_LOGLEVEL = "org.graalvm.internal.gradle.configrepo.logging"; + /** * This looks strange, but it is used to force the configuration of a dependent * task during the configuration of another one. This is a workaround for a bug @@ -279,9 +288,61 @@ private void configureAutomaticTaskCreation(Project project, options.getConfigurationFileDirectories().from(generateResourcesConfig.map(t -> t.getOutputFile().map(f -> f.getAsFile().getParentFile()) )); + configureJvmReachabilityConfigurationDirectories(project, graalExtension, options, sourceSet); }); } + private void configureJvmReachabilityConfigurationDirectories(Project project, GraalVMExtension graalExtension, NativeImageOptions options, SourceSet sourceSet) { + JvmReachabilityMetadataRepositoryExtension repositoryExtension = reachabilityExtensionOn(graalExtension); + Provider serviceProvider = project.getGradle() + .getSharedServices() + .registerIfAbsent("nativeConfigurationService", JvmReachabilityMetadataService.class, spec -> { + LogLevel logLevel = determineLogLevel(); + spec.getParameters().getLogLevel().set(logLevel); + spec.getParameters().getUri().set(repositoryExtension.getUri()); + spec.getParameters().getCacheDir().set(new File(project.getGradle().getGradleUserHomeDir(), "native-build-tools/repositories")); + }); + options.getConfigurationFileDirectories().from(repositoryExtension.getEnabled().flatMap(enabled -> { + if (enabled) { + if (repositoryExtension.getUri().isPresent()) { + Configuration classpath = project.getConfigurations().getByName(sourceSet.getRuntimeClasspathConfigurationName()); + Set excludedModules = repositoryExtension.getExcludedModules().getOrElse(Collections.emptySet()); + Map forcedVersions = repositoryExtension.getModuleToConfigVersion().getOrElse(Collections.emptyMap()); + return serviceProvider.map(repo -> repo.findConfigurationDirectoriesFor(query -> classpath.getIncoming().getResolutionResult().allComponents(component -> { + ModuleVersionIdentifier moduleVersion = component.getModuleVersion(); + String module = moduleVersion.getGroup() + ":" + moduleVersion.getName(); + if (!excludedModules.contains(module)) { + query.forArtifact(artifact -> { + artifact.gav(module + ":" + moduleVersion.getVersion()); + if (forcedVersions.containsKey(module)) { + artifact.forceConfigVersion(forcedVersions.get(module)); + } + }); + } + query.useLatestConfigWhenVersionIsUntested(); + })).stream() + .map(Path::toAbsolutePath) + .map(Path::toFile) + .collect(Collectors.toList())); + } + } + return project.getProviders().provider(Collections::emptySet); + })); + } + + private static LogLevel determineLogLevel() { + LogLevel logLevel = LogLevel.DEBUG; + String loggingProperty = System.getProperty(CONFIG_REPO_LOGLEVEL); + if (loggingProperty != null) { + logLevel = LogLevel.valueOf(loggingProperty.toUpperCase(Locale.US)); + } + return logLevel; + } + + private static JvmReachabilityMetadataRepositoryExtension reachabilityExtensionOn(GraalVMExtension graalExtension) { + return ((ExtensionAware) graalExtension).getExtensions().getByType(JvmReachabilityMetadataRepositoryExtension.class); + } + private void deprecateExtension(Project project, NativeImageOptions delegate, String name, @@ -340,9 +401,24 @@ private GraalVMExtension registerGraalVMExtension(Project project) { graalvmNative.getGeneratedResourcesDirectory().set(project.getLayout() .getBuildDirectory() .dir("native/generated/")); + configureNativeConfigurationRepo((ExtensionAware) graalvmNative); return graalvmNative; } + private void configureNativeConfigurationRepo(ExtensionAware graalvmNative) { + JvmReachabilityMetadataRepositoryExtension configurationRepository = graalvmNative.getExtensions().create("metadataRepository", JvmReachabilityMetadataRepositoryExtension.class); + configurationRepository.getEnabled().convention(false); + configurationRepository.getUri().convention(configurationRepository.getVersion().map(v -> { + try { + return new URI("https://github.com/graalvm/jvm-reachability-metadata/releases/download/" + v + "/jvm-reachability-metadata-" + v + ".zip"); + } catch (URISyntaxException e) { + return null; + } + })); + configurationRepository.getExcludedModules().convention(Collections.emptySet()); + configurationRepository.getModuleToConfigVersion().convention(Collections.emptyMap()); + } + private TaskProvider registerResourcesConfigTask(Provider generatedDir, NativeImageOptions options, TaskContainer tasks, @@ -380,8 +456,9 @@ public void registerTestBinary(Project project, TaskProvider testTask = config.validate().getTestTask(); testOptions.getAgent().getInstrumentedTask().set(testTask); testTask.configure(test -> { - testListDirectory.set(new File(testResultsDir, test.getName() + "/testlist")); - test.getOutputs().dir(testResultsDir); + File testList = new File(testResultsDir, test.getName() + "/testlist"); + testListDirectory.set(testList); + test.getOutputs().dir(testList); // Set system property read by the UniqueIdTrackingListener. test.systemProperty(JUNIT_PLATFORM_LISTENERS_UID_TRACKING_ENABLED, true); TrackingDirectorySystemPropertyProvider directoryProvider = project.getObjects().newInstance(TrackingDirectorySystemPropertyProvider.class); @@ -588,8 +665,7 @@ public void execute(Task task) { } public abstract static class TrackingDirectorySystemPropertyProvider implements CommandLineArgumentProvider { - @InputFiles - @PathSensitive(PathSensitivity.RELATIVE) + @OutputDirectory public abstract DirectoryProperty getDirectory(); /** diff --git a/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/dsl/JvmReachabilityMetadataRepositoryExtension.java b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/dsl/JvmReachabilityMetadataRepositoryExtension.java new file mode 100644 index 000000000..181b693fc --- /dev/null +++ b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/dsl/JvmReachabilityMetadataRepositoryExtension.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2020, 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.dsl; + +import org.gradle.api.provider.MapProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.provider.SetProperty; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; + +/** + * Extension used to configure the JVM reachability metadata repository. + */ +public interface JvmReachabilityMetadataRepositoryExtension { + /** + * Property used to determine if the native configuration + * repository should be used. + * @return the enabled property + */ + Property getEnabled(); + + /** + * A URI pointing to a jvm reachability metadata repository. This must + * either be a local file or a remote URI. In case of remote + * files, only zip or tarballs are supported. + * @return the uri property + */ + Property getUri(); + + /** + * An optional version of the remote repository: if specified, + * and that no URI is provided, it will automatically use a + * published repository from the official GraalVM configuration + * repository. + * + * @return the version of the repository to use + */ + Property getVersion(); + + /** + * The set of modules for which we don't want to use the + * configuration found in the repository. Modules must be + * declared with the `groupId:artifactId` syntax. + * @return the set of excluded modules + */ + SetProperty getExcludedModules(); + + /** + * A map from a module (org.group:artifact) to configuration + * repository config version. + * @return the map of modules to forced configuration versions + */ + MapProperty getModuleToConfigVersion(); + + /** + * Convenience method to use a String for the URI + * property. + * @param uri the URI + */ + default void uri(String uri) throws URISyntaxException { + getUri().set(new URI(uri)); + } + + /** + * Convenience method to use a URI for the property. + * @param file a file + */ + default void uri(File file) { + getUri().set(file.toURI()); + } +} diff --git a/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/JvmReachabilityMetadataService.java b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/JvmReachabilityMetadataService.java new file mode 100644 index 000000000..0e1997825 --- /dev/null +++ b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/internal/JvmReachabilityMetadataService.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2020, 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.internal; + +import org.graalvm.reachability.JvmReachabilityMetadataRepository; +import org.graalvm.reachability.Query; +import org.graalvm.reachability.internal.FileSystemRepository; +import org.gradle.api.file.ArchiveOperations; +import org.gradle.api.file.DirectoryProperty; +import org.gradle.api.file.FileSystemOperations; +import org.gradle.api.logging.LogLevel; +import org.gradle.api.logging.Logger; +import org.gradle.api.logging.Logging; +import org.gradle.api.provider.Property; +import org.gradle.api.services.BuildService; +import org.gradle.api.services.BuildServiceParameters; + +import javax.inject.Inject; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +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.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; +import java.util.function.Supplier; + +public abstract class JvmReachabilityMetadataService implements BuildService, JvmReachabilityMetadataRepository { + private static final Logger LOGGER = Logging.getLogger(JvmReachabilityMetadataService.class); + + private final JvmReachabilityMetadataRepository repository; + + @Inject + protected abstract ArchiveOperations getArchiveOperations(); + + @Inject + protected abstract FileSystemOperations getFileOperations(); + + public interface Params extends BuildServiceParameters { + Property getLogLevel(); + + Property getUri(); + + DirectoryProperty getCacheDir(); + } + + public JvmReachabilityMetadataService() throws URISyntaxException { + URI uri = getParameters().getUri().get(); + 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("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 | UnsupportedEncodingException e) { + throw new UnsupportedOperationException(e); + } + } + + private JvmReachabilityMetadataRepository newRepository(URI uri) throws URISyntaxException { + String cacheKey = hashFor(uri); + String path = uri.getPath(); + LogLevel logLevel = getParameters().getLogLevel().get(); + if (uri.getScheme().equals("file")) { + File localFile = new File(uri); + if (isSupportedZipFormat(path)) { + return newRepositoryFromZipFile(cacheKey, localFile, logLevel); + } + return newRepositoryFromDirectory(localFile.toPath(), logLevel); + } + if (isSupportedZipFormat(path)) { + File zipped = getParameters().getCacheDir().file(cacheKey + "/archive").get().getAsFile(); + if (!zipped.exists()) { + try (ReadableByteChannel readableByteChannel = Channels.newChannel(uri.toURL().openStream())) { + try (FileOutputStream fileOutputStream = new FileOutputStream(zipped)) { + fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return newRepositoryFromZipFile(cacheKey, zipped, logLevel); + } + throw new UnsupportedOperationException("Remote URI must point to a zip, a tar.gz or tar.bz2 file"); + } + + private static boolean isSupportedZipFormat(String path) { + return path.endsWith(".zip") || path.endsWith(".tar.gz") || path.endsWith(".tar.bz2"); + } + + private FileSystemRepository newRepositoryFromZipFile(String cacheKey, File localFile, LogLevel logLevel) { + File explodedEntry = getParameters().getCacheDir().file(cacheKey + "/exploded").get().getAsFile(); + if (!explodedEntry.exists()) { + if (explodedEntry.getParentFile().isDirectory() || explodedEntry.getParentFile().mkdirs()) { + LOGGER.info("Extracting {} to {}", localFile, explodedEntry); + getFileOperations().copy(spec -> { + if (localFile.getName().endsWith(".zip")) { + spec.from(getArchiveOperations().zipTree(localFile)); + } else if (localFile.getName().endsWith(".tar.gz")) { + spec.from(getArchiveOperations().tarTree(localFile)); + } else if (localFile.getName().endsWith(".tar.bz2")) { + spec.from(getArchiveOperations().tarTree(localFile)); + } + spec.into(explodedEntry); + }); + } + } + return newRepositoryFromDirectory(explodedEntry.toPath(), logLevel); + } + + private FileSystemRepository newRepositoryFromDirectory(Path path, LogLevel logLevel) { + if (Files.isDirectory(path)) { + return new FileSystemRepository(path, new FileSystemRepository.Logger() { + @Override + public void log(String groupId, String artifactId, String version, Supplier message) { + LOGGER.log(logLevel, "[jvm reachability metadata repository for {}:{}:{}]: {}", groupId, artifactId, version, message.get()); + } + }); + } else { + throw new IllegalArgumentException("JVM reachability metadata repository URI must point to a directory"); + } + } + + /** + * Performs a generic query on the repository, returning a list of + * configuration directories. The query may be parameterized with + * a number of artifacts, and can be used to refine behavior, for + * example if a configuration directory isn't available for a + * particular artifact version. + * + * @param queryBuilder the query builder + * @return the set of configuration directories matching the query + */ + @Override + public Set findConfigurationDirectoriesFor(Consumer queryBuilder) { + return repository.findConfigurationDirectoriesFor(queryBuilder); + } + + /** + * Returns a list of configuration directories for the specified artifact. + * There may be more than one configuration directory for a given artifact, + * but the list may also be empty if the repository doesn't contain any. + * Never null. + * + * @param gavCoordinates the artifact GAV coordinates (group:artifact:version) + * @return a list of configuration directories + */ + @Override + public Set findConfigurationDirectoriesFor(String gavCoordinates) { + return repository.findConfigurationDirectoriesFor(gavCoordinates); + } + + /** + * Returns the set of configuration directories for all the modules supplied + * as an argument. + * + * @param modules the list of modules + * @return the set of configuration directories + */ + @Override + public Set findConfigurationDirectoriesFor(Collection modules) { + return repository.findConfigurationDirectoriesFor(modules); + } +} diff --git a/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/tasks/NativeRunTask.java b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/tasks/NativeRunTask.java index f232d54a1..4129bc83e 100644 --- a/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/tasks/NativeRunTask.java +++ b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/tasks/NativeRunTask.java @@ -45,12 +45,15 @@ import org.gradle.api.file.RegularFileProperty; import org.gradle.api.plugins.ApplicationPlugin; import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.MapProperty; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputFile; +import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.TaskAction; import org.gradle.process.ExecOperations; import javax.inject.Inject; +import java.util.Map; @SuppressWarnings("unused") public abstract class NativeRunTask extends DefaultTask { @@ -62,6 +65,10 @@ public abstract class NativeRunTask extends DefaultTask { @Input public abstract ListProperty getRuntimeArgs(); + @Input + @Optional + public abstract MapProperty getEnvironment(); + @Inject protected abstract ExecOperations getExecOperations(); @@ -76,6 +83,12 @@ public void exec() { getExecOperations().exec(spec -> { spec.setExecutable(getImage().get().getAsFile().getAbsolutePath()); spec.args(getRuntimeArgs().get()); + if (getEnvironment().isPresent()) { + Map env = (Map) getEnvironment().get(); + for (Map.Entry entry : env.entrySet()) { + spec.environment(entry.getKey(), entry.getValue()); + } + } }); } } diff --git a/native-gradle-plugin/src/testFixtures/groovy/org/graalvm/buildtools/gradle/fixtures/AbstractFunctionalTest.groovy b/native-gradle-plugin/src/testFixtures/groovy/org/graalvm/buildtools/gradle/fixtures/AbstractFunctionalTest.groovy index 2df145387..a6a4f2e8f 100644 --- a/native-gradle-plugin/src/testFixtures/groovy/org/graalvm/buildtools/gradle/fixtures/AbstractFunctionalTest.groovy +++ b/native-gradle-plugin/src/testFixtures/groovy/org/graalvm/buildtools/gradle/fixtures/AbstractFunctionalTest.groovy @@ -49,6 +49,7 @@ import org.gradle.util.GradleVersion import spock.lang.Specification import spock.lang.TempDir +import java.nio.file.Files import java.nio.file.Path abstract class AbstractFunctionalTest extends Specification { @@ -114,6 +115,11 @@ abstract class AbstractFunctionalTest extends Specification { groovySettingsFile } + protected void withSpacesInProjectDir() { + testDirectory = testDirectory.resolve("with spaces") + Files.createDirectory(testDirectory) + } + protected void withSample(String name) { File sampleDir = new File("../samples/$name") GFileUtils.copyDirectory(sampleDir, testDirectory.toFile()) @@ -231,6 +237,13 @@ abstract class AbstractFunctionalTest extends Specification { } } + void upToDate(String... tasks) { + tasks.each { task -> + contains(task) + assert result.task(task).outcome == TaskOutcome.UP_TO_DATE + } + } + void contains(String... tasks) { tasks.each { task -> assert result.task(task) != null: "Expected to find task $task in the graph but it was missing" diff --git a/native-maven-plugin/build.gradle.kts b/native-maven-plugin/build.gradle.kts index 440b02907..508d24e6d 100644 --- a/native-maven-plugin/build.gradle.kts +++ b/native-maven-plugin/build.gradle.kts @@ -101,6 +101,7 @@ val localRepositoryDir = project.layout.buildDirectory.dir("maven-seeded-repo") tasks { generatePluginDescriptor { + dependsOn(prepareMavenLocalRepo) commonRepository.set(repoDirectory) localRepository.set(localRepositoryDir) } diff --git a/native-maven-plugin/reproducers/issue-144/pom.xml b/native-maven-plugin/reproducers/issue-144/pom.xml index 1ece57a5e..186472575 100644 --- a/native-maven-plugin/reproducers/issue-144/pom.xml +++ b/native-maven-plugin/reproducers/issue-144/pom.xml @@ -56,8 +56,8 @@ 1.8 UTF-8 - 0.9.10 - 0.9.10 + 0.9.11 + 0.9.11 example-app org.graalvm.demo.Application diff --git a/native-maven-plugin/settings.gradle.kts b/native-maven-plugin/settings.gradle.kts index 2dfa2116a..e9bc7eba9 100644 --- a/native-maven-plugin/settings.gradle.kts +++ b/native-maven-plugin/settings.gradle.kts @@ -40,7 +40,8 @@ */ pluginManagement { - includeBuild("../build-logic") + includeBuild("../build-logic/settings-plugins") + includeBuild("../build-logic/common-plugins") includeBuild("build-plugins") } diff --git a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationFunctionalTest.groovy b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationFunctionalTest.groovy index 905c87b58..8d2e40f15 100644 --- a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationFunctionalTest.groovy +++ b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationFunctionalTest.groovy @@ -41,6 +41,8 @@ package org.graalvm.buildtools.maven +import spock.lang.Issue + class JavaApplicationFunctionalTest extends AbstractGraalVMMavenFunctionalTest { def "can build and execute a native image with the Maven plugin"() { withSample("java-application") @@ -63,4 +65,33 @@ class JavaApplicationFunctionalTest extends AbstractGraalVMMavenFunctionalTest { buildSucceeded outputContains "Hello, native!" } + + @Issue("") + def "supports spaces in file names (useArgFile = #argFile)"() { + withSpacesInProjectDir() + withSample("java-application") + + when: + mvn '-Pnative', '-DskipTests', 'package', 'exec:exec@native', "-DuseArgFile=${argFile}" + + then: + buildSucceeded + outputContains "Hello, native!" + + where: + argFile << [true, false] + } + + def "can build and execute a native image with the Maven plugin when the application has a custom packaging type"() { + withSample("java-application-with-custom-packaging") + + when: + mvn 'package', '-Dpackaging=native-image', 'exec:exec@native' + + then: + buildSucceeded + outputContains "ImageClasspath Entry: org.graalvm.buildtools.examples:java-application-with-custom-packaging:native-image:0.1" + outputContains "Hello, native!" + } + } diff --git a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationWithTestsFunctionalTest.groovy b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationWithTestsFunctionalTest.groovy index 0830d9e9c..9e0b15e95 100644 --- a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationWithTestsFunctionalTest.groovy +++ b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationWithTestsFunctionalTest.groovy @@ -123,4 +123,21 @@ class JavaApplicationWithTestsFunctionalTest extends AbstractGraalVMMavenFunctio outputDoesNotContain "containers found" } + @Issue("https://github.com/graalvm/native-build-tools/issues/215") + def "can pass environment variables to native test execution"() { + given: + withSample("java-application-with-tests") + + when: + mvn '-Pnative', '-Ptest-variables', 'test' + + then: + buildSucceeded + outputContains "[junit-platform-native] Running in 'test listener' mode" + def nativeImageExecResult = after("JUnit Platform on Native Image - report") + nativeImageExecResult.contains "TEST_ENV = test-value" + nativeImageExecResult.contains "test-property = test-value" + + } + } diff --git a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeBuildMojo.java b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeBuildMojo.java index ac6b94608..c63ee6d6b 100644 --- a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeBuildMojo.java +++ b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeBuildMojo.java @@ -123,7 +123,7 @@ public void execute() throws MojoExecutionException { for (Artifact dependency : project.getArtifacts()) { addClasspath(dependency); } - addClasspath(project.getArtifact()); + addClasspath(project.getArtifact(), project.getPackaging()); } String classpathStr = imageClasspath.stream().map(Path::toString).collect(Collectors.joining(File.pathSeparator)); @@ -156,7 +156,11 @@ public void execute() throws MojoExecutionException { } private void addClasspath(Artifact artifact) throws MojoExecutionException { - if (!"jar".equals(artifact.getType())) { + addClasspath(artifact, "jar"); + } + + private void addClasspath(Artifact artifact, String artifactType) throws MojoExecutionException { + if (!artifactType.equals(artifact.getType())) { getLog().warn("Ignoring non-jar type ImageClasspath Entry " + artifact); return; } diff --git a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeTestMojo.java b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeTestMojo.java index 5439f90f9..70508e656 100644 --- a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeTestMojo.java +++ b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeTestMojo.java @@ -44,13 +44,16 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DependencyResolutionRequiredException; import org.apache.maven.model.FileSet; +import org.apache.maven.model.Plugin; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; +import org.codehaus.plexus.util.xml.Xpp3Dom; import org.graalvm.buildtools.Utils; +import org.graalvm.buildtools.utils.NativeImageUtils; import org.graalvm.junit.platform.JUnitPlatformFeature; import java.io.File; @@ -63,7 +66,9 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -90,12 +95,19 @@ public class NativeTestMojo extends AbstractNativeMojo { @Parameter(property = "project.build.directory") private File buildDirectory; + @Parameter(property = "environmentVariables") + private Map environment; + + @Parameter(property = "systemPropertyVariables") + private Map systemProperties; + @Override public void execute() throws MojoExecutionException, MojoFailureException { if (skipTests || skipNativeTests) { logger.info("Skipping native-image tests (parameter 'skipTests' or 'skipNativeTests' is true)."); return; } + configureEnvironment(); if (!hasTests()) { return; } @@ -123,6 +135,37 @@ public void execute() throws MojoExecutionException, MojoFailureException { runTests(targetFolder); } + private void configureEnvironment() { + // inherit from surefire mojo + Plugin plugin = project.getPlugin("org.apache.maven.plugins:maven-surefire-plugin"); + if (plugin != null) { + Object configuration = plugin.getConfiguration(); + if (configuration instanceof Xpp3Dom) { + Xpp3Dom dom = (Xpp3Dom) configuration; + Xpp3Dom environmentVariables = dom.getChild("environmentVariables"); + if (environmentVariables != null) { + Xpp3Dom[] children = environmentVariables.getChildren(); + if (environment == null) { + environment = new HashMap<>(children.length); + } + for (Xpp3Dom child : children) { + environment.put(child.getName(), child.getValue()); + } + } + Xpp3Dom systemProps = dom.getChild("systemPropertyVariables"); + if (systemProps != null) { + Xpp3Dom[] children = systemProps.getChildren(); + if (systemProperties == null) { + systemProperties = new HashMap<>(children.length); + } + for (Xpp3Dom child : children) { + systemProperties.put(child.getName(), child.getValue()); + } + } + } + } + } + private boolean hasTests() { Path testOutputPath = Paths.get(project.getBuild().getTestOutputDirectory()); if (Files.exists(testOutputPath) && Files.isDirectory(testOutputPath)) { @@ -139,7 +182,6 @@ private void buildImage(String classpath, Path targetFolder) throws MojoExecutio Path nativeImageExecutable = Utils.getNativeImage(); List command = new ArrayList<>(Arrays.asList( - nativeImageExecutable.toString(), "-cp", classpath, "--features=org.graalvm.junit.platform.JUnitPlatformFeature", "-Djunit.platform.listeners.uid.tracking.output.dir=" + NativeExtension.testIdsDirectory(buildDirectory.getAbsolutePath()), @@ -151,13 +193,14 @@ private void buildImage(String classpath, Path targetFolder) throws MojoExecutio command.addAll(buildArgs); } - command.add("org.graalvm.junit.platform.NativeImageJUnitLauncher"); - try { - ProcessBuilder processBuilder = new ProcessBuilder(command); + ProcessBuilder processBuilder = new ProcessBuilder(nativeImageExecutable.toString()); + prepareVariables(processBuilder, command); + command = NativeImageUtils.convertToArgsFile(command); + processBuilder.command().addAll(command); + processBuilder.command().add("org.graalvm.junit.platform.NativeImageJUnitLauncher"); processBuilder.directory(new File(project.getBuild().getDirectory())); processBuilder.inheritIO(); - String commandString = String.join(" ", processBuilder.command()); getLog().info("Executing: " + commandString); Process imageBuildProcess = processBuilder.start(); @@ -175,10 +218,13 @@ private void runTests(Path targetFolder) throws MojoExecutionException { try { ProcessBuilder processBuilder = new ProcessBuilder( - targetFolder.resolve(NATIVE_TESTS_EXE).toAbsolutePath().toString(), - "--xml-output-dir", xmlLocation.toString()); + targetFolder.resolve(NATIVE_TESTS_EXE).toAbsolutePath().toString()); processBuilder.inheritIO(); - + List command = new ArrayList<>(); + prepareVariables(processBuilder, command); + command.add("--xml-output-dir"); + command.add(xmlLocation.toString()); + processBuilder.command().addAll(command); String commandString = String.join(" ", processBuilder.command()); getLog().info("Executing: " + commandString); Process imageBuildProcess = processBuilder.start(); @@ -190,6 +236,17 @@ private void runTests(Path targetFolder) throws MojoExecutionException { } } + private void prepareVariables(ProcessBuilder processBuilder, List command) { + if (environment != null) { + processBuilder.environment().putAll(environment); + } + if (systemProperties != null) { + for (Map.Entry entry : systemProperties.entrySet()) { + command.add("-D" + entry.getKey() + "=" + entry.getValue()); + } + } + } + private String getClassPath() throws MojoFailureException { if (classpath != null && !classpath.isEmpty()) { return String.join(File.pathSeparator, classpath); diff --git a/native-maven-plugin/src/testFixtures/groovy/org/graalvm/buildtools/maven/AbstractGraalVMMavenFunctionalTest.groovy b/native-maven-plugin/src/testFixtures/groovy/org/graalvm/buildtools/maven/AbstractGraalVMMavenFunctionalTest.groovy index 99eb80d1b..57d3cc7ef 100644 --- a/native-maven-plugin/src/testFixtures/groovy/org/graalvm/buildtools/maven/AbstractGraalVMMavenFunctionalTest.groovy +++ b/native-maven-plugin/src/testFixtures/groovy/org/graalvm/buildtools/maven/AbstractGraalVMMavenFunctionalTest.groovy @@ -72,6 +72,11 @@ abstract class AbstractGraalVMMavenFunctionalTest extends Specification { executor.debug = true } + protected void withSpacesInProjectDir() { + testDirectory = testDirectory.resolve("with spaces") + Files.createDirectory(testDirectory) + } + protected void withReproducer(String name) { File sampleDir = new File("reproducers/$name") copySample(sampleDir.toPath(), testDirectory) @@ -134,6 +139,11 @@ abstract class AbstractGraalVMMavenFunctionalTest extends Specification { normalizeString(result.stdOut).contains(normalizeString(text)) } + String after(String text) { + def out = normalizeString(result.stdOut) + out.substring(out.indexOf(normalizeString(text))) + } + boolean outputDoesNotContain(String text) { !normalizeString(result.stdOut).contains(normalizeString(text)) } @@ -145,4 +155,14 @@ abstract class AbstractGraalVMMavenFunctionalTest extends Specification { private static String normalizeString(String input) { input.replace("\r\n", "\n") } + + String getArgFileContents() { + result.stdOut.lines().filter { + it.contains('Executing:') && it.contains('bin/native-image') + }.map { + new File(it.substring(it.lastIndexOf('@') + 1)) + }.findFirst() + .map { it.text } + .orElse("") + } } diff --git a/samples/java-application-with-custom-packaging/pom.xml b/samples/java-application-with-custom-packaging/pom.xml new file mode 100644 index 000000000..3a0deee4d --- /dev/null +++ b/samples/java-application-with-custom-packaging/pom.xml @@ -0,0 +1,167 @@ + + + + + 4.0.0 + org.graalvm.buildtools.examples + java-application-with-custom-packaging + 0.1 + ${packaging} + + + io.micronaut + micronaut-parent + 3.3.4 + + + + jar + 11 + 11 + 3.3.4 + org.graalvm.demo.Application + netty + 0.9.11-SNAPSHOT + + + + + central + https://repo.maven.apache.org/maven2 + + + + + + io.micronaut + micronaut-inject + compile + + + io.micronaut + micronaut-validation + compile + + + io.micronaut + micronaut-http-client + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + io.micronaut.test + micronaut-test-junit5 + test + + + info.picocli + picocli + compile + + + io.micronaut + micronaut-jackson-databind + compile + + + io.micronaut + micronaut-runtime + compile + + + io.micronaut.picocli + micronaut-picocli + compile + + + jakarta.annotation + jakarta.annotation-api + compile + + + ch.qos.logback + logback-classic + runtime + + + + + + + io.micronaut.build + micronaut-maven-plugin + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + + info.picocli + picocli-codegen + ${picocli.version} + + + + -Amicronaut.processing.group=org.graalvm.demo + -Amicronaut.processing.module=demo + + + + + + + diff --git a/samples/java-application-with-custom-packaging/src/main/java/org/graalvm/demo/Application.java b/samples/java-application-with-custom-packaging/src/main/java/org/graalvm/demo/Application.java new file mode 100644 index 000000000..81e95b73d --- /dev/null +++ b/samples/java-application-with-custom-packaging/src/main/java/org/graalvm/demo/Application.java @@ -0,0 +1,16 @@ +package org.graalvm.demo; + +import io.micronaut.configuration.picocli.PicocliRunner; +import picocli.CommandLine.Command; + +@Command(name = "demo", description = "...", mixinStandardHelpOptions = true) +public class Application implements Runnable { + + public static void main(String[] args) { + PicocliRunner.run(Application.class, args); + } + + public void run() { + System.out.println("Hello, native!"); + } +} diff --git a/samples/java-application-with-custom-packaging/src/main/resources/application.yml b/samples/java-application-with-custom-packaging/src/main/resources/application.yml new file mode 100644 index 000000000..91ee466e3 --- /dev/null +++ b/samples/java-application-with-custom-packaging/src/main/resources/application.yml @@ -0,0 +1,3 @@ +micronaut: + application: + name: java-application-with-custom-packaging diff --git a/samples/java-application-with-custom-packaging/src/main/resources/logback.xml b/samples/java-application-with-custom-packaging/src/main/resources/logback.xml new file mode 100644 index 000000000..214d9d904 --- /dev/null +++ b/samples/java-application-with-custom-packaging/src/main/resources/logback.xml @@ -0,0 +1,15 @@ + + + + true + + + %cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n + + + + + + + \ No newline at end of file diff --git a/samples/java-application-with-custom-tests/gradle.properties b/samples/java-application-with-custom-tests/gradle.properties index af2d4c275..e7aa7b8c8 100644 --- a/samples/java-application-with-custom-tests/gradle.properties +++ b/samples/java-application-with-custom-tests/gradle.properties @@ -1,3 +1,3 @@ -native.gradle.plugin.version = 0.9.10 +native.gradle.plugin.version = 0.9.11 junit.jupiter.version = 5.8.1 junit.platform.version = 1.8.1 diff --git a/samples/java-application-with-extra-sourceset/gradle.properties b/samples/java-application-with-extra-sourceset/gradle.properties index af2d4c275..e7aa7b8c8 100644 --- a/samples/java-application-with-extra-sourceset/gradle.properties +++ b/samples/java-application-with-extra-sourceset/gradle.properties @@ -1,3 +1,3 @@ -native.gradle.plugin.version = 0.9.10 +native.gradle.plugin.version = 0.9.11 junit.jupiter.version = 5.8.1 junit.platform.version = 1.8.1 diff --git a/samples/java-application-with-reflection/gradle.properties b/samples/java-application-with-reflection/gradle.properties index af2d4c275..e7aa7b8c8 100644 --- a/samples/java-application-with-reflection/gradle.properties +++ b/samples/java-application-with-reflection/gradle.properties @@ -1,3 +1,3 @@ -native.gradle.plugin.version = 0.9.10 +native.gradle.plugin.version = 0.9.11 junit.jupiter.version = 5.8.1 junit.platform.version = 1.8.1 diff --git a/samples/java-application-with-reflection/pom.xml b/samples/java-application-with-reflection/pom.xml index b4f9de150..a684225d5 100644 --- a/samples/java-application-with-reflection/pom.xml +++ b/samples/java-application-with-reflection/pom.xml @@ -52,8 +52,8 @@ 1.8 UTF-8 5.8.1 - 0.9.10 - 0.9.10 + 0.9.11 + 0.9.11 example-app org.graalvm.demo.Application diff --git a/samples/java-application-with-resources/gradle.properties b/samples/java-application-with-resources/gradle.properties index af2d4c275..e7aa7b8c8 100644 --- a/samples/java-application-with-resources/gradle.properties +++ b/samples/java-application-with-resources/gradle.properties @@ -1,3 +1,3 @@ -native.gradle.plugin.version = 0.9.10 +native.gradle.plugin.version = 0.9.11 junit.jupiter.version = 5.8.1 junit.platform.version = 1.8.1 diff --git a/samples/java-application-with-resources/pom.xml b/samples/java-application-with-resources/pom.xml index 3e2d57cc0..4fd4f54db 100644 --- a/samples/java-application-with-resources/pom.xml +++ b/samples/java-application-with-resources/pom.xml @@ -51,9 +51,9 @@ 1.8 UTF-8 - 0.9.10 + 0.9.11 5.8.1 - 0.9.10 + 0.9.11 example-app org.graalvm.demo.Application diff --git a/samples/java-application-with-tests/gradle.properties b/samples/java-application-with-tests/gradle.properties index af2d4c275..e7aa7b8c8 100644 --- a/samples/java-application-with-tests/gradle.properties +++ b/samples/java-application-with-tests/gradle.properties @@ -1,3 +1,3 @@ -native.gradle.plugin.version = 0.9.10 +native.gradle.plugin.version = 0.9.11 junit.jupiter.version = 5.8.1 junit.platform.version = 1.8.1 diff --git a/samples/java-application-with-tests/pom.xml b/samples/java-application-with-tests/pom.xml index 2915683bd..5abb87abd 100644 --- a/samples/java-application-with-tests/pom.xml +++ b/samples/java-application-with-tests/pom.xml @@ -52,8 +52,8 @@ 1.8 UTF-8 5.8.1 - 0.9.10 - 0.9.10 + 0.9.11 + 0.9.11 example-app org.graalvm.demo.Application @@ -83,7 +83,7 @@ native-maven-plugin ${native.maven.plugin.version} true - + test-native @@ -216,6 +216,26 @@ + + test-variables + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + test-value + + + test-value + + + + + + diff --git a/samples/java-application-with-tests/src/main/java/org/graalvm/demo/Calculator.java b/samples/java-application-with-tests/src/main/java/org/graalvm/demo/Calculator.java index 41e072c9b..b1facd323 100644 --- a/samples/java-application-with-tests/src/main/java/org/graalvm/demo/Calculator.java +++ b/samples/java-application-with-tests/src/main/java/org/graalvm/demo/Calculator.java @@ -2,6 +2,15 @@ public class Calculator { + public Calculator() { + if (System.getenv("TEST_ENV") != null) { + System.out.println("TEST_ENV = " + System.getenv("TEST_ENV")); + } + if (System.getProperty("test-property") != null) { + System.out.println("test-property = " + System.getProperty("test-property")); + } + } + public int add(int a, int b) { return a + b; } diff --git a/samples/java-application/build.gradle b/samples/java-application/build.gradle index 4a2400ff1..1953b0025 100644 --- a/samples/java-application/build.gradle +++ b/samples/java-application/build.gradle @@ -51,3 +51,7 @@ application { repositories { mavenCentral() } + +dependencies { + implementation 'org.apache.commons:commons-lang3:3.8.1' +} diff --git a/samples/java-application/gradle.properties b/samples/java-application/gradle.properties index af2d4c275..e7aa7b8c8 100644 --- a/samples/java-application/gradle.properties +++ b/samples/java-application/gradle.properties @@ -1,3 +1,3 @@ -native.gradle.plugin.version = 0.9.10 +native.gradle.plugin.version = 0.9.11 junit.jupiter.version = 5.8.1 junit.platform.version = 1.8.1 diff --git a/samples/java-application/pom.xml b/samples/java-application/pom.xml index 4ae6f56bd..4cf36901e 100644 --- a/samples/java-application/pom.xml +++ b/samples/java-application/pom.xml @@ -51,12 +51,20 @@ 1.8 UTF-8 - 0.9.10 - 0.9.10 + 0.9.11 + 0.9.11 example-app org.graalvm.demo.Application + + + org.apache.commons + commons-lang3 + 3.8.1 + + + native diff --git a/samples/java-library/gradle.properties b/samples/java-library/gradle.properties index af2d4c275..e7aa7b8c8 100644 --- a/samples/java-library/gradle.properties +++ b/samples/java-library/gradle.properties @@ -1,3 +1,3 @@ -native.gradle.plugin.version = 0.9.10 +native.gradle.plugin.version = 0.9.11 junit.jupiter.version = 5.8.1 junit.platform.version = 1.8.1 diff --git a/samples/java-library/pom.xml b/samples/java-library/pom.xml index 24b5acd8c..01a17a513 100644 --- a/samples/java-library/pom.xml +++ b/samples/java-library/pom.xml @@ -51,8 +51,8 @@ 1.8 UTF-8 - 0.9.10 - 0.9.10 + 0.9.11 + 0.9.11 java-library diff --git a/samples/kotlin-application-with-tests/gradle.properties b/samples/kotlin-application-with-tests/gradle.properties index af2d4c275..e7aa7b8c8 100644 --- a/samples/kotlin-application-with-tests/gradle.properties +++ b/samples/kotlin-application-with-tests/gradle.properties @@ -1,3 +1,3 @@ -native.gradle.plugin.version = 0.9.10 +native.gradle.plugin.version = 0.9.11 junit.jupiter.version = 5.8.1 junit.platform.version = 1.8.1 diff --git a/samples/multi-project-with-tests/gradle.properties b/samples/multi-project-with-tests/gradle.properties index af2d4c275..e7aa7b8c8 100644 --- a/samples/multi-project-with-tests/gradle.properties +++ b/samples/multi-project-with-tests/gradle.properties @@ -1,3 +1,3 @@ -native.gradle.plugin.version = 0.9.10 +native.gradle.plugin.version = 0.9.11 junit.jupiter.version = 5.8.1 junit.platform.version = 1.8.1 diff --git a/samples/native-config-integration/build.gradle b/samples/native-config-integration/build.gradle new file mode 100644 index 000000000..6a4eda85c --- /dev/null +++ b/samples/native-config-integration/build.gradle @@ -0,0 +1,102 @@ +/* + * 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. + */ + +plugins { + id 'application' + id 'org.graalvm.buildtools.native' +} + +repositories { + mavenCentral() +} + +application { + mainClass.set('org.graalvm.example.Application') +} + +def junitVersion = providers.gradleProperty('junit.jupiter.version') + .forUseAtConfigurationTime() + .get() + +dependencies { + implementation("org.graalvm.internal:library-with-reflection:1.5") + + testImplementation(platform("org.junit:junit-bom:${junitVersion}")) + testImplementation('org.junit.jupiter:junit-jupiter') +} + +tasks.withType(Test).configureEach { + useJUnitPlatform() +} + +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 + runtimeArgs.add("-DmessageClass=org.graalvm.internal.reflect.Message") + } +} + +tasks.register("configZip", Zip) { + destinationDirectory = project.layout.projectDirectory + from(file("config-directory")) + archiveName = 'config-directory.zip' +} + +tasks.register("configTarGz", Tar) { + destinationDirectory = project.layout.projectDirectory + compression = Compression.GZIP + from(file("config-directory")) + archiveName = 'config-directory.tar.gz' +} + +tasks.register("configTarBz2", Tar) { + destinationDirectory = project.layout.projectDirectory + compression = Compression.BZIP2 + from(file("config-directory")) + archiveName = 'config-directory.tar.bz2' +} diff --git a/samples/native-config-integration/config-directory/index.json b/samples/native-config-integration/config-directory/index.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/samples/native-config-integration/config-directory/index.json @@ -0,0 +1 @@ +[] diff --git a/samples/native-config-integration/config-directory/org/graalvm/internal/library-with-reflection/1/reflect-config.json b/samples/native-config-integration/config-directory/org/graalvm/internal/library-with-reflection/1/reflect-config.json new file mode 100644 index 000000000..b4de3b1f5 --- /dev/null +++ b/samples/native-config-integration/config-directory/org/graalvm/internal/library-with-reflection/1/reflect-config.json @@ -0,0 +1,7 @@ +[ + { + "name": "org.graalvm.internal.reflect.Message", + "allDeclaredFields": true, + "allDeclaredMethods": true + } +] diff --git a/samples/native-config-integration/config-directory/org/graalvm/internal/library-with-reflection/index.json b/samples/native-config-integration/config-directory/org/graalvm/internal/library-with-reflection/index.json new file mode 100644 index 000000000..0e78c26de --- /dev/null +++ b/samples/native-config-integration/config-directory/org/graalvm/internal/library-with-reflection/index.json @@ -0,0 +1,13 @@ +[ + { + "module": "org.graalvm.internal:library-with-reflection", + "tested-versions": [ + "1.0", + "1.1", + "1.2", + "1.3" + ], + "metadata-version": "1", + "latest": true + } +] diff --git a/samples/native-config-integration/gradle.properties b/samples/native-config-integration/gradle.properties new file mode 100644 index 000000000..e7aa7b8c8 --- /dev/null +++ b/samples/native-config-integration/gradle.properties @@ -0,0 +1,3 @@ +native.gradle.plugin.version = 0.9.11 +junit.jupiter.version = 5.8.1 +junit.platform.version = 1.8.1 diff --git a/samples/native-config-integration/settings.gradle b/samples/native-config-integration/settings.gradle new file mode 100644 index 000000000..32a2f35ac --- /dev/null +++ b/samples/native-config-integration/settings.gradle @@ -0,0 +1,52 @@ +/* + * 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. + */ + +pluginManagement { + plugins { + id 'org.graalvm.buildtools.native' version getProperty('native.gradle.plugin.version') + } + repositories { + mavenCentral() + gradlePluginPortal() + } +} + +rootProject.name = 'native-config-integration' diff --git a/samples/native-config-integration/src/main/java/org/graalvm/example/Application.java b/samples/native-config-integration/src/main/java/org/graalvm/example/Application.java new file mode 100644 index 000000000..75fee8112 --- /dev/null +++ b/samples/native-config-integration/src/main/java/org/graalvm/example/Application.java @@ -0,0 +1,10 @@ +package org.graalvm.example; + +import org.graalvm.internal.reflect.Greeter; + +public class Application { + public static void main(String[] args) { + Greeter greeter = new Greeter(); + greeter.greet(); + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 4f198c5be..4edd83d39 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -39,10 +39,16 @@ * SOFTWARE. */ +pluginManagement { + includeBuild("build-logic/settings-plugins") + includeBuild("build-logic/aggregator") +} + rootProject.name = "native-build-tools" includeBuild("common/junit-platform-native") includeBuild("common/utils") +includeBuild("common/jvm-reachability-metadata") includeBuild("native-gradle-plugin") includeBuild("native-maven-plugin") includeBuild("docs") diff --git a/test-support/library-with-reflection/build.gradle.kts b/test-support/library-with-reflection/build.gradle.kts new file mode 100644 index 000000000..0e0ced479 --- /dev/null +++ b/test-support/library-with-reflection/build.gradle.kts @@ -0,0 +1,21 @@ +plugins { + `java-library` + id("org.graalvm.build.publishing") +} + +group = "org.graalvm.internal" +version = "1.5" + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(8)) + } +} + +publishing { + publications { + create("maven") { + from(components["java"]) + } + } +} diff --git a/test-support/library-with-reflection/settings.gradle.kts b/test-support/library-with-reflection/settings.gradle.kts new file mode 100644 index 000000000..bd8668d0a --- /dev/null +++ b/test-support/library-with-reflection/settings.gradle.kts @@ -0,0 +1,5 @@ +pluginManagement { + includeBuild("../../build-logic/common-plugins") +} + +rootProject.name = "library-with-reflection" diff --git a/test-support/library-with-reflection/src/main/java/org/graalvm/internal/reflect/Greeter.java b/test-support/library-with-reflection/src/main/java/org/graalvm/internal/reflect/Greeter.java new file mode 100644 index 000000000..073ae2e5e --- /dev/null +++ b/test-support/library-with-reflection/src/main/java/org/graalvm/internal/reflect/Greeter.java @@ -0,0 +1,52 @@ +/* + * Copyright 2003-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.graalvm.internal.reflect; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Optional; + +public class Greeter { + private String message; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public void greet() { + System.out.println(Optional.ofNullable(message).orElseGet(() -> { + String msg = defaultMessage(); + if (msg == null) { + return "Reflection failed"; + } + return msg; + })); + } + + private String defaultMessage() { + Method method; + try { + method = Class.forName(System.getProperty("messageClass")).getDeclaredMethod("getDefault"); + return (String) method.invoke(null); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | ClassNotFoundException e) { + return null; + } + } +} diff --git a/test-support/library-with-reflection/src/main/java/org/graalvm/internal/reflect/Message.java b/test-support/library-with-reflection/src/main/java/org/graalvm/internal/reflect/Message.java new file mode 100644 index 000000000..dcc89ba98 --- /dev/null +++ b/test-support/library-with-reflection/src/main/java/org/graalvm/internal/reflect/Message.java @@ -0,0 +1,22 @@ +/* + * Copyright 2003-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.graalvm.internal.reflect; + +public class Message { + public static String getDefault() { + return "Hello, from reflection!"; + } +}