From c315a0ecefecfdb18b2cb4277cea7ab06f4022c4 Mon Sep 17 00:00:00 2001 From: Teymur Babayev Date: Thu, 2 Oct 2025 17:05:21 +0200 Subject: [PATCH] Manually enforce platform constraints for conditional dependencies in QuarkusComponentVariants Addresses #49743 --- ...ApplicationDeploymentClasspathBuilder.java | 35 ++++- .../gradle/dependency/PlatformSpec.java | 50 ++++++ .../dependency/QuarkusComponentVariants.java | 67 +++++++- .../consumer-project/gradle.properties | 3 + .../runner-enforced/build.gradle | 25 +++ .../src/main/java/org/acme/HelloResource.java | 22 +++ .../runner-excluded-1/build.gradle | 31 ++++ .../src/main/java/org/acme/HelloResource.java | 22 +++ .../runner-excluded-2/build.gradle | 25 +++ .../src/main/java/org/acme/HelloResource.java | 22 +++ .../consumer-project/runner/build.gradle | 24 +++ .../src/main/java/org/acme/HelloResource.java | 22 +++ .../consumer-project/settings.gradle | 17 ++ .../dev-mode-only-lib-940/build.gradle | 32 ++++ .../src/main/resources/META-INF/beans.xml | 0 .../dev-mode-only-lib-990/build.gradle | 32 ++++ .../src/main/resources/META-INF/beans.xml | 0 .../other-deps/ext-a/deployment/build.gradle | 31 ++++ .../enforcing/deps/QuarkusExtProcessor.java | 16 ++ .../other-deps/ext-a/runtime/build.gradle | 35 +++++ .../other-deps/gradle.properties | 3 + .../other-deps/settings.gradle | 20 +++ .../other-deps/simple-dep/build.gradle | 28 ++++ .../src/main/resources/META-INF/beans.xml | 0 .../test-bom-with-exclusion/build.gradle | 8 + .../test-bom-with-exclusion/pom.xml | 28 ++++ .../other-deps/test-bom/build.gradle | 29 ++++ ...forcingPlatformForConditionalDepsTest.java | 146 ++++++++++++++++++ .../TestCompositeBuildWithExtensionsTest.java | 10 +- .../gradle/TestFixtureMultiModuleTest.java | 19 +-- .../gradle/util/AppModelDeserializer.java | 26 ++++ 31 files changed, 786 insertions(+), 42 deletions(-) create mode 100644 devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/PlatformSpec.java create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/gradle.properties create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-enforced/build.gradle create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-enforced/src/main/java/org/acme/HelloResource.java create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-1/build.gradle create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-1/src/main/java/org/acme/HelloResource.java create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-2/build.gradle create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-2/src/main/java/org/acme/HelloResource.java create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner/build.gradle create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner/src/main/java/org/acme/HelloResource.java create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/settings.gradle create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-940/build.gradle create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-940/src/main/resources/META-INF/beans.xml create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-990/build.gradle create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-990/src/main/resources/META-INF/beans.xml create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/ext-a/deployment/build.gradle create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/ext-a/deployment/src/main/java/org/enforcing/deps/QuarkusExtProcessor.java create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/ext-a/runtime/build.gradle create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/gradle.properties create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/settings.gradle create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/simple-dep/build.gradle create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/simple-dep/src/main/resources/META-INF/beans.xml create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/test-bom-with-exclusion/build.gradle create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/test-bom-with-exclusion/pom.xml create mode 100644 integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/test-bom/build.gradle create mode 100644 integration-tests/gradle/src/test/java/io/quarkus/gradle/EnforcingPlatformForConditionalDepsTest.java create mode 100644 integration-tests/gradle/src/test/java/io/quarkus/gradle/util/AppModelDeserializer.java diff --git a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/ApplicationDeploymentClasspathBuilder.java b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/ApplicationDeploymentClasspathBuilder.java index bd51b464de299..cc3173179303c 100644 --- a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/ApplicationDeploymentClasspathBuilder.java +++ b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/ApplicationDeploymentClasspathBuilder.java @@ -29,6 +29,7 @@ import org.gradle.api.internal.tasks.TaskDependencyFactory; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.Property; import io.quarkus.bootstrap.BootstrapConstants; import io.quarkus.bootstrap.model.PlatformImports; @@ -38,6 +39,7 @@ import io.quarkus.gradle.tooling.dependency.DependencyUtils; import io.quarkus.gradle.tooling.dependency.ExtensionDependency; import io.quarkus.maven.dependency.ArtifactCoords; +import io.quarkus.maven.dependency.ArtifactKey; import io.quarkus.runtime.LaunchMode; public class ApplicationDeploymentClasspathBuilder { @@ -93,13 +95,14 @@ public static void initConfigurations(Project project) { final ConfigurationContainer configContainer = project.getConfigurations(); // Custom configuration for dev mode - configContainer.register(ToolingUtils.DEV_MODE_CONFIGURATION_NAME, config -> { - config.extendsFrom(configContainer.getByName(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME)); - config.setCanBeConsumed(false); - if (!isDisableComponentVariants(project)) { - QuarkusComponentVariants.setConditionalAttributes(config, project, LaunchMode.DEVELOPMENT); - } - }); + configContainer + .register(ToolingUtils.DEV_MODE_CONFIGURATION_NAME, config -> { + config.extendsFrom(configContainer.getByName(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME)); + config.setCanBeConsumed(false); + if (!isDisableComponentVariants(project)) { + QuarkusComponentVariants.setConditionalAttributes(config, project, LaunchMode.DEVELOPMENT); + } + }); // Base runtime configurations for every launch mode configContainer @@ -178,6 +181,7 @@ private static Configuration[] getOriginalRuntimeClasspaths(Project project, Lau private final String platformImportName; private final List platformDataDeps = new ArrayList<>(); + private final Map platformConstraints = new HashMap<>(); public ApplicationDeploymentClasspathBuilder(Project project, LaunchMode mode, TaskDependencyFactory taskDependencyFactory) { @@ -239,6 +243,13 @@ private void setUpPlatformConfiguration() { break; } } + } else { + ArtifactKey artifactKey = ArtifactKey.ga(d.getTarget().getGroup(), name); + platformConstraints.computeIfAbsent(artifactKey, + k -> new PlatformSpec.Constraint( + d.getTarget().getGroup(), + name, + d.getTarget().getVersion())); } }); }); @@ -276,6 +287,11 @@ private List resolvePlatformDependencies() { return platformDataDeps; } + private PlatformSpec resolvePlatformSpec() { + getPlatformConfiguration().resolve(); + return new PlatformSpec(platformConstraints, getPlatformConfiguration().getExcludeRules()); + } + private void setUpRuntimeConfiguration() { if (!project.getConfigurations().getNames().contains(this.runtimeConfigurationName)) { final String baseConfig; @@ -283,7 +299,10 @@ private void setUpRuntimeConfiguration() { if (disableComponentVariants) { baseConfig = ApplicationDeploymentClasspathBuilder.getBaseRuntimeConfigName(mode); } else { - QuarkusComponentVariants.addVariants(project, mode); + Property platformSpecProperty = project.getObjects() + .property(PlatformSpec.class); + QuarkusComponentVariants.addVariants(project, mode, + platformSpecProperty.value(project.provider(this::resolvePlatformSpec))); baseConfig = QuarkusComponentVariants.getConditionalConfigurationName(mode); } project.getConfigurations().register(this.runtimeConfigurationName, configuration -> { diff --git a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/PlatformSpec.java b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/PlatformSpec.java new file mode 100644 index 0000000000000..6365bb1266c48 --- /dev/null +++ b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/PlatformSpec.java @@ -0,0 +1,50 @@ +package io.quarkus.gradle.dependency; + +import java.util.Map; +import java.util.Set; + +import org.gradle.api.artifacts.ExcludeRule; + +import io.quarkus.maven.dependency.ArtifactKey; + +class PlatformSpec { + private final Map constraints; + private final Set exclusions; + + public PlatformSpec(Map constraints, Set exclusions) { + this.constraints = constraints; + this.exclusions = exclusions; + } + + public Map getConstraints() { + return constraints; + } + + public Set getExclusions() { + return exclusions; + } + + static class Constraint { + private final String groupId; + private final String artifactId; + private final String version; + + public Constraint(String groupId, String artifactId, String version) { + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + } + + public String getGroupId() { + return groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public String getVersion() { + return version; + } + } +} \ No newline at end of file diff --git a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/QuarkusComponentVariants.java b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/QuarkusComponentVariants.java index 16ced7ae08569..d11c520ea2cc4 100644 --- a/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/QuarkusComponentVariants.java +++ b/devtools/gradle/gradle-model/src/main/java/io/quarkus/gradle/dependency/QuarkusComponentVariants.java @@ -8,6 +8,8 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; @@ -28,6 +30,7 @@ import org.gradle.api.attributes.java.TargetJvmEnvironment; import org.gradle.api.model.ObjectFactory; import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.Property; import io.quarkus.gradle.tooling.dependency.DependencyUtils; import io.quarkus.gradle.tooling.dependency.ExtensionDependency; @@ -169,12 +172,14 @@ public static void setCommonAttributes(AttributeContainer attrs, ObjectFactory o * @param project project * @param mode launch mode */ - public static void addVariants(Project project, LaunchMode mode) { - new QuarkusComponentVariants(project, mode).configureAndAddVariants(); + public static void addVariants(Project project, LaunchMode mode, + Property platformSpecProperty) { + new QuarkusComponentVariants(project, mode, platformSpecProperty).configureAndAddVariants(); } private final Attribute quarkusDepAttr; private final Project project; + private final Property platformSpecProperty; private final Map processedDeps = new HashMap<>(); private final Map allConditionalDeps = new HashMap<>(); private final List dependencyVariantQueue = new ArrayList<>(); @@ -182,9 +187,11 @@ public static void addVariants(Project project, LaunchMode mode) { private final LaunchMode mode; private final AtomicInteger configCopyCounter = new AtomicInteger(); - private QuarkusComponentVariants(Project project, LaunchMode mode) { + private QuarkusComponentVariants(Project project, LaunchMode mode, + Property platformSpecProperty) { this.project = project; this.mode = mode; + this.platformSpecProperty = platformSpecProperty; this.quarkusDepAttr = getConditionalDependencyAttribute(project.getName(), mode); project.getDependencies().getAttributesSchema().attribute(quarkusDepAttr); project.getDependencies().getAttributesSchema().attribute(getDeploymentDependencyAttribute(project.getName(), mode)); @@ -407,7 +414,10 @@ private void processDependency(ProcessedDependency parent, } private void queueConditionalDependency(ProcessedDependency parent, Dependency dep) { - dependencyVariantQueue.add(new ConditionalDependencyVariant(parent.extension, getOrCreateConditionalDep(dep))); + var conditionalDep = getOrCreateConditionalDep(dep); + if (conditionalDep != null) { + dependencyVariantQueue.add(new ConditionalDependencyVariant(parent.extension, conditionalDep)); + } } private ConditionalDependency getOrCreateConditionalDep(Dependency dep) { @@ -417,7 +427,7 @@ private ConditionalDependency getOrCreateConditionalDep(Dependency dep) { } private ResolvedArtifact tryResolvingRelocationArtifact(Dependency dep) { - final Configuration configForRelocated = project.getConfigurations().detachedConfiguration(dep).setTransitive(true); + final Configuration configForRelocated = getDetachedWithExclusions(dep).setTransitive(true); setConditionalAttributes(configForRelocated, project, mode); var firstLevelDeps = configForRelocated.getResolvedConfiguration().getFirstLevelModuleDependencies(); @@ -447,8 +457,10 @@ private ResolvedArtifact tryResolvingRelocationArtifact(Dependency dep) { return artifact; } - private ConditionalDependency newConditionalDep(Dependency dep) { - final Configuration config = project.getConfigurations().detachedConfiguration(dep).setTransitive(false); + private ConditionalDependency newConditionalDep(Dependency originalDep) { + var dep = getConstrainedDep(originalDep); + final Configuration config = getDetachedWithExclusions(dep).setTransitive(false); + setConditionalAttributes(config, project, mode); ResolvedArtifact resolvedArtifact = null; @@ -464,6 +476,11 @@ private ConditionalDependency newConditionalDep(Dependency dep) { } if (resolvedArtifact == null) { + // check if that's due to exclude rules, and if yes, ignore + if (isExplicitlyExcluded(dep)) { + project.getLogger().info("Conditional dependency {} ignored due to exclusion rule", dep); + return null; + } throw new RuntimeException(dep + " did not resolve to any artifacts"); } @@ -474,6 +491,42 @@ private ConditionalDependency newConditionalDep(Dependency dep) { } + private boolean isExplicitlyExcluded(Dependency dep) { + return platformSpecProperty.get().getExclusions().stream().anyMatch(rule -> { + // Do not abort if the group is null, allow the next comparison to take place + if (rule.getGroup() != null && !Objects.equals(rule.getGroup(), dep.getGroup())) { + return false; + } + // If we reached this point, and module of the rule is null, it is a match + return rule.getModule() == null || Objects.equals(rule.getModule(), dep.getName()); + }); + } + + private Configuration getDetachedWithExclusions(Dependency dep) { + var c = project.getConfigurations().detachedConfiguration(dep); + PlatformSpec platformSpec = platformSpecProperty.get(); + platformSpec.getExclusions().forEach(rule -> { + Map excludeProperties = new HashMap<>(2); + excludeProperties.put("group", rule.getGroup()); + excludeProperties.put("module", rule.getModule()); + c.exclude(excludeProperties); + }); + return c; + } + + private Dependency getConstrainedDep(Dependency dep) { + return findMatchingConstraint(dep).map(c -> project.getDependencies().create( + dep.getGroup() + ":" + dep.getName() + ":" + c.getVersion())).orElse(dep); + } + + private Optional findMatchingConstraint(Dependency dep) { + PlatformSpec platformSpec = platformSpecProperty.get(); + Map constraints = platformSpec.getConstraints(); + PlatformSpec.Constraint matchingConstraint = constraints + .get(ArtifactKey.ga(dep.getGroup(), dep.getName())); + return Optional.ofNullable(matchingConstraint); + } + private class ProcessedDependency { private final ResolvedArtifact artifact; private final ExtensionDependency extension; diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/gradle.properties b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/gradle.properties new file mode 100644 index 0000000000000..92232c7bb27ec --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/gradle.properties @@ -0,0 +1,3 @@ +quarkusPlatformArtifactId=quarkus-bom +quarkusPlatformGroupId=io.quarkus +org.gradle.logging.level=INFO \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-enforced/build.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-enforced/build.gradle new file mode 100644 index 0000000000000..12332eeaa7c7a --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-enforced/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'java' + id 'io.quarkus' +} + +repositories { + mavenLocal { + content { + includeGroup 'org.enforcing.deps' // for dependencies built in this test + includeGroup 'org.enforcing.conditional' // for dependencies built in this test + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation enforcedPlatform("org.enforcing.deps:test-bom:1.0.0") + implementation 'io.quarkus:quarkus-rest' + implementation 'org.enforcing.deps:ext-a:1.0-SNAPSHOT' + testImplementation 'io.quarkus:quarkus-junit5' + testImplementation 'io.rest-assured:rest-assured' +} diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-enforced/src/main/java/org/acme/HelloResource.java b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-enforced/src/main/java/org/acme/HelloResource.java new file mode 100644 index 0000000000000..9b81f9385f088 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-enforced/src/main/java/org/acme/HelloResource.java @@ -0,0 +1,22 @@ +package org.acme; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; + +@Path("/hello") +public class HelloResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "hello"; + } +} diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-1/build.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-1/build.gradle new file mode 100644 index 0000000000000..118f9641c6b0e --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-1/build.gradle @@ -0,0 +1,31 @@ +plugins { + id 'java' + id 'io.quarkus' +} + +repositories { + mavenLocal { + content { + includeGroup 'org.enforcing.deps' // for dependencies built in this test + includeGroup 'org.enforcing.conditional' // for dependencies built in this test + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation enforcedPlatform("org.enforcing.deps:test-bom:1.0.0") + implementation 'io.quarkus:quarkus-rest' + implementation 'org.enforcing.deps:ext-a:1.0-SNAPSHOT' + testImplementation 'io.quarkus:quarkus-junit5' + testImplementation 'io.rest-assured:rest-assured' +} + +configurations { + configureEach { + exclude group: 'org.enforcing.conditional', module: 'dev-mode-only-lib' + } +} diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-1/src/main/java/org/acme/HelloResource.java b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-1/src/main/java/org/acme/HelloResource.java new file mode 100644 index 0000000000000..9b81f9385f088 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-1/src/main/java/org/acme/HelloResource.java @@ -0,0 +1,22 @@ +package org.acme; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; + +@Path("/hello") +public class HelloResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "hello"; + } +} diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-2/build.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-2/build.gradle new file mode 100644 index 0000000000000..1b157d042718e --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-2/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'java' + id 'io.quarkus' +} + +repositories { + mavenLocal { + content { + includeGroup 'org.enforcing.deps' // for dependencies built in this test + includeGroup 'org.enforcing.conditional' // for dependencies built in this test + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation enforcedPlatform("org.enforcing.deps:test-bom-with-exclusion:1.0.0") + implementation 'io.quarkus:quarkus-rest' + implementation 'org.enforcing.deps:ext-a:1.0-SNAPSHOT' + testImplementation 'io.quarkus:quarkus-junit5' + testImplementation 'io.rest-assured:rest-assured' +} diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-2/src/main/java/org/acme/HelloResource.java b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-2/src/main/java/org/acme/HelloResource.java new file mode 100644 index 0000000000000..9b81f9385f088 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner-excluded-2/src/main/java/org/acme/HelloResource.java @@ -0,0 +1,22 @@ +package org.acme; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; + +@Path("/hello") +public class HelloResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "hello"; + } +} diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner/build.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner/build.gradle new file mode 100644 index 0000000000000..ac0e616c76f5b --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner/build.gradle @@ -0,0 +1,24 @@ +plugins { + id 'java' + id 'io.quarkus' +} + +repositories { + mavenLocal { + content { + includeGroup 'org.enforcing.deps' // for dependencies built in this test + includeGroup 'org.enforcing.conditional' // for dependencies built in this test + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() +} + +dependencies { + implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation 'io.quarkus:quarkus-rest' + implementation 'org.enforcing.deps:ext-a:1.0-SNAPSHOT' + testImplementation 'io.quarkus:quarkus-junit5' + testImplementation 'io.rest-assured:rest-assured' +} diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner/src/main/java/org/acme/HelloResource.java b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner/src/main/java/org/acme/HelloResource.java new file mode 100644 index 0000000000000..9b81f9385f088 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/runner/src/main/java/org/acme/HelloResource.java @@ -0,0 +1,22 @@ +package org.acme; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; + +@Path("/hello") +public class HelloResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "hello"; + } +} diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/settings.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/settings.gradle new file mode 100644 index 0000000000000..45c0014ecfd8f --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/consumer-project/settings.gradle @@ -0,0 +1,17 @@ +pluginManagement { + repositories { + mavenLocal { + content { + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() + gradlePluginPortal() + } + plugins { + id 'io.quarkus' version "${quarkusPluginVersion}" + } +} + +include 'runner', 'runner-enforced', 'runner-excluded-1', 'runner-excluded-2' \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-940/build.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-940/build.gradle new file mode 100644 index 0000000000000..36f1389dbb21b --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-940/build.gradle @@ -0,0 +1,32 @@ +plugins { + id 'java-library' + id 'maven-publish' +} + +repositories { + mavenLocal { + content { + includeGroup 'org.enforcing.deps' // for dependencies built in this test + includeGroup 'org.enforcing.conditional' // for dependencies built in this test + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() +} + +dependencies { + implementation 'org.enforcing.deps:simple-dependency:1.0.0' +} + +publishing { + publications { + mavenJava(MavenPublication) { + groupId = 'org.enforcing.conditional' + artifactId = 'dev-mode-only-lib' + version = '9.4.0' + + from components.java + } + } +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-940/src/main/resources/META-INF/beans.xml b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-940/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-990/build.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-990/build.gradle new file mode 100644 index 0000000000000..d317c7d46e6a2 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-990/build.gradle @@ -0,0 +1,32 @@ +plugins { + id 'java-library' + id 'maven-publish' +} + +repositories { + mavenLocal { + content { + includeGroup 'org.enforcing.deps' // for dependencies built in this test + includeGroup 'org.enforcing.conditional' // for dependencies built in this test + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() +} + +dependencies { + implementation 'org.enforcing.deps:simple-dependency:1.0.0' +} + +publishing { + publications { + mavenJava(MavenPublication) { + groupId = 'org.enforcing.conditional' + artifactId = 'dev-mode-only-lib' + version = '9.9.0' + + from components.java + } + } +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-990/src/main/resources/META-INF/beans.xml b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/dev-mode-only-lib-990/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/ext-a/deployment/build.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/ext-a/deployment/build.gradle new file mode 100644 index 0000000000000..87b4efd86aca0 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/ext-a/deployment/build.gradle @@ -0,0 +1,31 @@ +plugins { + id 'java-library' + id 'maven-publish' +} + +repositories { + mavenLocal { + content { + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() +} + +dependencies { + implementation platform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") + implementation 'io.quarkus:quarkus-core-deployment' +} + +publishing { + publications { + mavenJava(MavenPublication) { + groupId = 'org.enforcing.deps' + artifactId = 'ext-a-deployment' + version = '1.0-SNAPSHOT' + + from components.java + } + } +} diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/ext-a/deployment/src/main/java/org/enforcing/deps/QuarkusExtProcessor.java b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/ext-a/deployment/src/main/java/org/enforcing/deps/QuarkusExtProcessor.java new file mode 100644 index 0000000000000..0969875b7f312 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/ext-a/deployment/src/main/java/org/enforcing/deps/QuarkusExtProcessor.java @@ -0,0 +1,16 @@ + +package org.enforcing.conditional.quarkus.ext.a.deployment; + +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.FeatureBuildItem; + +class AcmeQuarkusExtProcessor { + + private static final String FEATURE = "acme-quarkus-ext-a"; + + @BuildStep + FeatureBuildItem feature() { + return new FeatureBuildItem(FEATURE); + } + +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/ext-a/runtime/build.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/ext-a/runtime/build.gradle new file mode 100644 index 0000000000000..debe35beb66c1 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/ext-a/runtime/build.gradle @@ -0,0 +1,35 @@ +plugins { + id 'java-library' + id 'maven-publish' + id 'io.quarkus.extension' +} + +repositories { + mavenLocal { + content { + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() +} + +dependencies { + implementation platform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") +} + +quarkusExtension { + deploymentArtifact = "org.enforcing.deps:ext-a-deployment:1.0-SNAPSHOT" + conditionalDevDependencies = ["org.enforcing.conditional:dev-mode-only-lib::jar:9.9.0"] +} + +publishing { + publications { + mavenJave(MavenPublication) { + groupId = 'org.enforcing.deps' + artifactId = 'ext-a' + version = '1.0-SNAPSHOT' + from components.java + } + } +} diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/gradle.properties b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/gradle.properties new file mode 100644 index 0000000000000..92232c7bb27ec --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/gradle.properties @@ -0,0 +1,3 @@ +quarkusPlatformArtifactId=quarkus-bom +quarkusPlatformGroupId=io.quarkus +org.gradle.logging.level=INFO \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/settings.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/settings.gradle new file mode 100644 index 0000000000000..5a7a160cdb4f4 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/settings.gradle @@ -0,0 +1,20 @@ +pluginManagement { + repositories { + mavenLocal { + content { + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() + gradlePluginPortal() + } + plugins { + id 'io.quarkus' version "${quarkusPluginVersion}" + id 'io.quarkus.extension' version "${quarkusPluginVersion}" + } +} + +include 'ext-a:runtime', 'ext-a:deployment' +include 'dev-mode-only-lib-940', 'dev-mode-only-lib-990', 'simple-dep' +include 'test-bom', 'test-bom-with-exclusion' diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/simple-dep/build.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/simple-dep/build.gradle new file mode 100644 index 0000000000000..e91dd13557079 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/simple-dep/build.gradle @@ -0,0 +1,28 @@ +plugins { + id 'java-library' + id 'maven-publish' +} + +repositories { + mavenLocal { + content { + includeGroup 'org.enforcing.deps' // for dependencies built in this test + includeGroup 'org.enforcing.conditional' // for dependencies built in this test + includeGroupByRegex 'io.quarkus.*' + includeGroup 'org.hibernate.orm' + } + } + mavenCentral() +} + +publishing { + publications { + mavenJava(MavenPublication) { + groupId = 'org.enforcing.deps' + artifactId = 'simple-dependency' + version = '1.0.0' + + from components.java + } + } +} \ No newline at end of file diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/simple-dep/src/main/resources/META-INF/beans.xml b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/simple-dep/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/test-bom-with-exclusion/build.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/test-bom-with-exclusion/build.gradle new file mode 100644 index 0000000000000..460a5e9120f38 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/test-bom-with-exclusion/build.gradle @@ -0,0 +1,8 @@ +def isWindows() { + System.getProperty('os.name').toLowerCase().contains('win') +} + +tasks.register('publishToMavenLocal', Exec) { + commandLine = isWindows() ? ['cmd', '/c', 'mvn', '-q', 'clean', 'install'] + : ['mvn', '-q', 'clean', 'install'] +} diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/test-bom-with-exclusion/pom.xml b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/test-bom-with-exclusion/pom.xml new file mode 100644 index 0000000000000..cd80b1e50a225 --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/test-bom-with-exclusion/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + org.enforcing.deps + test-bom-with-exclusion + 1.0.0 + pom + + Test BOM With Exclusion + + + + + org.enforcing.conditional + dev-mode-only-lib + 9.4.0 + + + org.enforcing.deps + simple-dependency + + + + + + diff --git a/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/test-bom/build.gradle b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/test-bom/build.gradle new file mode 100644 index 0000000000000..1fcef6eec929b --- /dev/null +++ b/integration-tests/gradle/src/main/resources/enforcing-platform-for-conditional-deps/other-deps/test-bom/build.gradle @@ -0,0 +1,29 @@ +plugins { + id 'java-platform' + id 'maven-publish' +} + +javaPlatform { + allowDependencies() +} + +publishing { + publications { + mavenBom(MavenPublication) { + from components.javaPlatform + groupId = 'org.enforcing.deps' + artifactId = 'test-bom' + version = '1.0.0' + } + } + repositories { + mavenLocal() + } +} + +dependencies { + constraints { + api 'org.enforcing.conditional:dev-mode-only-lib:9.4.0' + } +} + diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/EnforcingPlatformForConditionalDepsTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/EnforcingPlatformForConditionalDepsTest.java new file mode 100644 index 0000000000000..47b623cde8147 --- /dev/null +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/EnforcingPlatformForConditionalDepsTest.java @@ -0,0 +1,146 @@ +package io.quarkus.gradle; + +import static io.quarkus.gradle.util.AppModelDeserializer.deserializeAppModel; +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + +import io.quarkus.maven.dependency.Dependency; + +/** + * Integration tests verifying enforcement of platform constraints for conditional development dependencies + * in Gradle projects. The test sequence intentionally relies on method ordering in order to first publish + * the synthetic extensions and libraries to the local Maven repository and then exercise different + * consumer scenarios: + *
    + *
  1. Publishing test extensions and libraries
  2. + *
  3. Baseline consumer without any enforced constraints
  4. + *
  5. Consumer with enforced (pinned) version constraints
  6. + *
  7. Consumer that excludes an optional dev-mode only dependency
  8. + *
