├── .github ├── dependabot.yml └── workflows │ ├── ci-build.yml │ ├── cross-version-tests.yml │ ├── dependency-submission.yml │ ├── gh-pages.yml │ └── release.yml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── build.gradle.kts ├── gradle.properties ├── gradle ├── checkstyle │ ├── checkstyle.xml │ └── header.txt ├── plugins │ ├── build-lifecycle │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ └── kotlin │ │ │ └── gradlexbuild.lifecycle.gradle.kts │ ├── build-parameters │ │ └── build.gradle.kts │ ├── documentation │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ └── kotlin │ │ │ ├── gradlexbuild.asciidoctor-conventions.gradle.kts │ │ │ └── gradlexbuild │ │ │ └── jvm │ │ │ └── dependency │ │ │ └── conflict │ │ │ └── documentation │ │ │ └── CapabilityListing.kt │ └── settings.gradle.kts └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── renovate.json ├── samples ├── sample-alignment │ ├── build.gradle.kts │ ├── build.out │ ├── build.sample.conf │ ├── settings.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── dummy │ │ └── DummyClass.java ├── sample-all-deactivated │ ├── build.gradle.kts │ ├── build.out │ ├── build.sample.conf │ ├── settings.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── dummy │ │ └── DummyClass.java ├── sample-all │ ├── build-scan.png │ ├── build.gradle.kts │ ├── build.out │ ├── build.sample.conf │ ├── settings.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── dummy │ │ └── DummyClass.java └── sample-javax-and-jakarta │ ├── build.gradle.kts │ ├── build.out │ ├── build.sample.conf │ ├── settings.gradle.kts │ └── src │ └── main │ └── java │ └── dummy │ └── DummyClass.java ├── settings.gradle.kts └── src ├── docs ├── asciidoc │ ├── docinfo-footer.html │ ├── docinfo.html │ ├── images │ │ └── build-scan.png │ ├── index.adoc │ └── parts │ │ ├── detection.adoc │ │ └── resolution.adoc └── samples │ └── plugin-dependency │ ├── groovy │ └── build.gradle │ ├── kotlin │ └── build.gradle.kts │ └── primer.sample.conf ├── main └── java │ └── org │ └── gradlex │ └── jvm │ └── dependency │ └── conflict │ ├── detection │ ├── JvmDependencyConflictDetectionPlugin.java │ ├── package-info.java │ ├── rules │ │ ├── AlignmentDefinition.java │ │ ├── AlignmentDefinitionRule.java │ │ ├── CapabilityDefinition.java │ │ ├── CapabilityDefinitionRule.java │ │ ├── FixedVersionCapabilityDefinitionRule.java │ │ ├── aopalliance │ │ │ ├── AopallianceRule.java │ │ │ └── package-info.java │ │ ├── asm │ │ │ └── AsmAlignmentRule.java │ │ ├── bouncycastle │ │ │ ├── BouncyCastleRule.java │ │ │ └── package-info.java │ │ ├── guava │ │ │ ├── GuavaListenableFutureRule.java │ │ │ └── package-info.java │ │ ├── jakarta │ │ │ ├── JakartaActivationApiRule.java │ │ │ ├── JakartaActivationImplementationRule.java │ │ │ ├── JakartaAnnotationApiRule.java │ │ │ ├── JakartaJwsApiRule.java │ │ │ ├── JakartaMailApiRule.java │ │ │ ├── JakartaServletApiRule.java │ │ │ ├── JakartaWebsocketApiRule.java │ │ │ ├── JakartaWebsocketClientApiRule.java │ │ │ ├── JakartaWsRsApiRule.java │ │ │ ├── JavaxActivationApiRule.java │ │ │ ├── JavaxAnnotationApiRule.java │ │ │ ├── JavaxEjbApiRule.java │ │ │ ├── JavaxElApiRule.java │ │ │ ├── JavaxInjectApiRule.java │ │ │ ├── JavaxJsonApiRule.java │ │ │ ├── JavaxJwsApisRule.java │ │ │ ├── JavaxMailApiRule.java │ │ │ ├── JavaxPersistenceApiRule.java │ │ │ ├── JavaxServletApiRule.java │ │ │ ├── JavaxServletJspRule.java │ │ │ ├── JavaxServletJstlRule.java │ │ │ ├── JavaxSoapApiRule.java │ │ │ ├── JavaxTransactionApiRule.java │ │ │ ├── JavaxValidationApiRule.java │ │ │ ├── JavaxWebsocketApiRule.java │ │ │ ├── JavaxWsRsApiRule.java │ │ │ ├── JavaxXmlBindApiRule.java │ │ │ ├── JavaxXmlWsApiRule.java │ │ │ └── package-info.java │ │ ├── jetty │ │ │ └── JettyAlignmentRule.java │ │ ├── logging │ │ │ ├── Log4J2Alignment.java │ │ │ ├── LoggingModuleIdentifiers.java │ │ │ ├── Slf4J2Alignment.java │ │ │ ├── Slf4JAlignment.java │ │ │ └── package-info.java │ │ └── package-info.java │ └── util │ │ └── VersionNumber.java │ └── resolution │ ├── ConflictResolution.java │ ├── ConsistentResolution.java │ ├── DefaultResolutionStrategy.java │ ├── JvmDependencyConflictDetectionPluginApplication.java │ ├── JvmDependencyConflictResolutionPlugin.java │ ├── JvmDependencyConflictsExtension.java │ ├── Logging.java │ ├── Patch.java │ ├── PatchModule.java │ ├── Slf4JEnforcementSubstitutionsUsing.java │ ├── package-info.java │ └── rules │ ├── AddAlignmentConstraintsMetadataRule.java │ ├── AddApiDependencyMetadataRule.java │ ├── AddBomDependencyMetadataRule.java │ ├── AddCapabilityMetadataRule.java │ ├── AddCompileOnlyApiDependencyMetadataRule.java │ ├── AddFeatureMetadataRule.java │ ├── AddRuntimeOnlyDependencyMetadataRule.java │ ├── AddTargetPlatformVariantsMetadataRule.java │ ├── ComponentStatusRule.java │ ├── GuavaComponentRule.java │ ├── ReduceToCompileOnlyApiDependencyMetadataRule.java │ ├── ReduceToRuntimeOnlyDependencyMetadataRule.java │ ├── RemoveCapabilityMetadataRule.java │ ├── RemoveDependencyMetadataRule.java │ ├── VariantIdentification.java │ ├── VariantSelection.java │ └── package-info.java └── test ├── groovy └── org │ └── gradlex │ └── jvm │ └── dependency │ └── conflict │ └── test │ ├── AopAllianceMinVersionTest.groovy │ ├── CapabilityWithDifferentVersionsTest.groovy │ ├── ComponentStatusRuleTest.groovy │ ├── ConsistentResolutionTest.groovy │ ├── CustomizationTest.groovy │ ├── GuavaCapabilityConflictResolutionTest.groovy │ ├── GuavaClasspathTest.groovy │ ├── JarOverlapTest.groovy │ ├── RulesModeTest.groovy │ ├── SettingsTest.groovy │ ├── fixture │ └── GradleBuild.groovy │ ├── issues │ └── Issue243Test.groovy │ ├── logging │ ├── AbstractLoggingCapabilitiesPluginFunctionalTest.groovy │ ├── LoggingCapabilitiesPluginDetectionFunctionalTest.groovy │ └── LoggingCapabilitiesPluginSelectionFunctionalTest.groovy │ └── patch │ ├── AbstractPatchTest.groovy │ ├── AddAlignmentTest.groovy │ ├── AddFeatureTest.groovy │ ├── AddTargetPlatformVariantTest.groovy │ ├── ModifyCapabilitiesTest.groovy │ ├── ModifyDependenciesTest.groovy │ └── SetStatusTest.groovy └── java └── org └── gradlex └── jvm └── dependency └── conflict └── samples ├── PluginBuildLocationSampleModifier.java └── SamplesTest.java /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | - package-ecosystem: "gradle" 8 | directory: "/" 9 | schedule: 10 | interval: "weekly" 11 | -------------------------------------------------------------------------------- /.github/workflows/ci-build.yml: -------------------------------------------------------------------------------- 1 | name: Build Plugin 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | gradle-build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: git clone 14 | uses: actions/checkout@v4 15 | - name: Set up JDK 16 | uses: actions/setup-java@v4 17 | with: 18 | distribution: temurin 19 | java-version: 17 20 | - name: Set up Gradle 21 | uses: gradle/actions/setup-gradle@v4 22 | - run: "./gradlew quickCheck" 23 | -------------------------------------------------------------------------------- /.github/workflows/cross-version-tests.yml: -------------------------------------------------------------------------------- 1 | name: Cross version tests 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | gradle-build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | gradleVersion: ["6.8.3", "6.9.4", "7.0.2", "8.0.2"] 15 | steps: 16 | - name: git clone 17 | uses: actions/checkout@v4 18 | - name: Set up JDK 19 | uses: actions/setup-java@v4 20 | with: 21 | distribution: temurin 22 | java-version: 17 23 | - name: Set up Gradle 24 | uses: gradle/actions/setup-gradle@v4 25 | - run: "./gradlew test${{ matrix.gradleVersion }}" 26 | -------------------------------------------------------------------------------- /.github/workflows/dependency-submission.yml: -------------------------------------------------------------------------------- 1 | name: Dependency Submission 2 | 3 | on: [ push ] 4 | 5 | permissions: 6 | contents: write 7 | 8 | jobs: 9 | dependency-submission: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout sources 13 | uses: actions/checkout@v4 14 | - name: Generate and submit dependency graph 15 | uses: gradle/actions/dependency-submission@v4 16 | with: 17 | build-scan-publish: true 18 | build-scan-terms-of-service-url: "https://gradle.com/terms-of-service" 19 | build-scan-terms-of-service-agree: "yes" 20 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: Deploy documentation to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | 7 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 8 | permissions: 9 | contents: read 10 | pages: write 11 | id-token: write 12 | 13 | # Allow one concurrent deployment 14 | concurrency: 15 | group: pages 16 | cancel-in-progress: true 17 | 18 | jobs: 19 | build: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v4 23 | - uses: actions/configure-pages@v5 24 | - uses: actions/setup-java@v4 25 | with: 26 | distribution: zulu 27 | java-version: 17 28 | - uses: gradle/actions/setup-gradle@v4 29 | - run: "./gradlew :asciidoctor --no-configuration-cache" 30 | - uses: actions/upload-pages-artifact@v3 31 | with: 32 | path: "./build/docs/asciidoc" 33 | 34 | deploy: 35 | environment: 36 | name: github-pages 37 | url: ${{ steps.deployment.outputs.page_url }} 38 | runs-on: ubuntu-latest 39 | needs: build 40 | steps: 41 | - name: Deploy to GitHub Pages 42 | id: deployment 43 | uses: actions/deploy-pages@v4 44 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Publish Release 2 | on: 3 | push: 4 | tags: 5 | - 'v*' 6 | jobs: 7 | release-build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: git clone 11 | uses: actions/checkout@v4 12 | - name: Set up JDK 13 | uses: actions/setup-java@v4 14 | with: 15 | distribution: temurin 16 | java-version: 17 17 | - name: Set up Gradle 18 | uses: gradle/actions/setup-gradle@v4 19 | - run: "./gradlew :publishPlugin --no-configuration-cache" 20 | env: 21 | SIGNING_KEY: ${{ secrets.SIGNING_KEY }} 22 | SIGNING_PASSPHRASE: ${{ secrets.SIGNING_PASSPHRASE }} 23 | GRADLE_PUBLISH_KEY: ${{ secrets.GRADLE_PUBLISH_KEY }} 24 | GRADLE_PUBLISH_SECRET: ${{ secrets.GRADLE_PUBLISH_SECRET }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | build 4 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("groovy") 3 | id("gradlexbuild.lifecycle") 4 | id("gradlexbuild.asciidoctor-conventions") 5 | id("org.gradlex.internal.plugin-publish-conventions") version "0.6" 6 | } 7 | 8 | group = "org.gradlex" 9 | version = "2.4" 10 | 11 | java { 12 | toolchain.languageVersion = JavaLanguageVersion.of(17) 13 | } 14 | 15 | tasks.withType().configureEach { 16 | options.release = 8 17 | } 18 | 19 | tasks.withType().configureEach { 20 | options { 21 | this as StandardJavadocDocletOptions 22 | encoding = "UTF-8" 23 | addStringOption("Xdoclint:all,-missing", "-quiet") 24 | addStringOption("Xwerror", "-quiet") 25 | } 26 | } 27 | 28 | val tagsList = listOf( 29 | "dependency", "dependencies", "dependency-management", "capabilities", "java", "logging", 30 | "asm", "bouncycastle", "cglib", "commons-io", "dom4j", "guava", "hamcrest", "javax", "jakarta", "junit", 31 | "mysql", "postgresql", "stax", "slf4j", "log4j2", "velocity", "woodstox" 32 | ) 33 | 34 | pluginPublishConventions { 35 | id("org.gradlex.jvm-dependency-conflict-resolution") 36 | implementationClass("org.gradlex.jvm.dependency.conflict.resolution.JvmDependencyConflictResolutionPlugin") 37 | displayName("JVM Conflict Resolution Gradle Plugin") 38 | description("Convenient dependency conflict management for Java projects.") 39 | tags(*tagsList.toTypedArray()) 40 | gitHub("https://github.com/gradlex-org/jvm-dependency-conflict-resolution") 41 | website("https://github.com/gradlex-org/jvm-dependency-conflict-resolution") 42 | developer { 43 | id = "britter" 44 | name = "Benedikt Ritter" 45 | email = "benedikt@gradlex.org" 46 | } 47 | developer { 48 | id = "jjohannes" 49 | name = "Jendrik Johannes" 50 | email = "jendrik@gradlex.org" 51 | } 52 | developer { 53 | id = "ljacomet" 54 | name = "Louis Jacomet" 55 | email = "louis@gradlex.org" 56 | } 57 | } 58 | 59 | gradlePlugin { 60 | plugins { 61 | create("jvm-dependency-conflict-detection") { 62 | id = "org.gradlex.jvm-dependency-conflict-detection" 63 | implementationClass = "org.gradlex.jvm.dependency.conflict.detection.JvmDependencyConflictDetectionPlugin" 64 | displayName = "JVM Conflict Detection Gradle Plugin" 65 | description = "Adds Capabilities to well-known Components hosted on Maven Central." 66 | tags = tagsList 67 | } 68 | } 69 | } 70 | 71 | dependencies { 72 | testImplementation("org.gradle.exemplar:samples-check:1.0.3") 73 | testImplementation("org.spockframework:spock-core:2.3-groovy-3.0") 74 | testRuntimeOnly("org.junit.vintage:junit-vintage-engine") 75 | } 76 | 77 | testing.suites.named("test") { 78 | useJUnitJupiter() 79 | listOf("6.8.3", "6.9.4", "7.0.2", "8.0.2").forEach { gradleVersionUnderTest -> 80 | targets.register("test${gradleVersionUnderTest}") { 81 | testTask { 82 | group = LifecycleBasePlugin.VERIFICATION_GROUP 83 | description = "Runs tests against Gradle $gradleVersionUnderTest" 84 | useJUnitPlatform { 85 | excludeTags("no-cross-version") 86 | } 87 | systemProperty("gradleVersionUnderTest", gradleVersionUnderTest) 88 | 89 | exclude("**/*SamplesTest.class") // Not yet cross-version ready 90 | } 91 | } 92 | } 93 | targets.all { 94 | testTask { 95 | maxParallelForks = 4 96 | inputs.dir(layout.projectDirectory.dir("samples")) 97 | inputs.dir("src/docs/samples") 98 | } 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.caching=true 2 | org.gradle.configuration-cache=true -------------------------------------------------------------------------------- /gradle/checkstyle/checkstyle.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /gradle/checkstyle/header.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ -------------------------------------------------------------------------------- /gradle/plugins/build-lifecycle/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `kotlin-dsl` 3 | } 4 | -------------------------------------------------------------------------------- /gradle/plugins/build-lifecycle/src/main/kotlin/gradlexbuild.lifecycle.gradle.kts: -------------------------------------------------------------------------------- 1 | // Workaround for the fact that test suites are always added to check. 2 | // Since we set up test suites for long running cross version tests 3 | // we want to have a lifecycle task that runs all quality checks and 4 | // the default tests. 5 | tasks.register("quickCheck") { 6 | group = LifecycleBasePlugin.VERIFICATION_GROUP 7 | description = "Runs the default test task as well as code verifications such as Checkstyle" 8 | dependsOn(tasks.named("assemble")) 9 | dependsOn(tasks.named("test")) 10 | dependsOn(tasks.named("checkstyleMain")) 11 | dependsOn(tasks.named("checkstyleTest")) 12 | } 13 | 14 | -------------------------------------------------------------------------------- /gradle/plugins/build-parameters/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("org.gradlex.build-parameters") version "1.4.4" 3 | } 4 | 5 | buildParameters { 6 | pluginId("gradlexbuild.build-parameters") 7 | bool("ci") { 8 | fromEnvironment() 9 | defaultValue = false 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /gradle/plugins/documentation/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `kotlin-dsl` 3 | } 4 | 5 | dependencies { 6 | implementation(project(":build-lifecycle")) 7 | implementation("org.asciidoctor:asciidoctor-gradle-jvm:4.0.4") 8 | } 9 | -------------------------------------------------------------------------------- /gradle/plugins/documentation/src/main/kotlin/gradlexbuild.asciidoctor-conventions.gradle.kts: -------------------------------------------------------------------------------- 1 | import gradlexbuild.jvm.dependency.conflict.documentation.CapabilityListing 2 | import org.asciidoctor.gradle.base.AsciidoctorAttributeProvider 3 | import org.asciidoctor.gradle.base.log.Severity 4 | 5 | plugins { 6 | id("java") 7 | id("org.asciidoctor.jvm.convert") 8 | } 9 | 10 | tasks { 11 | val generateCapabilitiesList by tasks.registering(CapabilityListing::class) { 12 | pluginClasses.from(tasks.jar) 13 | outputFile = layout.buildDirectory.file("generated/docs/asciidoc/parts/capabilities-listing.adoc") 14 | } 15 | 16 | asciidoctor { 17 | notCompatibleWithConfigurationCache("See https://github.com/asciidoctor/asciidoctor-gradle-plugin/issues/564") 18 | 19 | failureLevel = Severity.WARN 20 | 21 | attributes(mapOf( 22 | "docinfodir" to "src/docs/asciidoc", 23 | "docinfo" to "shared", 24 | "imagesdir" to "./images", 25 | "source-highlighter" to "prettify", 26 | "tabsize" to "4", 27 | "toc" to "left", 28 | "tip-caption" to "💡", 29 | "note-caption" to "ℹ️", 30 | "important-caption" to "❗", 31 | "caution-caption" to "🔥", 32 | "warning-caption" to "⚠️", 33 | "sectanchors" to true, 34 | "idprefix" to "", 35 | "idseparator" to "-", 36 | "samples-path" to "$projectDir/src/docs/samples" 37 | )) 38 | 39 | attributeProviders += AsciidoctorAttributeProvider { 40 | mapOf("capabilities-listing" to generateCapabilitiesList.get().outputFile.get().asFile.absolutePath) 41 | } 42 | dependsOn(generateCapabilitiesList) 43 | 44 | inputs.dir("src/docs/samples") 45 | .withPathSensitivity(PathSensitivity.RELATIVE) 46 | .withPropertyName("samples") 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /gradle/plugins/documentation/src/main/kotlin/gradlexbuild/jvm/dependency/conflict/documentation/CapabilityListing.kt: -------------------------------------------------------------------------------- 1 | package gradlexbuild.jvm.dependency.conflict.documentation 2 | 3 | import org.gradle.api.DefaultTask 4 | import org.gradle.api.artifacts.ComponentMetadataRule 5 | import org.gradle.api.file.ConfigurableFileCollection 6 | import org.gradle.api.file.RegularFileProperty 7 | import org.gradle.api.tasks.Classpath 8 | import org.gradle.api.tasks.OutputFile 9 | import org.gradle.api.tasks.TaskAction 10 | import java.net.URLClassLoader 11 | 12 | abstract class CapabilityListing : DefaultTask() { 13 | 14 | @get:OutputFile 15 | abstract val outputFile: RegularFileProperty 16 | 17 | @get:Classpath 18 | abstract val pluginClasses: ConfigurableFileCollection 19 | 20 | @TaskAction 21 | fun update() { 22 | val classesUrls = pluginClasses.files.map { it.toURI().toURL() } 23 | val loader = URLClassLoader("pluginClasspath", classesUrls.toTypedArray(), ComponentMetadataRule::class.java.classLoader) 24 | val definitions = loader.loadClass("org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition") 25 | 26 | val allCapabilities = definitions.enumConstants.map { rule -> 27 | val capability = definitions.getDeclaredMethod("getCapability").invoke(rule) as String 28 | val modules = definitions.getDeclaredMethod("getModules").invoke(rule) as List<*> 29 | 30 | Pair(capability, modules) 31 | }.sortedBy { it.first } 32 | 33 | val capabilityList = allCapabilities.joinToString("") { c -> 34 | "* ${c.first}\n${c.second.joinToString("") { "** ${(it as String).asRepoLink()}\n" }}" 35 | } 36 | 37 | outputFile.get().asFile.also { 38 | it.parentFile.mkdirs() 39 | it.writeText(capabilityList) 40 | } 41 | } 42 | 43 | private fun String.asRepoLink() = "https://search.maven.org/artifact/${replace(":", "/")}[$this]" 44 | } -------------------------------------------------------------------------------- /gradle/plugins/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencyResolutionManagement { 2 | repositories.gradlePluginPortal() 3 | } 4 | 5 | include("build-lifecycle") 6 | include("build-parameters") 7 | include("documentation") 8 | 9 | if (!JavaVersion.current().isJava11Compatible) { 10 | error("This build requires JDK 11 or higher") // The custom build logic that loads classes (e.g. ReadmeUpdate) fails otherwise 11 | } 12 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gradlex-org/jvm-dependency-conflict-resolution/5d34834083cd662732894f45fabca04ebccded86/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionSha256Sum=7197a12f450794931532469d4ff21a59ea2c1cd59a3ec3f89c035c3c420a6999 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip 5 | networkTimeout=10000 6 | validateDistributionUrl=true 7 | zipStoreBase=GRADLE_USER_HOME 8 | zipStorePath=wrapper/dists 9 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH= 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ], 6 | "ignorePaths": [ 7 | "samples/sample-alignment/**", 8 | "samples/sample-javax-and-jakarta/**" 9 | ], 10 | "packageRules": [ 11 | { 12 | "groupName": "Tomcat", 13 | "matchPackageNames": ["org.apache.tomcat**"] 14 | }, 15 | { 16 | "groupName": "Bouncy Castle", 17 | "matchPackageNames": ["org.bouncycastle**"] 18 | }, 19 | { 20 | "description": ["Do not suggest replacements"], 21 | "matchPackageNames": [ 22 | "com.lowagie:itext", 23 | "itext:itext", 24 | "junit:junit-dep", 25 | "mysql:mysql-connector-java", 26 | "org.apache.commons:commons-io", 27 | "org.bouncycastle:bcprov-ext-jdk14", 28 | "org.bouncycastle:bcprov-ext-jdk15to18", 29 | "org.bouncycastle:bcprov-ext-jdk18on", 30 | "org.bouncycastle:bcprov-jdk15", 31 | "org.codehaus.woodstox:wstx-asl", 32 | "org.hibernate.javax.persistence:hibernate-jpa-2.2-api", 33 | "org.slf4j:slf4j-log4j12", 34 | "servletapi:servletapi" 35 | ], 36 | "enabled": false 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /samples/sample-alignment/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition 2 | 3 | plugins { 4 | id("org.gradlex.jvm-dependency-conflict-resolution") 5 | id("java-library") 6 | } 7 | 8 | dependencies { 9 | implementation("org.apache.sshd:sshd-common:2.8.0") 10 | implementation("org.apache.sshd:sshd-core:2.9.2") 11 | implementation("org.ow2.asm:asm:9.4") 12 | implementation("org.ow2.asm:asm-tree:9.3") 13 | implementation("org.eclipse.jetty:jetty-server:11.0.13") 14 | implementation("org.eclipse.jetty:jetty-servlet:11.0.0") 15 | implementation("org.eclipse.jetty.toolchain:jetty-test-helper:6.0") 16 | implementation("org.glassfish.jersey.core:jersey-common:3.1.0") 17 | implementation("org.glassfish.jersey.media:jersey-media-json-jackson:3.0.6") 18 | } 19 | 20 | jvmDependencyConflicts { 21 | conflictResolution { 22 | select(CapabilityDefinition.JAKARTA_ACTIVATION_API, "com.sun.activation:jakarta.activation") 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /samples/sample-alignment/build.sample.conf: -------------------------------------------------------------------------------- 1 | executable: gradlew 2 | expected-output-file: build.out -------------------------------------------------------------------------------- /samples/sample-alignment/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | // This is for testing against the latest version of the plugin, remove if you copied this for a real project 3 | if (extra.properties["pluginLocation"] != null) { 4 | includeBuild(extra.properties["pluginLocation"]!!) 5 | } else { 6 | includeBuild("../../") 7 | } 8 | } 9 | 10 | dependencyResolutionManagement { 11 | repositories.mavenCentral() 12 | } 13 | -------------------------------------------------------------------------------- /samples/sample-alignment/src/main/java/dummy/DummyClass.java: -------------------------------------------------------------------------------- 1 | package dummy; 2 | 3 | public class DummyClass { 4 | } 5 | -------------------------------------------------------------------------------- /samples/sample-all-deactivated/build.sample.conf: -------------------------------------------------------------------------------- 1 | executable: gradlew 2 | args: -s 3 | expected-output-file: build.out -------------------------------------------------------------------------------- /samples/sample-all-deactivated/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | // This is for testing against the latest version of the plugin, remove if you copied this for a real project 3 | if (extra.properties["pluginLocation"] != null) { 4 | includeBuild(extra.properties["pluginLocation"]!!) 5 | } else { 6 | includeBuild("../../") 7 | } 8 | } 9 | 10 | dependencyResolutionManagement { 11 | repositories { 12 | maven("https://maven.scijava.org/content/groups/public") { 13 | mavenContent { 14 | includeGroup("org.jzy3d") 15 | includeGroup("org.smurn") 16 | } 17 | } 18 | mavenCentral() { 19 | metadataSources.artifact() // woodstox/wstx-lgpl/3.2.7 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /samples/sample-all-deactivated/src/main/java/dummy/DummyClass.java: -------------------------------------------------------------------------------- 1 | package dummy; 2 | 3 | public class DummyClass { 4 | } 5 | -------------------------------------------------------------------------------- /samples/sample-all/build-scan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gradlex-org/jvm-dependency-conflict-resolution/5d34834083cd662732894f45fabca04ebccded86/samples/sample-all/build-scan.png -------------------------------------------------------------------------------- /samples/sample-all/build.sample.conf: -------------------------------------------------------------------------------- 1 | executable: gradlew 2 | args: detectCollisions 3 | expected-output-file: build.out -------------------------------------------------------------------------------- /samples/sample-all/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | // This is for testing against the latest version of the plugin, remove if you copied this for a real project 3 | if (extra.properties["pluginLocation"] != null) { 4 | includeBuild(extra.properties["pluginLocation"]!!) 5 | } else { 6 | includeBuild("../../") 7 | } 8 | } 9 | 10 | dependencyResolutionManagement { 11 | repositories { 12 | maven("https://maven.scijava.org/content/groups/public") { 13 | mavenContent { 14 | includeGroup("org.jzy3d") 15 | includeGroup("org.smurn") 16 | } 17 | } 18 | mavenCentral() { 19 | metadataSources.artifact() // woodstox/wstx-lgpl/3.2.7 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /samples/sample-all/src/main/java/dummy/DummyClass.java: -------------------------------------------------------------------------------- 1 | package dummy; 2 | 3 | public class DummyClass { 4 | } 5 | -------------------------------------------------------------------------------- /samples/sample-javax-and-jakarta/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("org.gradlex.jvm-dependency-conflict-resolution") 3 | id("application") 4 | } 5 | 6 | application { 7 | mainClass.set("dummy.DummyClass") 8 | } 9 | 10 | dependencies { 11 | implementation("org.apache.tomcat:tomcat-catalina:9.0.68") 12 | implementation("io.undertow:undertow-servlet:2.3.0.Final") 13 | } 14 | -------------------------------------------------------------------------------- /samples/sample-javax-and-jakarta/build.out: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------ 2 | Root project 'sample-javax-and-jakarta_build.sample' 3 | ------------------------------------------------------------ 4 | 5 | compileClasspath - Compile classpath for source set 'main'. 6 | +--- org.apache.tomcat:tomcat-catalina:9.0.68 7 | | +--- org.apache.tomcat:tomcat-servlet-api:9.0.68 8 | | +--- org.apache.tomcat:tomcat-jsp-api:9.0.68 9 | | | +--- org.apache.tomcat:tomcat-el-api:9.0.68 10 | | | \--- org.apache.tomcat:tomcat-servlet-api:9.0.68 11 | | +--- org.apache.tomcat:tomcat-juli:9.0.68 12 | | +--- org.apache.tomcat:tomcat-annotations-api:9.0.68 13 | | +--- org.apache.tomcat:tomcat-api:9.0.68 14 | | | \--- org.apache.tomcat:tomcat-servlet-api:9.0.68 15 | | +--- org.apache.tomcat:tomcat-jni:9.0.68 16 | | +--- org.apache.tomcat:tomcat-coyote:9.0.68 17 | | | +--- org.apache.tomcat:tomcat-servlet-api:9.0.68 18 | | | +--- org.apache.tomcat:tomcat-jni:9.0.68 19 | | | +--- org.apache.tomcat:tomcat-juli:9.0.68 20 | | | \--- org.apache.tomcat:tomcat-util:9.0.68 21 | | | \--- org.apache.tomcat:tomcat-juli:9.0.68 22 | | +--- org.apache.tomcat:tomcat-util:9.0.68 (*) 23 | | +--- org.apache.tomcat:tomcat-util-scan:9.0.68 24 | | | +--- org.apache.tomcat:tomcat-util:9.0.68 (*) 25 | | | +--- org.apache.tomcat:tomcat-juli:9.0.68 26 | | | \--- org.apache.tomcat:tomcat-api:9.0.68 (*) 27 | | \--- org.apache.tomcat:tomcat-jaspic-api:9.0.68 28 | \--- io.undertow:undertow-servlet:2.3.0.Final 29 | +--- io.undertow:undertow-core:2.3.0.Final 30 | | +--- org.jboss.logging:jboss-logging:3.4.3.Final 31 | | +--- org.jboss.xnio:xnio-api:3.8.8.Final 32 | | | +--- org.wildfly.common:wildfly-common:1.5.4.Final 33 | | | \--- org.wildfly.client:wildfly-client-config:1.0.1.Final 34 | | | \--- org.jboss.logging:jboss-logging:3.3.1.Final -> 3.4.3.Final 35 | | \--- org.jboss.threads:jboss-threads:3.5.0.Final 36 | | \--- org.jboss.logging:jboss-logging:3.4.1.Final -> 3.4.3.Final 37 | +--- jakarta.servlet:jakarta.servlet-api:6.0.0 38 | \--- jakarta.annotation:jakarta.annotation-api:2.1.1 -------------------------------------------------------------------------------- /samples/sample-javax-and-jakarta/build.sample.conf: -------------------------------------------------------------------------------- 1 | executable: gradlew 2 | expected-output-file: build.out -------------------------------------------------------------------------------- /samples/sample-javax-and-jakarta/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | // This is for testing against the latest version of the plugin, remove if you copied this for a real project 3 | if (extra.properties["pluginLocation"] != null) { 4 | includeBuild(extra.properties["pluginLocation"]!!) 5 | } else { 6 | includeBuild("../../") 7 | } 8 | } 9 | 10 | dependencyResolutionManagement { 11 | repositories.mavenCentral() 12 | } 13 | -------------------------------------------------------------------------------- /samples/sample-javax-and-jakarta/src/main/java/dummy/DummyClass.java: -------------------------------------------------------------------------------- 1 | package dummy; 2 | 3 | import io.undertow.servlet.handlers.ServletHandler; 4 | 5 | public class DummyClass { 6 | 7 | public static void main(String[] args) { 8 | System.out.println(ServletHandler.class.getName()); 9 | new ServletHandler(null); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | import buildparameters.BuildParametersExtension 2 | 3 | pluginManagement { 4 | includeBuild("gradle/plugins") 5 | } 6 | 7 | plugins { 8 | id("com.gradle.develocity") version "4.0.2" 9 | id("gradlexbuild.build-parameters") 10 | } 11 | 12 | rootProject.name = "jvm-dependency-conflict-resolution" 13 | 14 | dependencyResolutionManagement { 15 | repositories.mavenCentral() 16 | } 17 | 18 | develocity { 19 | buildScan { 20 | // required until we can upgrade to Gradle 8.8 21 | val buildParameters = the() 22 | if (buildParameters.ci) { 23 | termsOfUseUrl = "https://gradle.com/help/legal-terms-of-use" 24 | termsOfUseAgree = "yes" 25 | } else { 26 | publishing.onlyIf { false } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/docs/asciidoc/images/build-scan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gradlex-org/jvm-dependency-conflict-resolution/5d34834083cd662732894f45fabca04ebccded86/src/docs/asciidoc/images/build-scan.png -------------------------------------------------------------------------------- /src/docs/samples/plugin-dependency/groovy/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | repositories.gradlePluginPortal() 6 | 7 | // tag::plugin-dependency[] 8 | dependencies { 9 | implementation 'org.gradlex:jvm-dependency-conflict-resolution:2.4' 10 | } 11 | // end::plugin-dependency[] -------------------------------------------------------------------------------- /src/docs/samples/plugin-dependency/kotlin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("java") 3 | } 4 | 5 | repositories.gradlePluginPortal() 6 | 7 | // tag::plugin-dependency[] 8 | dependencies { 9 | implementation("org.gradlex:jvm-dependency-conflict-resolution:2.4") 10 | } 11 | // end::plugin-dependency[] -------------------------------------------------------------------------------- /src/docs/samples/plugin-dependency/primer.sample.conf: -------------------------------------------------------------------------------- 1 | commands: [{ 2 | execution-subdirectory: kotlin 3 | executable: gradle 4 | args: "help" 5 | },{ 6 | execution-subdirectory: groovy 7 | executable: gradle 8 | args: "help" 9 | }] 10 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/JvmDependencyConflictDetectionPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection; 18 | 19 | import org.gradle.api.Plugin; 20 | import org.gradle.api.Project; 21 | import org.gradle.api.artifacts.dsl.ComponentMetadataHandler; 22 | import org.gradle.api.initialization.Settings; 23 | import org.gradle.api.plugins.ExtensionAware; 24 | import org.gradle.api.plugins.JvmEcosystemPlugin; 25 | import org.gradle.util.GradleVersion; 26 | import org.gradlex.jvm.dependency.conflict.detection.rules.AlignmentDefinition; 27 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 28 | 29 | public class JvmDependencyConflictDetectionPlugin implements Plugin { 30 | 31 | // Minimal version that works reliably with alignment, has the substitution rules `using` API 32 | // and has rulesMode setting in dependencyResolutionManagement 33 | private static final GradleVersion MINIMUM_SUPPORTED_VERSION = GradleVersion.version("6.8.3"); 34 | 35 | @Override 36 | public void apply(ExtensionAware projectOrSettings) { 37 | if (GradleVersion.current().compareTo(MINIMUM_SUPPORTED_VERSION) < 0) { 38 | throw new IllegalStateException("Plugin requires at least Gradle " + MINIMUM_SUPPORTED_VERSION.getVersion()); 39 | } 40 | 41 | ComponentMetadataHandler components; 42 | if (projectOrSettings instanceof Project) { 43 | // Make sure 'jvm-ecosystem' is applied which adds the schemas for the attributes this plugin relies on 44 | ((Project) projectOrSettings).getPlugins().apply(JvmEcosystemPlugin.class); 45 | components = ((Project) projectOrSettings).getDependencies().getComponents(); 46 | } else if (projectOrSettings instanceof Settings) { 47 | //noinspection UnstableApiUsage 48 | components = ((Settings) projectOrSettings).getDependencyResolutionManagement().getComponents(); 49 | } else { 50 | throw new IllegalStateException("Cannot apply plugin to: " + projectOrSettings.getClass().getName()); 51 | } 52 | registerRules(components); 53 | } 54 | 55 | private void registerRules(ComponentMetadataHandler components) { 56 | for (CapabilityDefinition definition : CapabilityDefinition.values()) { 57 | registerCapabilityRule(definition, components); 58 | } 59 | for (AlignmentDefinition definition : AlignmentDefinition.values()) { 60 | registerAlignmentRule(definition, components); 61 | } 62 | } 63 | 64 | private void registerCapabilityRule(CapabilityDefinition definition, ComponentMetadataHandler components) { 65 | for (String module : definition.getModules()) { 66 | components.withModule(module, definition.getRuleClass(), ac -> ac.params(definition)); 67 | } 68 | } 69 | 70 | private void registerAlignmentRule(AlignmentDefinition definition, ComponentMetadataHandler components) { 71 | for (String module : definition.getModules()) { 72 | components.withModule(module, definition.getRuleClass(), ac -> ac.params(definition)); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @NonNullApi 18 | package org.gradlex.jvm.dependency.conflict.detection; 19 | 20 | import org.gradle.api.NonNullApi; -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/AlignmentDefinitionRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataDetails; 22 | import org.gradle.api.artifacts.ComponentMetadataRule; 23 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 24 | import org.gradle.api.attributes.Category; 25 | import org.gradle.api.model.ObjectFactory; 26 | 27 | import javax.inject.Inject; 28 | 29 | @CacheableRule 30 | public abstract class AlignmentDefinitionRule implements ComponentMetadataRule { 31 | 32 | private final AlignmentDefinition definition; 33 | 34 | @Inject 35 | public AlignmentDefinitionRule(AlignmentDefinition definition) { 36 | this.definition = definition; 37 | } 38 | 39 | @Inject 40 | protected abstract ObjectFactory getObjects(); 41 | 42 | @Override 43 | public final void execute(ComponentMetadataContext context) { 44 | ComponentMetadataDetails details = context.getDetails(); 45 | if (shouldApply(details.getId())) { 46 | if (definition.hasBom()) { 47 | applyWithBom(details); 48 | } else { 49 | applyWithoutBom(details); 50 | } 51 | } 52 | } 53 | 54 | void applyWithBom(ComponentMetadataDetails details) { 55 | String version = details.getId().getVersion(); 56 | details.allVariants(v -> v.withDependencies(dependencies -> dependencies.add(definition.getBom() + ":" + version, 57 | d -> d.attributes(a -> a.attribute(Category.CATEGORY_ATTRIBUTE, getObjects().named(Category.class, Category.REGULAR_PLATFORM)))))); 58 | } 59 | 60 | void applyWithoutBom(ComponentMetadataDetails details) { 61 | String version = details.getId().getVersion(); 62 | String group = details.getId().getGroup(); 63 | details.allVariants(v -> { 64 | v.withDependencyConstraints(c -> { 65 | for (String member : definition.getModules()) { 66 | if (member.contains(":")) { 67 | c.add(member + ":" + version); 68 | } else { 69 | c.add(group + ":" + member + ":" + version); 70 | } 71 | } 72 | }); 73 | }); 74 | } 75 | 76 | protected boolean shouldApply(ModuleVersionIdentifier id) { 77 | return true; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/CapabilityDefinitionRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 23 | import org.gradle.api.artifacts.VariantMetadata; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class CapabilityDefinitionRule implements ComponentMetadataRule { 29 | 30 | private final CapabilityDefinition definition; 31 | 32 | @Inject 33 | public CapabilityDefinitionRule(CapabilityDefinition definition) { 34 | this.definition = definition; 35 | } 36 | 37 | @Override 38 | public final void execute(ComponentMetadataContext context) { 39 | if (shouldApply(context.getDetails().getId())) { 40 | context.getDetails().allVariants(variant -> { 41 | variant.withCapabilities(capabilities -> { 42 | // remove capability if it already exists so that it can be added back 43 | // with a potentially different version 44 | capabilities.removeCapability( 45 | definition.getGroup(), definition.getCapabilityName() 46 | ); 47 | capabilities.addCapability( 48 | definition.getGroup(), definition.getCapabilityName(), getVersion(context.getDetails().getId()) 49 | ); 50 | }); 51 | additionalAdjustments(variant); 52 | }); 53 | } 54 | } 55 | 56 | protected boolean shouldApply(ModuleVersionIdentifier id) { 57 | return true; 58 | } 59 | 60 | protected String getVersion(ModuleVersionIdentifier id) { 61 | return id.getVersion(); 62 | } 63 | 64 | protected void additionalAdjustments(VariantMetadata variant) { } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/FixedVersionCapabilityDefinitionRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | 22 | import javax.inject.Inject; 23 | 24 | /** 25 | * Rule adding a capability with a hard coded version. 26 | */ 27 | @CacheableRule 28 | public abstract class FixedVersionCapabilityDefinitionRule extends CapabilityDefinitionRule { 29 | 30 | @Inject 31 | public FixedVersionCapabilityDefinitionRule(CapabilityDefinition capabilityDefinition) { 32 | super(capabilityDefinition); 33 | } 34 | 35 | @Override 36 | protected String getVersion(ModuleVersionIdentifier id) { 37 | return "1.0"; 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/aopalliance/AopallianceRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.aopalliance; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class AopallianceRule extends CapabilityDefinitionRule { 29 | 30 | // the conflict starts from Spring 4.3.0, before that it is effectively a correct dependency 31 | private static final String FIRST_AOP_EMBEDDED_VERSION = "4.3.0"; 32 | 33 | @Inject 34 | public AopallianceRule(CapabilityDefinition rule) { 35 | super(rule); 36 | } 37 | 38 | @Override 39 | protected boolean shouldApply(ModuleVersionIdentifier id) { 40 | return "aopalliance".equals(id.getGroup()) || VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_AOP_EMBEDDED_VERSION)) >= 0; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/aopalliance/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @NonNullApi 18 | package org.gradlex.jvm.dependency.conflict.detection.rules.aopalliance; 19 | 20 | import org.gradle.api.NonNullApi; -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/asm/AsmAlignmentRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.asm; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.AlignmentDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.AlignmentDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class AsmAlignmentRule extends AlignmentDefinitionRule { 29 | 30 | @Inject 31 | public AsmAlignmentRule(AlignmentDefinition definition) { 32 | super(definition); 33 | } 34 | 35 | @Override 36 | protected boolean shouldApply(ModuleVersionIdentifier id) { 37 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse("9.3")) >= 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/bouncycastle/BouncyCastleRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.bouncycastle; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | 24 | import javax.inject.Inject; 25 | 26 | @CacheableRule 27 | public abstract class BouncyCastleRule extends CapabilityDefinitionRule { 28 | 29 | @Inject 30 | public BouncyCastleRule(CapabilityDefinition rule) { 31 | super(rule); 32 | } 33 | 34 | @Override 35 | protected String getVersion(ModuleVersionIdentifier id) { 36 | // The 2.x LTS versions correspond to the 1.x non-lts versions 37 | String version = id.getVersion(); 38 | if (id.getName().contains("-lts") && version.startsWith("2.")) { 39 | return "1." + version.substring(2); 40 | } 41 | if (!version.contains(".")) { 42 | // Weird version: bcprov-jdk12:130 43 | return "1.0"; 44 | } 45 | return super.getVersion(id); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/bouncycastle/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @NonNullApi 18 | package org.gradlex.jvm.dependency.conflict.detection.rules.bouncycastle; 19 | 20 | import org.gradle.api.NonNullApi; -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/guava/GuavaListenableFutureRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.guava; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradle.api.artifacts.VariantMetadata; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 23 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class GuavaListenableFutureRule extends CapabilityDefinitionRule { 29 | 30 | @Inject 31 | public GuavaListenableFutureRule(CapabilityDefinition rule) { 32 | super(rule); 33 | } 34 | 35 | @Override 36 | protected String getVersion(ModuleVersionIdentifier id) { 37 | return "1.0"; 38 | } 39 | 40 | @Override 41 | protected void additionalAdjustments(VariantMetadata variant) { 42 | // Despite publishing Gradle Metadata for Guava 32.1+, this part was not adopted eventually 43 | // See: https://github.com/google/guava/issues/6642#issuecomment-1656201382 44 | // Remove workaround dependency to '9999.0-empty-to-avoid-conflict-with-guava' 45 | variant.withDependencies(dependencies -> dependencies.removeIf(d -> "listenablefuture".equals(d.getName()))); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/guava/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @NonNullApi 18 | package org.gradlex.jvm.dependency.conflict.detection.rules.guava; 19 | 20 | import org.gradle.api.NonNullApi; -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JakartaActivationApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JakartaActivationApiRule extends CapabilityDefinitionRule { 29 | 30 | @Inject 31 | public JakartaActivationApiRule(CapabilityDefinition rule) { 32 | super(rule); 33 | } 34 | 35 | @Override 36 | protected boolean shouldApply(ModuleVersionIdentifier id) { 37 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(JavaxActivationApiRule.FIRST_JAKARTA_VERSION)) >= 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JakartaActivationImplementationRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JakartaActivationImplementationRule extends CapabilityDefinitionRule { 29 | 30 | // Starting with this version the implementation moved to the 'org.eclipse' package and is no longer a conflict 31 | public static final String FIRST_ECLIPSE_VERSION = "2.0.0"; 32 | 33 | @Inject 34 | public JakartaActivationImplementationRule(CapabilityDefinition rule) { 35 | super(rule); 36 | } 37 | 38 | @Override 39 | protected boolean shouldApply(ModuleVersionIdentifier id) { 40 | return isSunJakartaActivationImpl(id) || isAngusJakartaActivationImpl(id); 41 | } 42 | 43 | private boolean isSunJakartaActivationImpl(ModuleVersionIdentifier id) { 44 | return "com.sun.activation".equals(id.getGroup()) 45 | && VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(JavaxActivationApiRule.FIRST_JAKARTA_VERSION)) >= 0; 46 | } 47 | 48 | private boolean isAngusJakartaActivationImpl(ModuleVersionIdentifier id) { 49 | return "org.eclipse.angus".equals(id.getGroup()) 50 | && VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_ECLIPSE_VERSION)) < 0; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JakartaAnnotationApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JakartaAnnotationApiRule extends CapabilityDefinitionRule { 29 | 30 | @Inject 31 | public JakartaAnnotationApiRule(CapabilityDefinition rule) { 32 | super(rule); 33 | } 34 | 35 | @Override 36 | protected String getVersion(ModuleVersionIdentifier id) { 37 | if ("org.apache.tomcat".equals(id.getGroup())) { 38 | return annotationApiVersionForTomcatVersion(VersionNumber.parse(id.getVersion())); 39 | } 40 | return id.getVersion(); 41 | } 42 | 43 | @Override 44 | protected boolean shouldApply(ModuleVersionIdentifier id) { 45 | return VersionNumber.parse(getVersion(id)).compareTo(VersionNumber.parse(JavaxAnnotationApiRule.FIRST_JAKARTA_VERSION)) >= 0; 46 | } 47 | 48 | // This is probably 100% accurate - older Tomcat versions might ship older 1.x specs 49 | private static String annotationApiVersionForTomcatVersion(VersionNumber tomcatVersion) { 50 | if (tomcatVersion.compareTo(VersionNumber.version(10, 0)) >= 0) { 51 | return "2.1.0"; 52 | } 53 | return "1.3.0"; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JakartaJwsApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JakartaJwsApiRule extends CapabilityDefinitionRule { 29 | 30 | private static final String JWS_MERGER_VERSION = "4.0.0"; 31 | 32 | @Inject 33 | public JakartaJwsApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | if (id.getName().equals("jakarta.xml.ws-api")) { 40 | return VersionNumber.parse(getVersion(id)).compareTo(VersionNumber.parse(JWS_MERGER_VERSION)) >= 0; 41 | } 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JakartaMailApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JakartaMailApiRule extends CapabilityDefinitionRule { 29 | 30 | @Inject 31 | public JakartaMailApiRule(CapabilityDefinition rule) { 32 | super(rule); 33 | } 34 | 35 | @Override 36 | protected boolean shouldApply(ModuleVersionIdentifier id) { 37 | // org.eclipse.angus has its own versioning, and everything is Jakarta 38 | return "org.eclipse.angus".equals(id.getGroup()) 39 | || VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(JavaxMailApiRule.FIRST_JAKARTA_VERSION)) >= 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JakartaServletApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JakartaServletApiRule extends CapabilityDefinitionRule { 29 | 30 | @Inject 31 | public JakartaServletApiRule(CapabilityDefinition rule) { 32 | super(rule); 33 | } 34 | 35 | @Override 36 | protected String getVersion(ModuleVersionIdentifier id) { 37 | if (id.getGroup().startsWith("org.apache.tomcat")) { 38 | return JavaxServletApiRule.servletApiVersionForTomcatVersion(VersionNumber.parse(id.getVersion())); 39 | } 40 | return id.getVersion(); 41 | } 42 | 43 | @Override 44 | protected boolean shouldApply(ModuleVersionIdentifier id) { 45 | return VersionNumber.parse(getVersion(id)).compareTo(VersionNumber.parse(JavaxServletApiRule.FIRST_JAKARTA_VERSION)) >= 0; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JakartaWebsocketApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JakartaWebsocketApiRule extends CapabilityDefinitionRule { 29 | 30 | @Inject 31 | public JakartaWebsocketApiRule(CapabilityDefinition rule) { 32 | super(rule); 33 | } 34 | 35 | @Override 36 | protected String getVersion(ModuleVersionIdentifier id) { 37 | if (id.getGroup().startsWith("org.apache.tomcat")) { 38 | return JavaxWebsocketApiRule.websocketApiVersionForTomcatVersion(VersionNumber.parse(id.getVersion())); 39 | } 40 | return id.getVersion(); 41 | } 42 | 43 | @Override 44 | protected boolean shouldApply(ModuleVersionIdentifier id) { 45 | return VersionNumber.parse(getVersion(id)).compareTo(VersionNumber.parse(JavaxWebsocketApiRule.FIRST_JAKARTA_VERSION)) >= 0; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JakartaWebsocketClientApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JakartaWebsocketClientApiRule extends CapabilityDefinitionRule { 29 | 30 | @Inject 31 | public JakartaWebsocketClientApiRule(CapabilityDefinition rule) { 32 | super(rule); 33 | } 34 | 35 | @Override 36 | protected String getVersion(ModuleVersionIdentifier id) { 37 | if (id.getGroup().startsWith("org.apache.tomcat")) { 38 | return JavaxWebsocketApiRule.websocketApiVersionForTomcatVersion(VersionNumber.parse(id.getVersion())); 39 | } 40 | return id.getVersion(); 41 | } 42 | 43 | @Override 44 | protected boolean shouldApply(ModuleVersionIdentifier id) { 45 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(JavaxWebsocketApiRule.FIRST_JAKARTA_VERSION)) >= 0; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JakartaWsRsApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | 24 | import javax.inject.Inject; 25 | 26 | @CacheableRule 27 | public abstract class JakartaWsRsApiRule extends CapabilityDefinitionRule { 28 | 29 | @Inject 30 | public JakartaWsRsApiRule(CapabilityDefinition rule) { 31 | super(rule); 32 | } 33 | 34 | @Override 35 | protected String getVersion(ModuleVersionIdentifier id) { 36 | if ("jakarta.ws.rs".equals(id.getGroup())) { 37 | return id.getVersion(); 38 | } 39 | return "3.0.0"; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxActivationApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxActivationApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "2.0.0"; 31 | 32 | @Inject 33 | public JavaxActivationApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxAnnotationApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxAnnotationApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "2.0.0"; 31 | 32 | @Inject 33 | public JavaxAnnotationApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(getVersion(id)).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | 42 | @Override 43 | protected String getVersion(ModuleVersionIdentifier id) { 44 | if ("org.apache.tomcat".equals(id.getGroup())) { 45 | return annotationApiVersionForTomcatVersion(VersionNumber.parse(id.getVersion())); 46 | } 47 | return id.getVersion(); 48 | } 49 | 50 | // This is probably 100% accurate - older Tomcat versions might ship older 1.x specs 51 | private static String annotationApiVersionForTomcatVersion(VersionNumber tomcatVersion) { 52 | if (tomcatVersion.compareTo(VersionNumber.version(10, 0)) >= 0) { 53 | return "2.1.0"; 54 | } 55 | return "1.3.0"; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxEjbApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxEjbApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "4.0.0"; 31 | 32 | @Inject 33 | public JavaxEjbApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxElApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxElApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "4.0.0"; 31 | 32 | @Inject 33 | public JavaxElApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxInjectApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxInjectApiRule extends CapabilityDefinitionRule { 29 | 30 | public static final String FIRST_JAKARTA_VERSION = "2.0.0"; 31 | 32 | @Inject 33 | public JavaxInjectApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(getVersion(id)).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | 42 | @Override 43 | protected String getVersion(ModuleVersionIdentifier id) { 44 | if ("org.glassfish.hk2.external".equals(id.getGroup())) { 45 | return "1"; 46 | } 47 | return id.getVersion(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxJsonApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxJsonApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "2.0.0"; 31 | 32 | @Inject 33 | public JavaxJsonApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxJwsApisRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxJwsApisRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "3.0.0"; 31 | 32 | @Inject 33 | public JavaxJwsApisRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(getVersion(id)).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxMailApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxMailApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "2.0.0"; 31 | 32 | @Inject 33 | public JavaxMailApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(getVersion(id)).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | 42 | @Override 43 | protected String getVersion(ModuleVersionIdentifier id) { 44 | String group = id.getGroup(); 45 | if (group.equals("org.apache.geronimo.javamail") || group.equals("org.apache.geronimo.specs")) { 46 | return mailApiVersionForGeronimoName(id.getName()); 47 | } 48 | return id.getVersion(); 49 | } 50 | 51 | private String mailApiVersionForGeronimoName(String name) { 52 | int index = "geronimo-javamail_".length(); 53 | return name.substring(index, index + 3) + ".0"; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxPersistenceApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxPersistenceApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "3.0.0"; 31 | 32 | @Inject 33 | public JavaxPersistenceApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxServletApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxServletApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "5.0.0"; 31 | 32 | @Inject 33 | public JavaxServletApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(getVersion(id)).compareTo(VersionNumber.parse(JavaxServletApiRule.FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | 42 | @Override 43 | protected String getVersion(ModuleVersionIdentifier id) { 44 | if (id.getGroup().startsWith("org.apache.tomcat")) { 45 | return servletApiVersionForTomcatVersion(VersionNumber.parse(id.getVersion())); 46 | } 47 | return id.getVersion(); 48 | } 49 | 50 | // https://tomcat.apache.org/whichversion.html 51 | static String servletApiVersionForTomcatVersion(VersionNumber tomcatVersion) { 52 | if (tomcatVersion.compareTo(VersionNumber.version(10, 1)) >= 0) { 53 | return "6.0.0"; 54 | } 55 | if (tomcatVersion.compareTo(VersionNumber.version(10, 0)) >= 0) { 56 | return "5.0.0"; 57 | } 58 | if (tomcatVersion.compareTo(VersionNumber.version(9, 0)) >= 0) { 59 | return "4.0.0"; 60 | } 61 | if (tomcatVersion.compareTo(VersionNumber.version(8, 0)) >= 0) { 62 | return "3.1.0"; 63 | } 64 | if (tomcatVersion.compareTo(VersionNumber.version(7, 0)) >= 0) { 65 | return "3.0.0"; 66 | } 67 | if (tomcatVersion.compareTo(VersionNumber.version(6, 0)) >= 0) { 68 | return "2.5.0"; 69 | } 70 | if (tomcatVersion.compareTo(VersionNumber.version(5, 5)) >= 0) { 71 | return "2.4.0"; 72 | } 73 | if (tomcatVersion.compareTo(VersionNumber.version(4, 1)) >= 0) { 74 | return "2.3"; 75 | } 76 | return "2.2"; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxServletJspRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxServletJspRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "3.0.0"; 31 | 32 | @Inject 33 | public JavaxServletJspRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxServletJstlRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxServletJstlRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "2.0.0"; 31 | 32 | @Inject 33 | public JavaxServletJstlRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxSoapApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxSoapApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "2.0.0"; 31 | 32 | @Inject 33 | public JavaxSoapApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxTransactionApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxTransactionApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "2.0.0"; 31 | 32 | @Inject 33 | public JavaxTransactionApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(getVersion(id)).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | 42 | @Override 43 | protected String getVersion(ModuleVersionIdentifier id) { 44 | String name = id.getName(); 45 | String moduleVersion = id.getVersion(); 46 | 47 | if (name.contains("jboss-transaction-api_")) { 48 | return transactionApiVersionForJbossName(name); 49 | } 50 | 51 | return moduleVersion; 52 | } 53 | 54 | private static String transactionApiVersionForJbossName(String name) { 55 | int index = "jboss-transaction-api_".length(); 56 | return name.substring(index, index + 3) + ".0"; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxValidationApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxValidationApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "3.0.0"; 31 | 32 | @Inject 33 | public JavaxValidationApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxWebsocketApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxWebsocketApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "2.0.0"; 31 | 32 | @Inject 33 | public JavaxWebsocketApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(getVersion(id)).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | 42 | @Override 43 | protected String getVersion(ModuleVersionIdentifier id) { 44 | if (id.getGroup().startsWith("org.apache.tomcat")) { 45 | return websocketApiVersionForTomcatVersion(VersionNumber.parse(id.getVersion())); 46 | } 47 | return id.getVersion(); 48 | } 49 | 50 | // https://tomcat.apache.org/whichversion.html 51 | static String websocketApiVersionForTomcatVersion(VersionNumber tomcatVersion) { 52 | if (tomcatVersion.compareTo(VersionNumber.version(10, 1)) >= 0) { 53 | return "2.1.0"; 54 | } 55 | if (tomcatVersion.compareTo(VersionNumber.version(10, 0)) >= 0) { 56 | return "2.0.0"; 57 | } 58 | return "1.1.0"; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxWsRsApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxWsRsApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "3.0.0"; 31 | 32 | @Inject 33 | public JavaxWsRsApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return "org.jboss.resteasy".equals(id.getGroup()) || VersionNumber.parse(getVersion(id)).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | 42 | @Override 43 | protected String getVersion(ModuleVersionIdentifier id) { 44 | String name = id.getName(); 45 | String moduleVersion = id.getVersion(); 46 | 47 | if (name.contains("jboss-jaxrs-api_")) { 48 | return rsApiVersionForJbossName(name); 49 | } 50 | if (moduleVersion.endsWith(".Final")) { 51 | return moduleVersion.substring(0, moduleVersion.indexOf(".Final")); 52 | } 53 | if (moduleVersion.endsWith(".GA")) { 54 | return moduleVersion.substring(0, moduleVersion.indexOf(".GA")); 55 | } 56 | 57 | return moduleVersion; 58 | } 59 | 60 | private static String rsApiVersionForJbossName(String name) { 61 | int index = "jboss-jaxrs-api_".length(); 62 | return name.substring(index, index + 3) + ".0"; 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxXmlBindApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxXmlBindApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "3.0.0"; 31 | 32 | @Inject 33 | public JavaxXmlBindApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/JavaxXmlWsApiRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JavaxXmlWsApiRule extends CapabilityDefinitionRule { 29 | 30 | static final String FIRST_JAKARTA_VERSION = "3.0.0"; 31 | 32 | @Inject 33 | public JavaxXmlWsApiRule(CapabilityDefinition rule) { 34 | super(rule); 35 | } 36 | 37 | @Override 38 | protected boolean shouldApply(ModuleVersionIdentifier id) { 39 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse(FIRST_JAKARTA_VERSION)) < 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jakarta/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @NonNullApi 18 | package org.gradlex.jvm.dependency.conflict.detection.rules.jakarta; 19 | 20 | import org.gradle.api.NonNullApi; -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/jetty/JettyAlignmentRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.jetty; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.AlignmentDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.AlignmentDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class JettyAlignmentRule extends AlignmentDefinitionRule { 29 | 30 | @Inject 31 | public JettyAlignmentRule(AlignmentDefinition definition) { 32 | super(definition); 33 | } 34 | 35 | @Override 36 | protected boolean shouldApply(ModuleVersionIdentifier id) { 37 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse("9.3.19.v20170502")) >= 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/logging/Log4J2Alignment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.logging; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.AlignmentDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.AlignmentDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class Log4J2Alignment extends AlignmentDefinitionRule { 29 | 30 | @Inject 31 | public Log4J2Alignment(AlignmentDefinition definition) { 32 | super(definition); 33 | } 34 | 35 | @Override 36 | protected boolean shouldApply(ModuleVersionIdentifier id) { 37 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse("2.0")) >= 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/logging/LoggingModuleIdentifiers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.logging; 18 | 19 | import org.gradle.api.artifacts.Dependency; 20 | 21 | public enum LoggingModuleIdentifiers { 22 | LOG4J_SLF4J_IMPL("org.apache.logging.log4j", "log4j-slf4j-impl", "2.0"), 23 | LOG4J_SLF4J2_IMPL("org.apache.logging.log4j", "log4j-slf4j2-impl", "2.19.0"), 24 | LOG4J_TO_SLF4J("org.apache.logging.log4j", "log4j-to-slf4j", "2.0"), 25 | SLF4J_SIMPLE("org.slf4j", "slf4j-simple", "1.0"), 26 | SLF4J_NOP("org.slf4j", "slf4j-nop", "1.0"), 27 | LOGBACK_CLASSIC("ch.qos.logback", "logback-classic", "1.0.0"), 28 | SLF4J_LOG4J12("org.slf4j", "slf4j-log4j12", "1.0"), 29 | SLF4J_JCL("org.slf4j", "slf4j-jcl", "1.0"), 30 | SLF4J_JDK14("org.slf4j", "slf4j-jdk14", "1.0"), 31 | LOG4J_OVER_SLF4J("org.slf4j", "log4j-over-slf4j", "1.4.2"), 32 | LOG4J12API("org.apache.logging.log4j", "log4j-1.2-api", "2.0"), 33 | LOG4J("log4j", "log4j", "1.1.3"), 34 | JUL_TO_SLF4J("org.slf4j", "jul-to-slf4j", "1.5.10"), 35 | LOG4J_JUL("org.apache.logging.log4j", "log4j-jul", "2.1"), 36 | COMMONS_LOGGING("commons-logging", "commons-logging", "1.0"), 37 | JCL_OVER_SLF4J("org.slf4j", "jcl-over-slf4j", "1.5.10"), 38 | LOG4J_JCL("org.apache.logging.log4j", "log4j-jcl", "2.0"), 39 | LOG4J_CORE("org.apache.logging.log4j", "log4j-core", "2.0"), 40 | SPRING_JCL("org.springframework", "spring-jcl", "5.0.0.RELEASE"); 41 | 42 | public final String moduleId; 43 | public final String group; 44 | public final String name; 45 | private final String firstVersion; 46 | 47 | LoggingModuleIdentifiers(String group, String name, String firstVersion) { 48 | this.group = group; 49 | this.name = name; 50 | this.firstVersion = firstVersion; 51 | this.moduleId = group + ":" + name; 52 | } 53 | 54 | public boolean matches(Dependency dependency) { 55 | return group.equals(dependency.getGroup()) && name.equals(dependency.getName()); 56 | } 57 | 58 | public String asFirstVersion() { 59 | return moduleId + ":" + firstVersion; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/logging/Slf4J2Alignment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.logging; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.AlignmentDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.AlignmentDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class Slf4J2Alignment extends AlignmentDefinitionRule { 29 | 30 | @Inject 31 | public Slf4J2Alignment(AlignmentDefinition definition) { 32 | super(definition); 33 | } 34 | 35 | @Override 36 | protected boolean shouldApply(ModuleVersionIdentifier id) { 37 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse("2.0.8")) >= 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/logging/Slf4JAlignment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.detection.rules.logging; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.AlignmentDefinition; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.AlignmentDefinitionRule; 23 | import org.gradlex.jvm.dependency.conflict.detection.util.VersionNumber; 24 | 25 | import javax.inject.Inject; 26 | 27 | @CacheableRule 28 | public abstract class Slf4JAlignment extends AlignmentDefinitionRule { 29 | 30 | @Inject 31 | public Slf4JAlignment(AlignmentDefinition definition) { 32 | super(definition); 33 | } 34 | 35 | @Override 36 | protected boolean shouldApply(ModuleVersionIdentifier id) { 37 | return VersionNumber.parse(id.getVersion()).compareTo(VersionNumber.parse("2.0.8")) < 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/logging/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @NonNullApi 18 | package org.gradlex.jvm.dependency.conflict.detection.rules.logging; 19 | 20 | import org.gradle.api.NonNullApi; -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @NonNullApi 18 | package org.gradlex.jvm.dependency.conflict.detection.rules; 19 | 20 | import org.gradle.api.NonNullApi; -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/ConflictResolution.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution; 18 | 19 | import org.gradle.api.artifacts.CapabilityResolutionDetails; 20 | import org.gradle.api.artifacts.ComponentVariantIdentifier; 21 | import org.gradle.api.artifacts.ConfigurationContainer; 22 | import org.gradle.api.artifacts.component.ComponentIdentifier; 23 | import org.gradle.api.artifacts.component.ModuleComponentIdentifier; 24 | import org.gradle.api.provider.SetProperty; 25 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 26 | 27 | import javax.inject.Inject; 28 | import java.util.Arrays; 29 | import java.util.Optional; 30 | 31 | public abstract class ConflictResolution { 32 | 33 | @Inject 34 | protected abstract ConfigurationContainer getConfigurations(); 35 | 36 | abstract SetProperty getDeactivatedResolutionStrategies(); 37 | 38 | public void deactivateResolutionStrategy(CapabilityDefinition capability) { 39 | getDeactivatedResolutionStrategies().add(capability); 40 | } 41 | 42 | public void deactivateResolutionStrategy(String capability) { 43 | Optional definition = Arrays.stream(CapabilityDefinition.values()).filter(c -> capability.equals(c.getCapability())).findFirst(); 44 | definition.ifPresent(c -> getDeactivatedResolutionStrategies().add(c)); 45 | } 46 | 47 | public void selectHighestVersion(CapabilityDefinition capability) { 48 | deactivateResolutionStrategy(capability); 49 | doSelectHighestVersion(capability.getCapability()); 50 | } 51 | 52 | public void selectHighestVersion(String capability) { 53 | deactivateResolutionStrategy(capability); 54 | doSelectHighestVersion(capability); 55 | } 56 | 57 | public void select(CapabilityDefinition capability, String module) { 58 | deactivateResolutionStrategy(capability); 59 | doSelect(capability.getCapability(), module, false); 60 | } 61 | 62 | public void select(String capability, String module) { 63 | deactivateResolutionStrategy(capability); 64 | doSelect(capability, module, false); 65 | } 66 | 67 | public void selectLenient(CapabilityDefinition capability, String module) { 68 | deactivateResolutionStrategy(capability); 69 | doSelect(capability.getCapability(), module, true); 70 | } 71 | 72 | private void selectLenient(String capability, String module) { 73 | deactivateResolutionStrategy(capability); 74 | doSelect(capability, module, true); 75 | } 76 | 77 | private void doSelectHighestVersion(String capability) { 78 | getConfigurations().configureEach(conf -> conf.getResolutionStrategy().getCapabilitiesResolution().withCapability(capability, 79 | CapabilityResolutionDetails::selectHighestVersion)); 80 | } 81 | 82 | private void doSelect(String capability, String module, boolean lenient) { 83 | String group = module.split(":")[0]; 84 | String name = module.split(":")[1]; 85 | getConfigurations().configureEach(conf -> conf.getResolutionStrategy().getCapabilitiesResolution().withCapability(capability, c -> { 86 | for (ComponentVariantIdentifier candidate : c.getCandidates()) { 87 | ComponentIdentifier id = candidate.getId(); 88 | if (id instanceof ModuleComponentIdentifier 89 | && ((ModuleComponentIdentifier) id).getGroup().equals(group) 90 | && ((ModuleComponentIdentifier) id).getModule().equals(name)) { 91 | c.select(candidate); 92 | return; 93 | } 94 | } 95 | if (lenient && !c.getCandidates().isEmpty()) { 96 | c.select(c.getCandidates().get(0)); 97 | } 98 | })); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/DefaultResolutionStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution; 18 | 19 | public enum DefaultResolutionStrategy { 20 | HIGHEST_VERSION, 21 | FIRST_MODULE, 22 | NONE 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/JvmDependencyConflictDetectionPluginApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution; 18 | 19 | import org.gradle.api.Project; 20 | import org.gradle.api.initialization.resolve.RulesMode; 21 | import org.gradle.api.internal.GradleInternal; 22 | import org.gradle.api.internal.SettingsInternal; 23 | import org.gradlex.jvm.dependency.conflict.detection.JvmDependencyConflictDetectionPlugin; 24 | 25 | final class JvmDependencyConflictDetectionPluginApplication { 26 | 27 | private static final String PLUGIN_ID = "org.gradlex.jvm-dependency-conflict-detection"; 28 | 29 | static JvmDependencyConflictDetectionPluginApplication of(Project project) { 30 | return new JvmDependencyConflictDetectionPluginApplication(project); 31 | } 32 | 33 | private final Project project; 34 | 35 | private JvmDependencyConflictDetectionPluginApplication(Project project) { 36 | this.project = project; 37 | } 38 | 39 | void handleRulesMode() { 40 | boolean baseAppliedViaSettings = isBaseAppliedViaSettings(); 41 | RulesMode rulesMode = getRulesMode(); 42 | String settingsFileName = getSettings().getSettingsScript().getFileName(); 43 | switch(rulesMode) { 44 | // PREFER_PROJECT is the default if the user did not configure something else 45 | case PREFER_PROJECT: 46 | project.getPlugins().apply(JvmDependencyConflictDetectionPlugin.class); 47 | break; 48 | case PREFER_SETTINGS: 49 | case FAIL_ON_PROJECT_RULES: 50 | if (!baseAppliedViaSettings) { 51 | throw new IllegalStateException( 52 | "RulesMode is set to " + rulesMode + " in " + settingsFileName + " but the '" + PLUGIN_ID + "' plugin was not applied via settings." + 53 | " As a result this plugin will not work." + 54 | " Fix this problem by either changing dependencyResolutionManagement.rulesMode to PREFER_PROJECT or by applying '" + PLUGIN_ID + "' as a settings plugin in " + settingsFileName + "." 55 | ); 56 | } 57 | break; 58 | default: 59 | throw new IllegalStateException("Unknown RulesMode value '" + rulesMode + "'"); 60 | } 61 | } 62 | 63 | private boolean isBaseAppliedViaSettings() { 64 | return getSettings().getPlugins().hasPlugin(JvmDependencyConflictDetectionPlugin.class); 65 | } 66 | 67 | private RulesMode getRulesMode() { 68 | return getSettings().getDependencyResolutionManagement().getRulesMode().get(); 69 | } 70 | 71 | private SettingsInternal getSettings() { 72 | return ((GradleInternal) project.getGradle()).getSettings(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/JvmDependencyConflictResolutionPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution; 18 | 19 | import org.gradle.api.Plugin; 20 | import org.gradle.api.Project; 21 | import org.gradle.api.artifacts.CapabilitiesResolution; 22 | import org.gradle.api.artifacts.CapabilityResolutionDetails; 23 | import org.gradle.api.artifacts.ComponentVariantIdentifier; 24 | import org.gradle.api.artifacts.Configuration; 25 | import org.gradle.api.artifacts.ConfigurationContainer; 26 | import org.gradle.api.artifacts.component.ModuleComponentIdentifier; 27 | import org.gradle.api.plugins.JvmEcosystemPlugin; 28 | import org.gradle.api.tasks.SourceSetContainer; 29 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition; 30 | 31 | import java.util.Optional; 32 | 33 | import static org.gradlex.jvm.dependency.conflict.resolution.DefaultResolutionStrategy.FIRST_MODULE; 34 | import static org.gradlex.jvm.dependency.conflict.resolution.DefaultResolutionStrategy.HIGHEST_VERSION; 35 | 36 | public abstract class JvmDependencyConflictResolutionPlugin implements Plugin { 37 | public static final String MAIN_RUNTIME_CLASSPATH_CONFIGURATION_NAME = "mainRuntimeClasspath"; 38 | public static final String INTERNAL_CONFIGURATION_NAME = "internal"; 39 | 40 | @Override 41 | public void apply(Project project) { 42 | JvmDependencyConflictDetectionPluginApplication.of(project).handleRulesMode(); 43 | 44 | // Make sure 'jvm-ecosystem' is applied which adds the schemas for the attributes this plugin relies on 45 | project.getPlugins().apply(JvmEcosystemPlugin.class); 46 | 47 | JvmDependencyConflictsExtension jvmDependencyConflicts = project.getExtensions().create( 48 | "jvmDependencyConflicts", 49 | JvmDependencyConflictsExtension.class, 50 | project.getExtensions().getByType(SourceSetContainer.class) 51 | ); 52 | 53 | configureResolutionStrategies(project.getConfigurations(), jvmDependencyConflicts); 54 | } 55 | 56 | private void configureResolutionStrategies(ConfigurationContainer configurations, JvmDependencyConflictsExtension jvmDependencyConflicts) { 57 | configurations.configureEach(configuration -> { 58 | for (CapabilityDefinition definition : CapabilityDefinition.values()) { 59 | defineStrategy(definition, configuration, jvmDependencyConflicts); 60 | } 61 | }); 62 | } 63 | 64 | private void defineStrategy(CapabilityDefinition definition, Configuration configuration, JvmDependencyConflictsExtension jvmDependencyConflicts) { 65 | CapabilitiesResolution resolution = configuration.getResolutionStrategy().getCapabilitiesResolution(); 66 | resolution.withCapability(definition.getCapability(), details -> { 67 | if (!jvmDependencyConflicts.getConflictResolution().getDeactivatedResolutionStrategies().get().contains(definition)) { 68 | if (definition.getDefaultStrategy() == HIGHEST_VERSION) { 69 | details.selectHighestVersion(); 70 | } else if (definition.getDefaultStrategy() == FIRST_MODULE) { 71 | select(details, definition.getModules().get(0)); 72 | } 73 | } 74 | }); 75 | } 76 | 77 | private void select(CapabilityResolutionDetails details, String moduleGA) { 78 | Optional module = details.getCandidates().stream().filter(c -> { 79 | if (c.getId() instanceof ModuleComponentIdentifier) { 80 | return ((ModuleComponentIdentifier) c.getId()).getModuleIdentifier().toString().equals(moduleGA); 81 | } 82 | return false; 83 | }).findFirst(); 84 | module.ifPresent(details::select); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/JvmDependencyConflictsExtension.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution; 18 | 19 | import org.gradle.api.Action; 20 | import org.gradle.api.model.ObjectFactory; 21 | import org.gradle.api.tasks.SourceSetContainer; 22 | 23 | import javax.inject.Inject; 24 | 25 | public abstract class JvmDependencyConflictsExtension { 26 | 27 | private final ConflictResolution conflictResolution; 28 | private final Logging logging; 29 | private final Patch patch; 30 | private final ConsistentResolution consistentResolution; 31 | 32 | @Inject 33 | public JvmDependencyConflictsExtension(SourceSetContainer sourceSets) { 34 | conflictResolution = getObjects().newInstance(ConflictResolution.class); 35 | logging = getObjects().newInstance(Logging.class); 36 | patch = getObjects().newInstance(Patch.class); 37 | consistentResolution = getObjects().newInstance(ConsistentResolution.class, sourceSets); 38 | } 39 | 40 | @Inject 41 | protected abstract ObjectFactory getObjects(); 42 | 43 | public ConflictResolution getConflictResolution() { 44 | return conflictResolution; 45 | } 46 | 47 | public void conflictResolution(Action action) { 48 | action.execute(conflictResolution); 49 | } 50 | 51 | public Logging getLogging() { 52 | return logging; 53 | } 54 | 55 | public void logging(Action action) { 56 | action.execute(logging); 57 | } 58 | 59 | public Patch getPatch() { 60 | return patch; 61 | } 62 | 63 | public void patch(Action action) { 64 | action.execute(patch); 65 | } 66 | 67 | public ConsistentResolution getConsistentResolution() { 68 | return consistentResolution; 69 | } 70 | 71 | public void consistentResolution(Action action) { 72 | action.execute(consistentResolution); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/Patch.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution; 18 | 19 | import org.gradle.api.Action; 20 | import org.gradle.api.artifacts.dsl.DependencyHandler; 21 | import org.gradle.api.model.ObjectFactory; 22 | import org.gradlex.jvm.dependency.conflict.resolution.rules.AddAlignmentConstraintsMetadataRule; 23 | import org.gradlex.jvm.dependency.conflict.resolution.rules.AddBomDependencyMetadataRule; 24 | 25 | import javax.inject.Inject; 26 | import java.util.Arrays; 27 | 28 | public abstract class Patch { 29 | 30 | @Inject 31 | protected abstract ObjectFactory getObjects(); 32 | 33 | @Inject 34 | protected abstract DependencyHandler getDependencies(); 35 | 36 | /** 37 | * Adjust metadata of the given 'module'. 38 | */ 39 | public PatchModule module(String module) { 40 | return getObjects().newInstance(PatchModule.class, module); 41 | } 42 | 43 | /** 44 | * Adjust metadata of the given 'module'. 45 | */ 46 | public void module(String module, Action action) { 47 | action.execute(getObjects().newInstance(PatchModule.class, module)); 48 | } 49 | 50 | /** 51 | * Align the versions of all 'modules' by adding a platform dependency to each module that points at the given 'bom'. 52 | */ 53 | public void alignWithBom(String bom, String... modules) { 54 | for (String module : modules) { 55 | getDependencies().getComponents().withModule(module, AddBomDependencyMetadataRule.class, r -> r.params(bom)); 56 | } 57 | } 58 | 59 | /** 60 | * Align the versions of all 'modules' by adding version constraints for all modules to each module. 61 | */ 62 | public void align(String... modules) { 63 | for (String module : modules) { 64 | getDependencies().getComponents().withModule(module, AddAlignmentConstraintsMetadataRule.class, r -> r.params(Arrays.asList(modules))); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/Slf4JEnforcementSubstitutionsUsing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution; 18 | 19 | import org.gradle.api.Action; 20 | import org.gradle.api.artifacts.Configuration; 21 | import org.gradle.api.artifacts.component.ComponentSelector; 22 | import org.gradlex.jvm.dependency.conflict.detection.rules.logging.LoggingModuleIdentifiers; 23 | 24 | class Slf4JEnforcementSubstitutionsUsing implements Action { 25 | 26 | private final String onlyApplyTo; 27 | 28 | public Slf4JEnforcementSubstitutionsUsing() { 29 | this.onlyApplyTo = null; 30 | } 31 | 32 | public Slf4JEnforcementSubstitutionsUsing(String onlyApplyTo) { 33 | this.onlyApplyTo = onlyApplyTo; 34 | } 35 | 36 | @Override 37 | public void execute(Configuration configuration) { 38 | if (onlyApplyTo != null && !configuration.getName().equals(onlyApplyTo)) { 39 | return; 40 | } 41 | configuration.getResolutionStrategy().dependencySubstitution(substitution -> { 42 | ComponentSelector log4JOverSlf4J = substitution.module(LoggingModuleIdentifiers.LOG4J_OVER_SLF4J.asFirstVersion()); 43 | substitution.substitute(substitution.module(LoggingModuleIdentifiers.LOG4J.moduleId)).using(log4JOverSlf4J); 44 | substitution.substitute(substitution.module(LoggingModuleIdentifiers.LOG4J12API.moduleId)).using(log4JOverSlf4J); 45 | 46 | substitution.substitute(substitution.module(LoggingModuleIdentifiers.LOG4J_JUL.moduleId)).using(substitution.module(LoggingModuleIdentifiers.JUL_TO_SLF4J.asFirstVersion())); 47 | 48 | ComponentSelector jclOverSlf4J = substitution.module(LoggingModuleIdentifiers.JCL_OVER_SLF4J.asFirstVersion()); 49 | substitution.substitute(substitution.module(LoggingModuleIdentifiers.COMMONS_LOGGING.moduleId)).using(jclOverSlf4J); 50 | substitution.substitute(substitution.module(LoggingModuleIdentifiers.LOG4J_JCL.moduleId)).using(jclOverSlf4J); 51 | substitution.substitute(substitution.module(LoggingModuleIdentifiers.SPRING_JCL.moduleId)).using(jclOverSlf4J); 52 | }); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @NonNullApi 18 | package org.gradlex.jvm.dependency.conflict.resolution; 19 | 20 | import org.gradle.api.NonNullApi; -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/AddAlignmentConstraintsMetadataRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | 23 | import javax.inject.Inject; 24 | import java.util.List; 25 | 26 | /** 27 | * See: 28 | * blog.gradle.org/alignment-with-gradle-module-metadata 29 | */ 30 | @CacheableRule 31 | public abstract class AddAlignmentConstraintsMetadataRule implements ComponentMetadataRule { 32 | 33 | private final List components; 34 | 35 | @Inject 36 | public AddAlignmentConstraintsMetadataRule(List components) { 37 | this.components = components; 38 | } 39 | 40 | @Override 41 | public void execute(ComponentMetadataContext context) { 42 | String version = context.getDetails().getId().getVersion(); 43 | String group = context.getDetails().getId().getGroup(); 44 | context.getDetails().allVariants(v -> { 45 | v.withDependencyConstraints(c -> { 46 | for (String member : components) { 47 | if (member.contains(":")) { 48 | c.add(member + ":" + version); 49 | } else { 50 | c.add(group + ":" + member + ":" + version); 51 | } 52 | } 53 | }); 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/AddApiDependencyMetadataRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | import org.gradle.api.attributes.Category; 23 | import org.gradle.api.attributes.Usage; 24 | 25 | import javax.inject.Inject; 26 | 27 | import static org.gradlex.jvm.dependency.conflict.resolution.rules.VariantSelection.allVariantsMatching; 28 | 29 | /** 30 | * See: 31 | * 32 | * component_metadata_rules.html#fixing_wrong_dependency_details 33 | */ 34 | @CacheableRule 35 | public abstract class AddApiDependencyMetadataRule implements ComponentMetadataRule { 36 | 37 | private final String dependency; 38 | 39 | @Inject 40 | public AddApiDependencyMetadataRule(String dependency) { 41 | this.dependency = dependency; 42 | } 43 | 44 | @Override 45 | public void execute(ComponentMetadataContext context) { 46 | allVariantsMatching(context, 47 | id -> (id.matches(Usage.USAGE_ATTRIBUTE, Usage.JAVA_API) || id.matches(Usage.USAGE_ATTRIBUTE, Usage.JAVA_RUNTIME)) && id.matches(Category.CATEGORY_ATTRIBUTE, Category.LIBRARY), 48 | v -> v.withDependencies(d -> d.add(dependency))); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/AddBomDependencyMetadataRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | import org.gradle.api.attributes.Category; 23 | import org.gradle.api.model.ObjectFactory; 24 | 25 | import javax.inject.Inject; 26 | 27 | /** 28 | * See: 29 | * 30 | * component_metadata_rules.html#fixing_wrong_dependency_details 31 | */ 32 | @CacheableRule 33 | public abstract class AddBomDependencyMetadataRule implements ComponentMetadataRule { 34 | 35 | private final String bom; 36 | 37 | @Inject 38 | public AddBomDependencyMetadataRule(String bom) { 39 | this.bom = bom; 40 | } 41 | 42 | @Inject 43 | protected abstract ObjectFactory getObjects(); 44 | 45 | @Override 46 | public void execute(ComponentMetadataContext context) { 47 | String version = context.getDetails().getId().getVersion(); 48 | context.getDetails().allVariants(v -> v.withDependencies(dependencies -> dependencies.add(bom + ":" + version, 49 | d -> d.attributes(a -> a.attribute(Category.CATEGORY_ATTRIBUTE, getObjects().named(Category.class, Category.REGULAR_PLATFORM)))))); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/AddCapabilityMetadataRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 23 | 24 | import javax.inject.Inject; 25 | /** 26 | * See: 27 | * 28 | * component_metadata_rules.html#adding_missing_capabilities_to_detect_conflicts, 29 | * blog.gradle.org/addressing-logging-complexity-capabilities 30 | */ 31 | @CacheableRule 32 | public abstract class AddCapabilityMetadataRule implements ComponentMetadataRule { 33 | 34 | private final String capability; 35 | 36 | @Inject 37 | public AddCapabilityMetadataRule(String capability) { 38 | this.capability = capability; 39 | } 40 | 41 | @Override 42 | public void execute(ComponentMetadataContext context) { 43 | ModuleVersionIdentifier id = context.getDetails().getId(); 44 | String group = capability.split(":")[0]; 45 | String name = capability.split(":")[1]; 46 | String version = id.getVersion(); 47 | 48 | context.getDetails().allVariants(v -> v.withCapabilities(c -> c.addCapability(group, name, version))); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/AddCompileOnlyApiDependencyMetadataRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | import org.gradle.api.attributes.Category; 23 | import org.gradle.api.attributes.Usage; 24 | 25 | import javax.inject.Inject; 26 | 27 | import static org.gradlex.jvm.dependency.conflict.resolution.rules.VariantSelection.allVariantsMatching; 28 | 29 | /** 30 | * See: 31 | * 32 | * component_metadata_rules.html#fixing_wrong_dependency_details 33 | */ 34 | @CacheableRule 35 | public abstract class AddCompileOnlyApiDependencyMetadataRule implements ComponentMetadataRule { 36 | 37 | private final String dependency; 38 | 39 | @Inject 40 | public AddCompileOnlyApiDependencyMetadataRule(String dependency) { 41 | this.dependency = dependency; 42 | } 43 | 44 | @Override 45 | public void execute(ComponentMetadataContext context) { 46 | allVariantsMatching(context, 47 | id -> (id.matches(Usage.USAGE_ATTRIBUTE, Usage.JAVA_API) && id.matches(Category.CATEGORY_ATTRIBUTE, Category.LIBRARY)), 48 | v -> v.withDependencies(d -> d.add(dependency))); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/AddFeatureMetadataRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 23 | 24 | import javax.inject.Inject; 25 | 26 | /** 27 | * See: 28 | * 29 | * component_metadata_rules.html#making_different_flavors_of_a_library_available_through_capabilities, 30 | * blog.gradle.org/optional-dependencies 31 | */ 32 | @CacheableRule 33 | public abstract class AddFeatureMetadataRule implements ComponentMetadataRule { 34 | 35 | private final String classifier; 36 | 37 | @Inject 38 | public AddFeatureMetadataRule(String classifier) { 39 | this.classifier = classifier; 40 | } 41 | 42 | @Override 43 | public void execute(ComponentMetadataContext context) { 44 | addFeatureVariant(context, classifier, "Compile", "compile"); 45 | addFeatureVariant(context, classifier, "Runtime", "runtime"); 46 | } 47 | 48 | private static void addFeatureVariant(ComponentMetadataContext context, String classifier, String nameSuffix, String baseVariant) { 49 | ModuleVersionIdentifier id = context.getDetails().getId(); 50 | String group = id.getGroup(); 51 | String name = id.getName(); 52 | String version = id.getVersion(); 53 | 54 | context.getDetails().addVariant(classifier + nameSuffix, baseVariant, v -> { 55 | v.withCapabilities(c -> { 56 | c.removeCapability(group, name); 57 | c.addCapability(group, name + "-" + classifier, version); 58 | }); 59 | v.withFiles(f -> { 60 | f.removeAllFiles(); 61 | f.addFile(name + "-" + version + "-" + classifier + ".jar"); 62 | }); 63 | }); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/AddRuntimeOnlyDependencyMetadataRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | import org.gradle.api.attributes.Category; 23 | import org.gradle.api.attributes.Usage; 24 | 25 | import javax.inject.Inject; 26 | 27 | import static org.gradlex.jvm.dependency.conflict.resolution.rules.VariantSelection.allVariantsMatching; 28 | 29 | /** 30 | * See: 31 | * 32 | * component_metadata_rules.html#fixing_wrong_dependency_details 33 | */ 34 | @CacheableRule 35 | public abstract class AddRuntimeOnlyDependencyMetadataRule implements ComponentMetadataRule { 36 | 37 | private final String dependency; 38 | 39 | @Inject 40 | public AddRuntimeOnlyDependencyMetadataRule(String dependency) { 41 | this.dependency = dependency; 42 | } 43 | 44 | @Override 45 | public void execute(ComponentMetadataContext context) { 46 | allVariantsMatching(context, 47 | id -> id.matches(Usage.USAGE_ATTRIBUTE, Usage.JAVA_RUNTIME) && id.matches(Category.CATEGORY_ATTRIBUTE, Category.LIBRARY), 48 | v -> v.withDependencies(d -> d.add(dependency))); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/AddTargetPlatformVariantsMetadataRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataDetails; 22 | import org.gradle.api.artifacts.ComponentMetadataRule; 23 | import org.gradle.api.artifacts.VariantMetadata; 24 | import org.gradle.api.model.ObjectFactory; 25 | import org.gradle.nativeplatform.MachineArchitecture; 26 | import org.gradle.nativeplatform.OperatingSystemFamily; 27 | 28 | import javax.inject.Inject; 29 | 30 | import static org.gradle.nativeplatform.MachineArchitecture.ARCHITECTURE_ATTRIBUTE; 31 | import static org.gradle.nativeplatform.OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTE; 32 | 33 | /** 34 | * See: 35 | * 36 | * component_metadata_rules.html#adding_variants_for_native_jars 37 | */ 38 | @CacheableRule 39 | public abstract class AddTargetPlatformVariantsMetadataRule implements ComponentMetadataRule { 40 | 41 | private final String feature; 42 | private final String classifier; 43 | private final String operatingSystem; 44 | private final String architecture; 45 | 46 | @Inject 47 | abstract protected ObjectFactory getObjects(); 48 | 49 | @Inject 50 | public AddTargetPlatformVariantsMetadataRule(String feature, String classifier, String operatingSystem, String architecture) { 51 | this.feature = feature; 52 | this.classifier = classifier; 53 | this.operatingSystem = operatingSystem; 54 | this.architecture = architecture; 55 | } 56 | 57 | @Override 58 | public void execute(ComponentMetadataContext context) { 59 | ComponentMetadataDetails details = context.getDetails(); 60 | if (classifier.isEmpty()) { 61 | if (!feature.isEmpty()) { 62 | throw new IllegalStateException("if classifier is empty, feature must be empty too."); 63 | } 64 | details.withVariant("compile", this::configureAttributes); 65 | details.withVariant("runtime", this::configureAttributes); 66 | } else { 67 | addTargetPlatformVariant(details, "Compile", "compile"); 68 | addTargetPlatformVariant(details, "Runtime", "runtime"); 69 | } 70 | } 71 | 72 | private void addTargetPlatformVariant(ComponentMetadataDetails details, String nameSuffix, String baseVariant) { 73 | String group = details.getId().getGroup(); 74 | String name = details.getId().getName(); 75 | String version = details.getId().getVersion(); 76 | 77 | details.addVariant(classifier + nameSuffix, baseVariant, variant -> { 78 | if (!feature.isEmpty()) { 79 | variant.withCapabilities(c -> { 80 | c.removeCapability(group, name); 81 | c.addCapability(group, name + "-" + feature, version); 82 | }); 83 | } 84 | configureAttributes(variant); 85 | variant.withFiles(files -> { 86 | files.removeAllFiles(); 87 | files.addFile(name + "-" + version + "-" + classifier + ".jar"); 88 | }); 89 | }); 90 | } 91 | 92 | private void configureAttributes(VariantMetadata variant) { 93 | variant.attributes(attributes -> { 94 | attributes.attribute(OPERATING_SYSTEM_ATTRIBUTE, getObjects().named(OperatingSystemFamily.class, operatingSystem)); 95 | attributes.attribute(ARCHITECTURE_ATTRIBUTE, getObjects().named(MachineArchitecture.class, architecture)); 96 | }); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/ComponentStatusRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | 23 | import javax.inject.Inject; 24 | import java.util.List; 25 | 26 | /** 27 | * Sets status of component versions that are not final releases to 'integration' instead of 'release'. 28 | * Otherwise, they are considered when asking for the 'latest.release' version. 29 | * POM metadata does not support the 'status' concept and thus Gradle assumes everything is a 'release' by default. 30 | * See: component_metadata_rules.html#sec:custom_status_scheme 31 | */ 32 | @CacheableRule 33 | public abstract class ComponentStatusRule implements ComponentMetadataRule { 34 | 35 | private final List integrationVersionMarker; 36 | 37 | @Inject 38 | public ComponentStatusRule(List integrationVersionMarker) { 39 | this.integrationVersionMarker = integrationVersionMarker; 40 | } 41 | 42 | @Override 43 | public void execute(ComponentMetadataContext context) { 44 | String version = context.getDetails().getId().getVersion().toLowerCase(); 45 | if (integrationVersionMarker.stream().anyMatch(version::contains)) { 46 | context.getDetails().setStatus("integration"); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/ReduceToCompileOnlyApiDependencyMetadataRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | import org.gradle.api.attributes.Category; 23 | import org.gradle.api.attributes.Usage; 24 | 25 | import javax.inject.Inject; 26 | import java.util.stream.Collectors; 27 | 28 | import static org.gradlex.jvm.dependency.conflict.resolution.rules.VariantSelection.allVariantsMatching; 29 | 30 | /** 31 | * See: 32 | * 33 | * component_metadata_rules.html#fixing_wrong_dependency_details 34 | */ 35 | @CacheableRule 36 | public abstract class ReduceToCompileOnlyApiDependencyMetadataRule implements ComponentMetadataRule { 37 | 38 | private final String dependency; 39 | 40 | @Inject 41 | public ReduceToCompileOnlyApiDependencyMetadataRule(String dependency) { 42 | this.dependency = dependency; 43 | } 44 | 45 | @Override 46 | public void execute(ComponentMetadataContext context) { 47 | allVariantsMatching(context, 48 | id -> id.matches(Usage.USAGE_ATTRIBUTE, Usage.JAVA_RUNTIME) && id.matches(Category.CATEGORY_ATTRIBUTE, Category.LIBRARY), 49 | v -> v.withDependencies(d -> d.removeAll(d.stream().filter(it -> dependency.equals(it.getModule().toString())).collect(Collectors.toList())))); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/ReduceToRuntimeOnlyDependencyMetadataRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | import org.gradle.api.attributes.Category; 23 | import org.gradle.api.attributes.Usage; 24 | 25 | import javax.inject.Inject; 26 | import java.util.stream.Collectors; 27 | 28 | import static org.gradlex.jvm.dependency.conflict.resolution.rules.VariantSelection.allVariantsMatching; 29 | 30 | /** 31 | * See: 32 | * 33 | * component_metadata_rules.html#fixing_wrong_dependency_details 34 | */ 35 | @CacheableRule 36 | public abstract class ReduceToRuntimeOnlyDependencyMetadataRule implements ComponentMetadataRule { 37 | 38 | private final String dependency; 39 | 40 | @Inject 41 | public ReduceToRuntimeOnlyDependencyMetadataRule(String dependency) { 42 | this.dependency = dependency; 43 | } 44 | 45 | @Override 46 | public void execute(ComponentMetadataContext context) { 47 | allVariantsMatching(context, 48 | id -> id.matches(Usage.USAGE_ATTRIBUTE, Usage.JAVA_API) && id.matches(Category.CATEGORY_ATTRIBUTE, Category.LIBRARY), 49 | v -> v.withDependencies(d -> d.removeAll(d.stream().filter(it -> dependency.equals(it.getModule().toString())).collect(Collectors.toList())))); // .module 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/RemoveCapabilityMetadataRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | import org.gradle.api.artifacts.ModuleVersionIdentifier; 23 | 24 | import javax.inject.Inject; 25 | 26 | /** 27 | * See: 28 | * 29 | * component_metadata_rules.html#adding_missing_capabilities_to_detect_conflicts, 30 | * blog.gradle.org/addressing-logging-complexity-capabilities 31 | */ 32 | @CacheableRule 33 | public abstract class RemoveCapabilityMetadataRule implements ComponentMetadataRule { 34 | 35 | private final String capability; 36 | 37 | @Inject 38 | public RemoveCapabilityMetadataRule(String capability) { 39 | this.capability = capability; 40 | } 41 | 42 | @Override 43 | public void execute(ComponentMetadataContext context) { 44 | ModuleVersionIdentifier id = context.getDetails().getId(); 45 | String group = capability.split(":")[0]; 46 | String name = capability.split(":")[1]; 47 | 48 | context.getDetails().allVariants(v -> v.withCapabilities(c -> c.removeCapability(group, name))); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/RemoveDependencyMetadataRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.artifacts.CacheableRule; 20 | import org.gradle.api.artifacts.ComponentMetadataContext; 21 | import org.gradle.api.artifacts.ComponentMetadataRule; 22 | import org.gradle.api.attributes.Category; 23 | import org.gradle.api.attributes.Usage; 24 | 25 | import javax.inject.Inject; 26 | import java.util.stream.Collectors; 27 | 28 | import static org.gradlex.jvm.dependency.conflict.resolution.rules.VariantSelection.allVariantsMatching; 29 | 30 | /** 31 | * See: 32 | * 33 | * component_metadata_rules.html#fixing_wrong_dependency_details 34 | */ 35 | @CacheableRule 36 | public abstract class RemoveDependencyMetadataRule implements ComponentMetadataRule { 37 | 38 | private final String dependency; 39 | 40 | @Inject 41 | public RemoveDependencyMetadataRule(String dependency) { 42 | this.dependency = dependency; 43 | } 44 | 45 | @Override 46 | public void execute(ComponentMetadataContext context) { 47 | allVariantsMatching(context, 48 | id -> (id.matches(Usage.USAGE_ATTRIBUTE, Usage.JAVA_API) || id.matches(Usage.USAGE_ATTRIBUTE, Usage.JAVA_RUNTIME)) && id.matches(Category.CATEGORY_ATTRIBUTE, Category.LIBRARY), 49 | v -> v.withDependencies(d -> d.removeAll(d.stream().filter(it -> dependency.equals(it.getModule().toString())).collect(Collectors.toList())))); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/VariantIdentification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 18 | 19 | import org.gradle.api.Named; 20 | import org.gradle.api.attributes.Attribute; 21 | 22 | import java.util.Map; 23 | import java.util.Objects; 24 | 25 | class VariantIdentification { 26 | 27 | private final Map attributes; 28 | 29 | VariantIdentification(Map attributes) { 30 | this.attributes = attributes; 31 | } 32 | 33 | boolean matches(Attribute attribute, String value) { 34 | return matches(attribute.getName(), value); 35 | } 36 | 37 | boolean matches(String attribute, String value) { 38 | return Objects.equals(attributes.get(attribute), value); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/gradlex/jvm/dependency/conflict/resolution/rules/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @NonNullApi 18 | package org.gradlex.jvm.dependency.conflict.resolution.rules; 19 | 20 | import org.gradle.api.NonNullApi; -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/AopAllianceMinVersionTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradlex.jvm.dependency.conflict.test 2 | 3 | import org.gradlex.jvm.dependency.conflict.test.fixture.GradleBuild 4 | import spock.lang.Specification 5 | import spock.lang.Unroll 6 | 7 | class AopAllianceMinVersionTest extends Specification { 8 | 9 | @Delegate 10 | GradleBuild build = new GradleBuild() 11 | 12 | def setup() { 13 | settingsFile << """ 14 | pluginManagement { 15 | repositories.mavenCentral() 16 | } 17 | """ 18 | } 19 | 20 | @Unroll 21 | def "include aopalliance for older spring-aop v#springVersion"(String springVersion) { 22 | given: 23 | buildFile << """ 24 | plugins { 25 | id("org.gradlex.jvm-dependency-conflict-resolution") 26 | id("java-library") 27 | } 28 | 29 | repositories { 30 | mavenCentral() 31 | google() 32 | } 33 | 34 | dependencies { 35 | implementation("aopalliance:aopalliance:1.0") 36 | implementation("org.springframework:spring-aop:${springVersion}") 37 | } 38 | 39 | tasks.register("printJars") { 40 | println(configurations.compileClasspath.get().files.joinToString("\\n") { it.name }); 41 | } 42 | """ 43 | 44 | expect: 45 | def jars = printJars().output.trim().split("\n").toList() 46 | jars.contains("aopalliance-1.0.jar") 47 | jars.contains("spring-aop-" + springVersion + ".jar") 48 | 49 | where: 50 | springVersion << [ "4.2.9.RELEASE", "4.1.9.RELEASE", "4.0.9.RELEASE", "3.2.18.RELEASE", "3.1.4.RELEASE", "3.0.7.RELEASE" ] 51 | } 52 | 53 | @Unroll 54 | def "exclude aopalliance for older spring-aop v#springVersion"(String springVersion) { 55 | given: 56 | buildFile << """ 57 | plugins { 58 | id("org.gradlex.jvm-dependency-conflict-resolution") 59 | id("java-library") 60 | } 61 | 62 | repositories { 63 | mavenCentral() 64 | google() 65 | } 66 | 67 | dependencies { 68 | implementation("aopalliance:aopalliance:1.0") 69 | implementation("org.springframework:spring-aop:${springVersion}") 70 | } 71 | 72 | tasks.register("printJars") { 73 | println(configurations.compileClasspath.get().files.joinToString("\\n") { it.name }); 74 | } 75 | """ 76 | 77 | expect: 78 | def jars = printJars().output.trim().split("\n").toList() 79 | !jars.contains("aopalliance-1.0.jar") 80 | jars.contains("spring-aop-" + springVersion + ".jar") 81 | 82 | where: 83 | springVersion << [ "4.3.30.RELEASE", "5.0.20.RELEASE", "5.1.20.RELEASE", "5.2.25.RELEASE", "5.3.31" ] 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/CapabilityWithDifferentVersionsTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradlex.jvm.dependency.conflict.test 2 | 3 | import org.gradlex.jvm.dependency.conflict.test.fixture.GradleBuild 4 | import spock.lang.Specification 5 | 6 | import static org.gradlex.jvm.dependency.conflict.test.fixture.GradleBuild.GRADLE6_TEST 7 | 8 | class CapabilityWithDifferentVersionsTest extends Specification { 9 | 10 | @Delegate 11 | GradleBuild build = new GradleBuild() 12 | 13 | def "does not fail if capability is added several times with different versions"() { 14 | given: 15 | buildFile << """ 16 | plugins { 17 | id("org.gradlex.jvm-dependency-conflict-detection") apply false 18 | id("java-library") 19 | } 20 | repositories.mavenCentral() 21 | dependencies.components { 22 | withModule("com.google.guava:guava") { 23 | allVariants { 24 | withCapabilities { 25 | addCapability("com.google.guava", "listenablefuture", 26 | "9999.0-empty-to-avoid-conflict-with-guava") 27 | } 28 | } 29 | } 30 | } 31 | 32 | apply(plugin = "org.gradlex.jvm-dependency-conflict-detection") 33 | 34 | dependencies { 35 | api("com.google.guava:guava:33.0.0-jre") 36 | } 37 | 38 | tasks.register("printJars") { 39 | println(configurations.compileClasspath.get().files.joinToString("\\n") { it.name }) 40 | } 41 | """ 42 | if (GRADLE6_TEST) { configureEnvAttribute() } 43 | 44 | expect: 45 | printJars() 46 | } 47 | 48 | def "does not fail with empty listenable future dependency on the classpath"() { 49 | given: 50 | buildFile << """ 51 | plugins { 52 | id("org.gradlex.jvm-dependency-conflict-resolution") 53 | id("java-library") 54 | } 55 | tasks.withType().configureEach { 56 | options.release.set(17) 57 | } 58 | repositories.mavenCentral() 59 | dependencies { 60 | implementation(platform("com.google.cloud:spring-cloud-gcp-dependencies:5.2.0")) 61 | implementation("com.google.cloud:spring-cloud-gcp-starter-bigquery") 62 | } 63 | 64 | tasks.register("printJars") { 65 | println(configurations.compileClasspath.get().files.joinToString("\\n") { it.name }) 66 | } 67 | """ 68 | if (GRADLE6_TEST) { configureEnvAttribute() } 69 | 70 | expect: 71 | printJars() 72 | } 73 | 74 | void configureEnvAttribute() { 75 | buildFile << """ 76 | val envAttribute = Attribute.of("org.gradle.jvm.environment", String::class.java) 77 | configurations.compileClasspath { 78 | attributes.attribute(envAttribute, "standard-jvm") 79 | } 80 | """ 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/ComponentStatusRuleTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradlex.jvm.dependency.conflict.test 2 | 3 | import org.gradlex.jvm.dependency.conflict.test.fixture.GradleBuild 4 | import spock.lang.IgnoreIf 5 | import spock.lang.Specification 6 | 7 | @IgnoreIf({ GradleBuild.GRADLE6_TEST || GradleBuild.GRADLE7_TEST }) 8 | class ComponentStatusRuleTest extends Specification { 9 | 10 | @Delegate 11 | GradleBuild build = new GradleBuild() 12 | 13 | def setup() { 14 | buildFile << """ 15 | import org.gradlex.jvm.dependency.conflict.resolution.rules.* 16 | plugins { 17 | id("org.gradlex.jvm-dependency-conflict-resolution") 18 | id("java-library") 19 | } 20 | repositories.mavenCentral() 21 | dependencies.components { 22 | all() { params(listOf( 23 | "-b", "alpha", "beta", "cr", "m", "rc" 24 | ))} 25 | } 26 | """ 27 | } 28 | 29 | def "status of non-released versions is set to integration"() { 30 | given: 31 | buildFile << """ 32 | dependencies { 33 | implementation("com.sun.activation:jakarta.activation:2.0.0-rc1") 34 | implementation("com.sun.mail:jakarta.mail:2.0.0-RC6") 35 | implementation("jakarta.servlet:jakarta.servlet-api:5.0.0-M2") 36 | implementation("org.jboss.resteasy:resteasy-client:5.0.0.Beta3") 37 | implementation("org.slf4j:slf4j-api:2.0.0-alpha1") 38 | } 39 | """ 40 | 41 | expect: 42 | status('com.sun.activation:jakarta.activation') == 'integration' 43 | status('com.sun.mail:jakarta.mail') == 'integration' 44 | status('jakarta.servlet:jakarta.servlet-api') == 'integration' 45 | status('org.jboss.resteasy:resteasy-client') == 'integration' 46 | status('org.slf4j:slf4j-api') == 'integration' 47 | } 48 | 49 | def "status of released versions stays release"() { 50 | given: 51 | buildFile << """ 52 | dependencies { 53 | implementation("com.sun.activation:jakarta.activation:2.0.0") 54 | implementation("com.sun.mail:jakarta.mail:2.0.0") 55 | implementation("jakarta.servlet:jakarta.servlet-api:5.0.0") 56 | implementation("org.jboss.resteasy:resteasy-client:5.0.0.Final") 57 | implementation("org.slf4j:slf4j-api:2.0.0") 58 | } 59 | """ 60 | 61 | expect: 62 | status('com.sun.activation:jakarta.activation') == 'release' 63 | status('com.sun.mail:jakarta.mail') == 'release' 64 | status('jakarta.servlet:jakarta.servlet-api') == 'release' 65 | status('org.jboss.resteasy:resteasy-client') == 'release' 66 | status('org.slf4j:slf4j-api') == 'release' 67 | } 68 | 69 | private String status(String module) { 70 | dependencyInsight(module).output.readLines().find { it.contains('org.gradle.status') }.split('\\|')[2].trim() 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/RulesModeTest.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.test 18 | 19 | import org.gradlex.jvm.dependency.conflict.test.fixture.GradleBuild 20 | import spock.lang.Specification 21 | import spock.lang.Tag 22 | 23 | @Tag("no-cross-version") 24 | class RulesModeTest extends Specification { 25 | 26 | @Delegate 27 | GradleBuild build = new GradleBuild() 28 | 29 | def "applying the plugin in a project without rulesMode configured works"() { 30 | given: 31 | buildFile << """ 32 | plugins { 33 | id("org.gradlex.jvm-dependency-conflict-resolution") 34 | } 35 | """ 36 | 37 | expect: 38 | build() 39 | } 40 | 41 | def "applying the plugin in a project with rulesMode set to FAIL_ON_PROJECT_RULES fails the build"() { 42 | given: 43 | settingsFile << """ 44 | dependencyResolutionManagement { 45 | rulesMode = RulesMode.FAIL_ON_PROJECT_RULES 46 | } 47 | """ 48 | 49 | and: 50 | buildFile << """ 51 | plugins { 52 | id("org.gradlex.jvm-dependency-conflict-resolution") 53 | } 54 | """ 55 | 56 | when: 57 | def result = fail() 58 | 59 | then: 60 | result.output.contains("RulesMode is set to FAIL_ON_PROJECT_RULES") 61 | result.output.contains("As a result this plugin will not work.") 62 | result.output.contains("Fix this problem by either changing dependencyResolutionManagement.rulesMode to PREFER_PROJECT or by applying 'org.gradlex.jvm-dependency-conflict-detection' as a settings plugin") 63 | } 64 | 65 | def "applying the plugin in a project and applying the base plugin in settings with rulesMode set to FAIL_ON_PROJECT_RULES works"() { 66 | given: 67 | settingsFile << """ 68 | plugins { 69 | id("org.gradlex.jvm-dependency-conflict-detection") 70 | } 71 | 72 | dependencyResolutionManagement { 73 | rulesMode = RulesMode.FAIL_ON_PROJECT_RULES 74 | } 75 | """ 76 | 77 | and: 78 | buildFile << """ 79 | plugins { 80 | id("org.gradlex.jvm-dependency-conflict-resolution") 81 | } 82 | """ 83 | 84 | expect: 85 | build() 86 | } 87 | 88 | def "applying the plugin in a project without applying the base plugin in settings and rulesMode set to PREFER_SETTINGS fails the build"() { 89 | given: 90 | settingsFile << """ 91 | dependencyResolutionManagement { 92 | rulesMode = RulesMode.PREFER_SETTINGS 93 | } 94 | """ 95 | 96 | and: 97 | buildFile << """ 98 | plugins { 99 | id("org.gradlex.jvm-dependency-conflict-resolution") 100 | } 101 | """ 102 | 103 | when: 104 | def result = fail() 105 | 106 | then: 107 | result.output.contains("RulesMode is set to PREFER_SETTINGS") 108 | result.output.contains("As a result this plugin will not work.") 109 | result.output.contains("Fix this problem by either changing dependencyResolutionManagement.rulesMode to PREFER_PROJECT or by applying 'org.gradlex.jvm-dependency-conflict-detection' as a settings plugin") 110 | } 111 | 112 | def "applying the plugin in a project and applying the base plugin in settings and rulesMode set to PREFER_SETTINGS works"() { 113 | given: 114 | settingsFile << """ 115 | plugins { 116 | id("org.gradlex.jvm-dependency-conflict-detection") 117 | } 118 | 119 | dependencyResolutionManagement { 120 | rulesMode = RulesMode.PREFER_SETTINGS 121 | } 122 | """ 123 | 124 | and: 125 | buildFile << """ 126 | plugins { 127 | id("org.gradlex.jvm-dependency-conflict-resolution") 128 | } 129 | """ 130 | 131 | expect: 132 | build() 133 | } 134 | 135 | def "applying the plugin in a project with rulesMode set to PREFER_PROJECT works, because the base plugin is applied to the project"() { 136 | given: 137 | settingsFile << """ 138 | dependencyResolutionManagement { 139 | rulesMode = RulesMode.PREFER_PROJECT 140 | } 141 | """ 142 | 143 | and: 144 | buildFile << """ 145 | plugins { 146 | id("org.gradlex.jvm-dependency-conflict-resolution") 147 | } 148 | """ 149 | 150 | expect: 151 | build() 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/SettingsTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradlex.jvm.dependency.conflict.test 2 | 3 | import org.gradlex.jvm.dependency.conflict.test.fixture.GradleBuild 4 | import spock.lang.Specification 5 | import spock.lang.Tag 6 | 7 | class SettingsTest extends Specification { 8 | 9 | @Delegate 10 | GradleBuild build = new GradleBuild() 11 | 12 | @Tag("no-cross-version") 13 | def "plugin can be applied in settings file"() { 14 | given: 15 | settingsFile << """ 16 | plugins { 17 | id("org.gradlex.jvm-dependency-conflict-detection") 18 | } 19 | """ 20 | buildFile << """ 21 | import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition 22 | 23 | plugins { 24 | id("java-library") 25 | } 26 | 27 | repositories.mavenCentral() 28 | 29 | configurations.all { 30 | resolutionStrategy.capabilitiesResolution { 31 | withCapability(CapabilityDefinition.CGLIB.capability) { 32 | select("cglib:cglib:0") 33 | } 34 | withCapability(CapabilityDefinition.JAVAX_MAIL_API.capability) { 35 | select("com.sun.mail:jakarta.mail:0") 36 | } 37 | withCapability(CapabilityDefinition.JAVAX_WS_RS_API.capability) { 38 | select("org.jboss.resteasy:jaxrs-api:0") 39 | } 40 | withCapability(CapabilityDefinition.JAKARTA_SERVLET_API.capability) { 41 | select("jakarta.servlet:jakarta.servlet-api:0") 42 | } 43 | } 44 | } 45 | 46 | dependencies { 47 | implementation("cglib:cglib-nodep:3.2.10") 48 | implementation("cglib:cglib:3.2.10") 49 | implementation("com.sun.mail:jakarta.mail:1.6.7") 50 | implementation("com.sun.mail:mailapi:1.6.7") 51 | implementation("jakarta.servlet:jakarta.servlet-api:5.0.0") 52 | implementation("org.apache.tomcat:tomcat-servlet-api:10.0.18") 53 | } 54 | """ 55 | 56 | expect: 57 | dependenciesCompile().output.contains ''' 58 | compileClasspath - Compile classpath for source set 'main'. 59 | +--- cglib:cglib-nodep:3.2.10 -> cglib:cglib:3.2.10 60 | | +--- org.ow2.asm:asm:7.0 61 | | \\--- org.apache.ant:ant:1.10.3 62 | | \\--- org.apache.ant:ant-launcher:1.10.3 63 | +--- cglib:cglib:3.2.10 (*) 64 | +--- com.sun.mail:jakarta.mail:1.6.7 65 | | \\--- com.sun.activation:jakarta.activation:1.2.1 66 | +--- com.sun.mail:mailapi:1.6.7 -> com.sun.mail:jakarta.mail:1.6.7 (*) 67 | +--- jakarta.servlet:jakarta.servlet-api:5.0.0 68 | \\--- org.apache.tomcat:tomcat-servlet-api:10.0.18 -> jakarta.servlet:jakarta.servlet-api:5.0.0 69 | '''.stripIndent() 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/fixture/GradleBuild.groovy: -------------------------------------------------------------------------------- 1 | package org.gradlex.jvm.dependency.conflict.test.fixture 2 | 3 | import org.gradle.testkit.runner.BuildResult 4 | import org.gradle.testkit.runner.GradleRunner 5 | 6 | import java.lang.management.ManagementFactory 7 | import java.nio.file.Files 8 | 9 | class GradleBuild { 10 | 11 | final File projectDir 12 | final File settingsFile 13 | final File buildFile 14 | final File propertiesFile 15 | 16 | final static String GRADLE_VERSION_UNDER_TEST = System.getProperty("gradleVersionUnderTest") 17 | final static boolean GRADLE6_TEST = GRADLE_VERSION_UNDER_TEST?.startsWith("6.") 18 | final static boolean GRADLE7_TEST = GRADLE_VERSION_UNDER_TEST?.startsWith("7.") 19 | 20 | GradleBuild(File projectDir = Files.createTempDirectory("gradle-build").toFile()) { 21 | this.projectDir = projectDir 22 | this.settingsFile = file("settings.gradle.kts") 23 | this.buildFile = file("build.gradle.kts") 24 | this.propertiesFile = file("gradle.properties") 25 | 26 | settingsFile << ''' 27 | rootProject.name = "test-project" 28 | ''' 29 | buildFile << ''' 30 | ''' 31 | propertiesFile << ''' 32 | ''' 33 | } 34 | 35 | File file(String path) { 36 | new File(projectDir, path).tap { 37 | it.getParentFile().mkdirs() 38 | } 39 | } 40 | 41 | BuildResult build() { 42 | runner('build').build() 43 | } 44 | 45 | BuildResult fail() { 46 | runner('build').buildAndFail() 47 | } 48 | 49 | BuildResult printJars() { 50 | runner('printJars').build() 51 | } 52 | 53 | BuildResult dependenciesCompile() { 54 | runner('dependencies', '--configuration=compileClasspath').build() 55 | } 56 | 57 | BuildResult dependenciesRuntime() { 58 | runner('dependencies', '--configuration=runtimeClasspath').build() 59 | } 60 | 61 | BuildResult dependencyInsight(String module) { 62 | runner('dependencyInsight', '--configuration=compileClasspath', '--dependency', module).build() 63 | } 64 | 65 | GradleRunner runner(String... args) { 66 | List latestFeaturesArgs = GRADLE_VERSION_UNDER_TEST ? [] : [ 67 | '--configuration-cache', 68 | '-Dorg.gradle.unsafe.isolated-projects=true' 69 | ] 70 | GradleRunner.create() 71 | .forwardOutput() 72 | .withPluginClasspath() 73 | .withProjectDir(projectDir) 74 | .withArguments(Arrays.asList(args) + latestFeaturesArgs + '-s' + '-q') 75 | .withDebug(ManagementFactory.getRuntimeMXBean().getInputArguments().toString().contains("-agentlib:jdwp")).with { 76 | GRADLE_VERSION_UNDER_TEST ? it.withGradleVersion(GRADLE_VERSION_UNDER_TEST) : it 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/issues/Issue243Test.groovy: -------------------------------------------------------------------------------- 1 | package org.gradlex.jvm.dependency.conflict.test.issues 2 | 3 | import org.gradlex.jvm.dependency.conflict.test.fixture.GradleBuild 4 | import spock.lang.Issue 5 | import spock.lang.Specification 6 | 7 | @Issue("https://github.com/gradlex-org/jvm-dependency-conflict-resolution/issues/243") 8 | class Issue243Test extends Specification { 9 | 10 | @Delegate 11 | GradleBuild build = new GradleBuild() 12 | 13 | def "works for older versions"() { 14 | given: 15 | buildFile << """ 16 | plugins { 17 | id("org.gradlex.jvm-dependency-conflict-detection") 18 | id("java-library") 19 | } 20 | 21 | repositories { 22 | mavenCentral() 23 | } 24 | 25 | dependencies { 26 | implementation("jakarta.xml.ws:jakarta.xml.ws-api:3.0.1") 27 | implementation("jakarta.jws:jakarta.jws-api:3.0.0") 28 | } 29 | """ 30 | 31 | expect: 32 | dependenciesCompile().output.contains ''' 33 | compileClasspath - Compile classpath for source set 'main'. 34 | +--- jakarta.xml.ws:jakarta.xml.ws-api:3.0.1 35 | | +--- jakarta.xml.bind:jakarta.xml.bind-api:3.0.1 36 | | | \\--- com.sun.activation:jakarta.activation:2.0.1 37 | | +--- jakarta.xml.soap:jakarta.xml.soap-api:2.0.1 38 | | | \\--- com.sun.activation:jakarta.activation:2.0.1 39 | | \\--- jakarta.jws:jakarta.jws-api:3.0.0 40 | \\--- jakarta.jws:jakarta.jws-api:3.0.0 41 | ''' 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/logging/AbstractLoggingCapabilitiesPluginFunctionalTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradlex.jvm.dependency.conflict.test.logging 2 | 3 | import org.gradle.testkit.runner.BuildResult 4 | import org.gradle.testkit.runner.GradleRunner 5 | import org.gradle.testkit.runner.TaskOutcome 6 | import org.gradle.util.GradleVersion 7 | import spock.lang.Specification 8 | import spock.lang.TempDir 9 | 10 | import java.nio.file.Path 11 | 12 | abstract class AbstractLoggingCapabilitiesPluginFunctionalTest extends Specification { 13 | 14 | static GradleVersion testGradleVersion = System.getProperty("test.gradle-version")?.with { GradleVersion.version(it) } ?: GradleVersion.current() 15 | 16 | @TempDir 17 | Path testFolder 18 | File buildFile 19 | 20 | def setup() { 21 | buildFile = testFolder.resolve('build.gradle.kts').toFile() 22 | testFolder.resolve('settings.gradle.kts').toFile() << 'rootProject.name = "test-project"' 23 | } 24 | 25 | TaskOutcome outcomeOf(BuildResult result, String path) { 26 | result.task(path)?.outcome 27 | } 28 | 29 | BuildResult build(List args) { 30 | gradleRunnerFor(args).build() 31 | } 32 | 33 | BuildResult buildAndFail(List args) { 34 | gradleRunnerFor(args).buildAndFail() 35 | } 36 | 37 | GradleRunner gradleRunnerFor(List args) { 38 | GradleRunner.create() 39 | .forwardOutput() 40 | .withGradleVersion(testGradleVersion.version) 41 | .withPluginClasspath() 42 | .withProjectDir(testFolder.toFile()) 43 | .withArguments(args + ["-s"]) 44 | } 45 | 46 | void withBuildScript(String content) { 47 | buildFile << content 48 | } 49 | 50 | void withBuildScriptWithDependencies(String... dependencies) { 51 | buildFile << """ 52 | plugins { 53 | `java-library` 54 | id("org.gradlex.jvm-dependency-conflict-resolution") 55 | } 56 | 57 | repositories { 58 | mavenCentral() 59 | } 60 | 61 | dependencies { 62 | ${dependencies.collect { " implementation(\"$it\")" }.join("\n")} 63 | } 64 | 65 | tasks.register("doIt") { 66 | doLast { 67 | println(configurations["compileClasspath"].files) 68 | } 69 | } 70 | """ 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/patch/AbstractPatchTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradlex.jvm.dependency.conflict.test.patch 2 | 3 | import org.gradlex.jvm.dependency.conflict.test.fixture.GradleBuild 4 | import spock.lang.Specification 5 | 6 | abstract class AbstractPatchTest extends Specification { 7 | 8 | @Delegate 9 | GradleBuild build = new GradleBuild() 10 | 11 | def setup() { 12 | file('src/main/java/Dummy.java') << 'class Dummy {}' 13 | buildFile << """ 14 | plugins { 15 | id("org.gradlex.jvm-dependency-conflict-resolution") 16 | id("java-library") 17 | } 18 | repositories.mavenCentral() 19 | """ 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/patch/AddFeatureTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradlex.jvm.dependency.conflict.test.patch 2 | 3 | class AddFeatureTest extends AbstractPatchTest { 4 | 5 | def "can add feature"() { 6 | given: 7 | buildFile << """ 8 | jvmDependencyConflicts { 9 | patch { 10 | module("io.netty:netty-transport-native-epoll") { 11 | addFeature("linux-x86_64") 12 | addFeature("linux-aarch_64") 13 | } 14 | } 15 | } 16 | dependencies { 17 | implementation("io.netty:netty-transport-native-epoll:4.1.106.Final") 18 | implementation("io.netty:netty-transport-native-epoll:4.1.106.Final") { 19 | capabilities { requireCapabilities("io.netty:netty-transport-native-epoll-linux-x86_64") } 20 | } 21 | implementation("io.netty:netty-transport-native-epoll:4.1.106.Final") { 22 | capabilities { requireCapabilities("io.netty:netty-transport-native-epoll-linux-aarch_64") } 23 | } 24 | } 25 | """ 26 | 27 | expect: 28 | def output = dependencyInsight('io.netty:netty-transport-native-epoll').output 29 | output.contains 'linux-x86_64Compile' 30 | output.contains 'linux-aarch_64Compile' 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/patch/AddTargetPlatformVariantTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradlex.jvm.dependency.conflict.test.patch 2 | 3 | class AddTargetPlatformVariantTest extends AbstractPatchTest { 4 | 5 | def "can add target variant"() { 6 | given: 7 | buildFile << """ 8 | jvmDependencyConflicts { 9 | patch { 10 | module("org.openjfx:javafx-base") { 11 | addTargetPlatformVariant("", "none", "none") 12 | addTargetPlatformVariant("mac", "macos", "x86-64") 13 | addTargetPlatformVariant("mac-aarch64", "macos", "aarch64") 14 | addTargetPlatformVariant("win", "windows", "x86-64") 15 | addTargetPlatformVariant("linux-aarch64", "linux", "x86-64") 16 | } 17 | } 18 | } 19 | configurations.compileClasspath { 20 | attributes.attribute(OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTE, objects.named("windows")) 21 | attributes.attribute(MachineArchitecture.ARCHITECTURE_ATTRIBUTE, objects.named("x86-64")) 22 | } 23 | dependencies { 24 | implementation("org.openjfx:javafx-base:17.0.10") 25 | } 26 | tasks.register("printJars") { 27 | println(configurations.compileClasspath.get().files.joinToString("\\n") { it.name }); 28 | } 29 | """ 30 | 31 | expect: 32 | String output = printJars().output 33 | output == 'javafx-base-17.0.10-win.jar\n' 34 | } 35 | 36 | def "can add target variant with feature name"() { 37 | given: 38 | buildFile << """ 39 | jvmDependencyConflicts { 40 | patch { 41 | module("org.lwjgl:lwjgl") { 42 | addTargetPlatformVariant("natives", "natives-linux", "linux", "x86-64") 43 | addTargetPlatformVariant("natives", "natives-linux-arm64", "linux", "aarch64") 44 | addTargetPlatformVariant("natives", "natives-macos", "macos", "x86-64") 45 | addTargetPlatformVariant("natives", "natives-macos-arm64", "macos", "aarch64") 46 | addTargetPlatformVariant("natives", "natives-windows", "windows", "x86-64") 47 | addTargetPlatformVariant("natives", "natives-windows-arm64", "windows", "aarch64") 48 | } 49 | } 50 | } 51 | configurations.runtimeClasspath { 52 | attributes.attribute(OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTE, objects.named("windows")) 53 | attributes.attribute(MachineArchitecture.ARCHITECTURE_ATTRIBUTE, objects.named("x86-64")) 54 | } 55 | dependencies { 56 | implementation("org.lwjgl:lwjgl:3.3.6") 57 | runtimeOnly("org.lwjgl:lwjgl:3.3.6") { capabilities { requireCapability("org.lwjgl:lwjgl-natives") } } 58 | } 59 | tasks.register("printJars") { 60 | println(configurations.runtimeClasspath.get().files.joinToString("\\n") { it.name }); 61 | } 62 | """ 63 | 64 | expect: 65 | dependenciesCompile() 66 | String output = printJars().output 67 | output == 'lwjgl-3.3.6.jar\nlwjgl-3.3.6-natives-windows.jar\n' 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/patch/ModifyCapabilitiesTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradlex.jvm.dependency.conflict.test.patch 2 | 3 | import org.gradlex.jvm.dependency.conflict.test.fixture.GradleBuild 4 | 5 | class ModifyCapabilitiesTest extends AbstractPatchTest { 6 | 7 | def "can add capability by enum"() { 8 | given: 9 | buildFile.text = 'import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition.STAX_API\n' + buildFile.text 10 | buildFile << """ 11 | jvmDependencyConflicts { 12 | patch { 13 | module("org.eclipse.birt.runtime:javax.xml.stream") { 14 | addCapability(STAX_API) 15 | } 16 | } 17 | } 18 | dependencies { 19 | implementation("stax:stax-api:1.0.1") 20 | implementation("org.eclipse.birt.runtime:javax.xml.stream:1.0.1.v201004272200") 21 | } 22 | """ 23 | 24 | expect: 25 | dependenciesCompile().output.contains ''' 26 | compileClasspath - Compile classpath for source set 'main'. 27 | +--- stax:stax-api:1.0.1 28 | \\--- org.eclipse.birt.runtime:javax.xml.stream:1.0.1.v201004272200 -> stax:stax-api:1.0.1 29 | 30 | ''' 31 | } 32 | 33 | def "can add capability by string"() { 34 | given: 35 | buildFile << """ 36 | jvmDependencyConflicts { 37 | patch { 38 | module("org.apache.commons:commons-lang3") { 39 | addCapability("commons-lang:commons-lang") // artificial case for testing! 40 | } 41 | } 42 | } 43 | dependencies { 44 | implementation("commons-lang:commons-lang:2.6") 45 | implementation("org.apache.commons:commons-lang3:3.11") 46 | } 47 | """ 48 | 49 | expect: 50 | fail().output.contains "Cannot select module with conflict on capability 'commons-lang:commons-lang:2.6' also provided by [org.apache.commons:commons-lang3:3.11(compile)]" 51 | } 52 | 53 | def "can remove capability by enum"() { 54 | given: 55 | buildFile.text = 'import org.gradlex.jvm.dependency.conflict.detection.rules.CapabilityDefinition.STAX_API\n' + buildFile.text 56 | buildFile << """ 57 | jvmDependencyConflicts { 58 | patch { 59 | module("javax.xml.stream:stax-api") { 60 | removeCapability(STAX_API) 61 | } 62 | } 63 | } 64 | dependencies { 65 | implementation("stax:stax-api:1.0.1") 66 | implementation("javax.xml.stream:stax-api:1.0-2") 67 | } 68 | """ 69 | 70 | expect: 71 | dependenciesCompile().output.contains ''' 72 | compileClasspath - Compile classpath for source set 'main'. 73 | +--- stax:stax-api:1.0.1 74 | \\--- javax.xml.stream:stax-api:1.0-2 75 | 76 | ''' 77 | } 78 | 79 | def "can remove capability by string"() { 80 | given: 81 | if (GradleBuild.GRADLE6_TEST) { 82 | buildFile << """ 83 | configurations.runtimeClasspath { 84 | attributes.attribute(Attribute.of("org.gradle.jvm.environment", String::class.java), "standard-jvm") 85 | } 86 | """ 87 | } 88 | 89 | buildFile << """ 90 | jvmDependencyConflicts { 91 | patch { 92 | module("com.google.guava:guava") { 93 | removeCapability("com.google.collections:google-collections") 94 | } 95 | } 96 | } 97 | dependencies { 98 | implementation("com.google.guava:guava:33.1.0-jre") 99 | implementation("com.google.collections:google-collections:1.0") 100 | } 101 | """ 102 | 103 | expect: 104 | dependenciesRuntime().output.contains ''' 105 | runtimeClasspath - Runtime classpath of source set 'main'. 106 | +--- com.google.guava:guava:33.1.0-jre 107 | | +--- com.google.guava:failureaccess:1.0.2 108 | | +--- com.google.code.findbugs:jsr305:3.0.2 109 | | +--- org.checkerframework:checker-qual:3.42.0 110 | | \\--- com.google.errorprone:error_prone_annotations:2.26.1 111 | \\--- com.google.collections:google-collections:1.0 112 | 113 | ''' 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/test/groovy/org/gradlex/jvm/dependency/conflict/test/patch/SetStatusTest.groovy: -------------------------------------------------------------------------------- 1 | package org.gradlex.jvm.dependency.conflict.test.patch 2 | 3 | class SetStatusTest extends AbstractPatchTest { 4 | def "can set component status to integration for certain versions"() { 5 | given: 6 | buildFile << """ 7 | jvmDependencyConflicts { 8 | patch { 9 | module("com.fasterxml.jackson.core:jackson-core") { 10 | setStatusToIntegration("-m", "-rc") 11 | } 12 | } 13 | } 14 | dependencies { 15 | implementation("com.fasterxml.jackson.core:jackson-core:2.15.0-rc3") 16 | } 17 | """ 18 | 19 | expect: 20 | dependencyInsight("com.fasterxml.jackson.core:jackson-core").output.contains 'integration' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/gradlex/jvm/dependency/conflict/samples/PluginBuildLocationSampleModifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.samples; 18 | 19 | import org.gradle.exemplar.model.Command; 20 | import org.gradle.exemplar.model.Sample; 21 | import org.gradle.exemplar.test.runner.SampleModifier; 22 | 23 | import java.io.File; 24 | import java.lang.management.ManagementFactory; 25 | import java.util.ArrayList; 26 | import java.util.Arrays; 27 | 28 | public class PluginBuildLocationSampleModifier implements SampleModifier { 29 | @Override 30 | public Sample modify(Sample sampleIn) { 31 | Command cmd = sampleIn.getCommands().remove(0); 32 | File pluginProjectDir = new File("."); 33 | ArrayList allArgs = new ArrayList<>(cmd.getArgs()); 34 | allArgs.addAll(Arrays.asList("dependencies", "--configuration=compileClasspath", "-s", "-q", "-PpluginLocation=" + pluginProjectDir.getAbsolutePath())); 35 | if (ManagementFactory.getRuntimeMXBean().getInputArguments().toString().contains("-agentlib:jdwp")) { 36 | allArgs.add("-Dorg.gradle.debug=true"); 37 | } 38 | sampleIn.getCommands().add( 39 | new Command(new File(pluginProjectDir, "./gradlew").getAbsolutePath(), 40 | cmd.getExecutionSubdirectory(), 41 | allArgs, 42 | cmd.getFlags(), 43 | cmd.getExpectedOutput(), 44 | cmd.isExpectFailure(), 45 | true, 46 | cmd.isAllowDisorderedOutput(), 47 | cmd.getUserInputs())); 48 | return sampleIn; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/org/gradlex/jvm/dependency/conflict/samples/SamplesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright the GradleX team. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.gradlex.jvm.dependency.conflict.samples; 18 | 19 | import org.gradle.exemplar.test.runner.SampleModifiers; 20 | import org.gradle.exemplar.test.runner.SamplesRoot; 21 | import org.gradle.exemplar.test.runner.SamplesRunner; 22 | import org.junit.runner.RunWith; 23 | 24 | @RunWith(SamplesRunner.class) 25 | @SamplesRoot("samples") 26 | @SampleModifiers(PluginBuildLocationSampleModifier.class) 27 | public class SamplesTest { 28 | 29 | } 30 | --------------------------------------------------------------------------------