+ * + * We avoid a {@code @BeforeAll} lifecycle hook (which would need to be static) to preserve access to + * instance helpers from {@link QuarkusGradleWrapperTestBase}. + */ +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@DisplayName("Conditional dependency platform enforcement (Gradle)") +public class EnforcingPlatformForConditionalDepsTest extends QuarkusGradleWrapperTestBase { + + private static final String CONSUMER_PROJECT_PATH = "enforcing-platform-for-conditional-deps/consumer-project"; + private static final String PRODUCER_PROJECT_PATH = "enforcing-platform-for-conditional-deps/other-deps"; + private static final Set GROUP_IDS_TO_TEST = Set.of("org.enforcing.deps", "org.enforcing.conditional"); + + /** + * Publishes the test extensions, libraries and BOM used by the subsequent test scenarios to the local Maven repo. + */ + @Test + @Order(1) + @DisplayName("Publish synthetic test artifacts to local Maven repository") + public void publishTestArtifacts() throws IOException, InterruptedException { + File dependencyProject = getProjectDir(PRODUCER_PROJECT_PATH); + runGradleWrapper(dependencyProject, ":simple-dep:publishToMavenLocal"); + runGradleWrapper(dependencyProject, + ":ext-a:runtime:publishToMavenLocal", + ":ext-a:deployment:publishToMavenLocal", + ":dev-mode-only-lib-94:publishToMavenLocal", + ":dev-mode-only-lib-99:publishToMavenLocal", + ":test-bom:publishToMavenLocal", + ":test-bom-with-exclusion:publishToMavenLocal"); + } + + /** + * Verifies that, without any platform constraint enforcement, the newer dev-mode only library version (9.9.0) + * is selected alongside the test extension artifacts. + */ + @Test + @Order(2) + @DisplayName("Resolve conditional dev dependencies without enforced constraints (selects newest version)") + public void conditionalDevDependenciesWithoutConstraints() throws Exception { + assertConditionalDependencies( + "runner", + "ext-a:1.0-SNAPSHOT", + "ext-a-deployment:1.0-SNAPSHOT", + "dev-mode-only-lib:9.9.0", + "simple-dependency:1.0.0"); + } + + /** + * Verifies that when constraints are enforced, the pinned dev-mode only library version (9.4.0) is respected. + */ + @Test + @Order(3) + @DisplayName("Enforce pinned dev-mode-only dependency version (9.4.0)") + public void enforcePinnedVersion() throws Exception { + assertConditionalDependencies( + "runner-enforced", + "ext-a:1.0-SNAPSHOT", + "ext-a-deployment:1.0-SNAPSHOT", + "dev-mode-only-lib:9.4.0", + "simple-dependency:1.0.0"); + } + + /** + * Verifies that the conditional dev-mode only library can be excluded entirely via consumer-level configuration. + * The exclusion is configured directly in the consumer project's build configuration. + */ + @Test + @Order(4) + @DisplayName("Exclude conditional dev-mode-only dependency via consumer configuration") + public void excludeConditionalDependencyFromConsumer() throws Exception { + assertConditionalDependencies( + "runner-excluded-1", + "ext-a:1.0-SNAPSHOT", + "ext-a-deployment:1.0-SNAPSHOT"); + } + + /** + * Verifies that the conditional dev-mode only library can be excluded entirely via BOM-level configuration. + * The exclusion is specified in the Bill of Materials (BOM) that governs dependency management. + */ + @Test + @Order(5) + @DisplayName("Exclude conditional dev-mode-only dependency via BOM configuration") + public void excludeConditionalDependencyFromBom() throws Exception { + assertConditionalDependencies( + "runner-excluded-2", + "ext-a:1.0-SNAPSHOT", + "ext-a-deployment:1.0-SNAPSHOT", + "dev-mode-only-lib:9.4.0"); + } + + // ------------------------------------------------------------------------------------- + // Helper method + // ------------------------------------------------------------------------------------- + + /** + * Runs the given Gradle task that produces the dev application model for the specified module variant, then + * asserts that the resolved set of artifacts belonging to {@link #GROUP_IDS_TO_TEST} matches exactly the + * expected coordinates (artifactId:version) in any order. + * + * @param moduleDirName the directory name of the module (used to compute the build output path) + * @param expectedArtifacts the expected set of artifactId:version coordinates + */ + private void assertConditionalDependencies(String moduleDirName, String... expectedArtifacts) + throws Exception { + var projectDir = getProjectDir(CONSUMER_PROJECT_PATH); + var fullTaskName = ":%s:quarkusGenerateDevAppModel".formatted(moduleDirName); + runGradleWrapper(projectDir, "clean", fullTaskName); + var appModel = deserializeAppModel( + projectDir.toPath().resolve(moduleDirName + "/build/quarkus/application-model/quarkus-app-dev-model.dat")); + var conditionalArtifacts = ((Collection) appModel.getDependencies()).stream() + .filter(d -> GROUP_IDS_TO_TEST.contains(d.getGroupId())) + .map(d -> d.getArtifactId() + ":" + d.getVersion()) + .collect(Collectors.toSet()); + assertThat(conditionalArtifacts).containsExactlyInAnyOrder(expectedArtifacts); + } +} diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestCompositeBuildWithExtensionsTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestCompositeBuildWithExtensionsTest.java index 7ed9e6eb7f92d..4d463eaae4150 100644 --- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestCompositeBuildWithExtensionsTest.java +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestCompositeBuildWithExtensionsTest.java @@ -1,10 +1,10 @@ package io.quarkus.gradle; +import static io.quarkus.gradle.util.AppModelDeserializer.deserializeAppModel; import static org.assertj.core.api.Assertions.assertThat; import java.io.File; import java.io.IOException; -import java.io.ObjectInputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; @@ -71,12 +71,4 @@ protected File getProjectDir(String projectName) { } return testProjectDir; } - - private static ApplicationModel deserializeAppModel(Path path) throws IOException { - try (ObjectInputStream out = new ObjectInputStream(Files.newInputStream(path))) { - return (ApplicationModel) out.readObject(); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } } diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestFixtureMultiModuleTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestFixtureMultiModuleTest.java index 75e0c4bf87007..0bd1498749b53 100644 --- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestFixtureMultiModuleTest.java +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestFixtureMultiModuleTest.java @@ -1,11 +1,9 @@ package io.quarkus.gradle; +import static io.quarkus.gradle.util.AppModelDeserializer.deserializeAppModel; import static org.assertj.core.api.Assertions.assertThat; import java.io.File; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; @@ -46,19 +44,4 @@ public void testTaskShouldUseTestFixtures() throws Exception { ArtifactKey.fromString("my-groupId:static-init-library::jar"), "runtime-cp, deployment-cp, workspace-module, reloadable")); } - - /** - * Copied from ToolingUtils - * - * @param path application model dat file - * @return deserialized ApplicationModel - * @throws IOException in case of a failure to read the model - */ - private static ApplicationModel deserializeAppModel(Path path) throws IOException { - try (ObjectInputStream out = new ObjectInputStream(Files.newInputStream(path))) { - return (ApplicationModel) out.readObject(); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } } diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/util/AppModelDeserializer.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/util/AppModelDeserializer.java new file mode 100644 index 0000000000000..29f1db043367b --- /dev/null +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/util/AppModelDeserializer.java @@ -0,0 +1,26 @@ +package io.quarkus.gradle.util; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +import io.quarkus.bootstrap.model.ApplicationModel; + +public class AppModelDeserializer { + + /** + * Copied from ToolingUtils + * + * @param path application model dat file + * @return deserialized ApplicationModel + * @throws IOException in case of a failure to read the model + */ + public static ApplicationModel deserializeAppModel(Path path) throws IOException { + try (ObjectInputStream out = new ObjectInputStream(Files.newInputStream(path))) { + return (ApplicationModel) out.readObject(); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +}