Created
October 10, 2025 09:21
-
-
Save gnodet/5f3a2fec143e9e0270bfa238172dabe9 to your computer and use it in GitHub Desktop.
Diff between master and 4.0.x
This file has been truncated, but you can view the full file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/.asf.yaml b/.asf.yaml | |
| index 3344951e1a..a6530be680 100644 | |
| --- a/.asf.yaml | |
| +++ b/.asf.yaml | |
| @@ -16,16 +16,10 @@ github: | |
| - MNG | |
| pull_requests: | |
| del_branch_on_merge: true | |
| - protected_branches: | |
| - master: {} | |
| - maven-4.0.x: {} | |
| - maven-3.9.x: {} | |
| - maven-3.8.x: {} | |
| - maven-3.0.x: {} | |
| - pre-reset-master: {} | |
| features: | |
| issues: true | |
| notifications: | |
| commits: commits@maven.apache.org | |
| issues: issues@maven.apache.org | |
| pullrequests: issues@maven.apache.org | |
| + jira_options: link label | |
| diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml | |
| index b27d663311..10fb08b82c 100644 | |
| --- a/.github/ISSUE_TEMPLATE/config.yml | |
| +++ b/.github/ISSUE_TEMPLATE/config.yml | |
| @@ -24,3 +24,7 @@ contact_links: | |
| - name: Project Mailing Lists | |
| url: https://maven.apache.org/mailing-lists.html | |
| about: Please ask a question or discuss here | |
| + | |
| + - name: Old JIRA Issues | |
| + url: https://issues.apache.org/jira/browse/MNG | |
| + about: Please search old JIRA issues | |
| diff --git a/.github/ci-extensions.xml b/.github/ci-extensions.xml | |
| index 17fa89e437..5c6a0b4378 100644 | |
| --- a/.github/ci-extensions.xml | |
| +++ b/.github/ci-extensions.xml | |
| @@ -20,7 +20,7 @@ under the License. | |
| <extensions> | |
| <extension> | |
| <groupId>eu.maveniverse.maven.mimir</groupId> | |
| - <artifactId>extension3</artifactId> | |
| - <version>${env.MIMIR_VERSION}</version> | |
| + <artifactId>extension</artifactId> | |
| + <version>0.7.8</version> | |
| </extension> | |
| </extensions> | |
| \ No newline at end of file | |
| diff --git a/.github/ci-mimir-daemon.properties b/.github/ci-mimir-daemon.properties | |
| index 16c507a283..86a84b6ac5 100644 | |
| --- a/.github/ci-mimir-daemon.properties | |
| +++ b/.github/ci-mimir-daemon.properties | |
| @@ -15,7 +15,7 @@ | |
| # limitations under the License. | |
| # | |
| -# Mimir Daemon config properties | |
| +# Mimir Daemon properties | |
| -# Pre-seed itself | |
| -mimir.daemon.preSeedItself=true | |
| +# Disable JGroups; we don't want/use LAN cache sharing | |
| +mimir.jgroups.enabled=false | |
| \ No newline at end of file | |
| diff --git a/.github/ci-mimir-session.properties b/.github/ci-mimir-session.properties | |
| deleted file mode 100644 | |
| index 5f7f9e54d2..0000000000 | |
| --- a/.github/ci-mimir-session.properties | |
| +++ /dev/null | |
| @@ -1,21 +0,0 @@ | |
| -# | |
| -# Licensed to the Apache Software Foundation (ASF) under one or more | |
| -# contributor license agreements. See the NOTICE file distributed with | |
| -# this work for additional information regarding copyright ownership. | |
| -# The ASF licenses this file to You under the Apache License, Version 2.0 | |
| -# (the "License"); you may not use this file except in compliance with | |
| -# the License. You may obtain a copy of the License at | |
| -# | |
| -# http://www.apache.org/licenses/LICENSE-2.0 | |
| -# | |
| -# Unless required by applicable law or agreed to in writing, software | |
| -# distributed under the License is distributed on an "AS IS" BASIS, | |
| -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| -# See the License for the specific language governing permissions and | |
| -# limitations under the License. | |
| -# | |
| - | |
| -# Mimir Session config properties | |
| - | |
| -# do not waste time on this; we maintain the version | |
| -mimir.daemon.autoupdate=false | |
| \ No newline at end of file | |
| diff --git a/.github/dependabot.yml b/.github/dependabot.yml | |
| index 1576b20f13..098e0d129b 100644 | |
| --- a/.github/dependabot.yml | |
| +++ b/.github/dependabot.yml | |
| @@ -22,15 +22,6 @@ updates: | |
| schedule: | |
| interval: "daily" | |
| - - package-ecosystem: "maven" | |
| - directory: "/" | |
| - schedule: | |
| - interval: "daily" | |
| - target-branch: "maven-4.0.x" | |
| - labels: | |
| - - "mvn40" | |
| - - "dependencies" | |
| - | |
| - package-ecosystem: "maven" | |
| directory: "/" | |
| schedule: | |
| @@ -45,16 +36,6 @@ updates: | |
| schedule: | |
| interval: "daily" | |
| - - package-ecosystem: "github-actions" | |
| - directory: "/" | |
| - schedule: | |
| - interval: "daily" | |
| - target-branch: "maven-4.0.x" | |
| - labels: | |
| - - "mvn40" | |
| - - "dependencies" | |
| - - "github_actions" | |
| - | |
| - package-ecosystem: "github-actions" | |
| directory: "/" | |
| schedule: | |
| @@ -63,4 +44,3 @@ updates: | |
| labels: | |
| - "mvn3" | |
| - "dependencies" | |
| - - "github_actions" | |
| diff --git a/.github/release-drafter-3.x.yml b/.github/release-drafter-3.x.yml | |
| index da2e7a556c..7438f11173 100644 | |
| --- a/.github/release-drafter-3.x.yml | |
| +++ b/.github/release-drafter-3.x.yml | |
| @@ -16,4 +16,3 @@ | |
| # under the License. | |
| _extends: maven-gh-actions-shared:.github/release-drafter.yml | |
| -tag-template: maven-$RESOLVED_VERSION | |
| diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml | |
| index add27b1def..eaea796b4d 100644 | |
| --- a/.github/release-drafter.yml | |
| +++ b/.github/release-drafter.yml | |
| @@ -16,7 +16,6 @@ | |
| # under the License. | |
| _extends: maven-gh-actions-shared | |
| -tag-template: maven-$RESOLVED_VERSION | |
| include-pre-releases: true | |
| prerelease: true | |
| diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml | |
| index 19a0265f14..04f3eef000 100644 | |
| --- a/.github/workflows/maven.yml | |
| +++ b/.github/workflows/maven.yml | |
| @@ -19,9 +19,9 @@ name: Java CI | |
| on: | |
| push: | |
| - branches: [ master ] | |
| + branches: [ maven-4.0.x ] | |
| pull_request: | |
| - branches: [ master ] | |
| + branches: [ maven-4.0.x ] | |
| # allow single build per branch or PR | |
| concurrency: | |
| @@ -31,12 +31,6 @@ concurrency: | |
| # clear all permissions for GITHUB_TOKEN | |
| permissions: {} | |
| -env: | |
| - MIMIR_VERSION: 0.9.4 | |
| - MIMIR_BASEDIR: ~/.mimir | |
| - MIMIR_LOCAL: ~/.mimir/local | |
| - MAVEN_OPTS: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./target/java_heapdump.hprof | |
| - | |
| jobs: | |
| initial-build: | |
| runs-on: ubuntu-latest | |
| @@ -52,31 +46,25 @@ jobs: | |
| with: | |
| persist-credentials: false | |
| - - name: Prepare Mimir for Maven 3.x | |
| + - name: Prepare Mimir | |
| shell: bash | |
| run: | | |
| - mkdir -p ${{ env.MIMIR_BASEDIR }} | |
| - cp .github/ci-mimir-session.properties ${{ env.MIMIR_BASEDIR }}/session.properties | |
| - cp .github/ci-mimir-daemon.properties ${{ env.MIMIR_BASEDIR }}/daemon.properties | |
| - cp .github/ci-extensions.xml .mvn/extensions.xml | |
| - | |
| - - name: Restore Mimir caches | |
| - uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| - id: restore-cache | |
| + mkdir -p ~/.mimir | |
| + cp .github/ci-extensions.xml ~/.m2/extensions.xml | |
| + cp .github/ci-mimir-daemon.properties ~/.mimir/daemon.properties | |
| + | |
| + - name: Handle Mimir caches | |
| + uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4 | |
| with: | |
| - path: ${{ env.MIMIR_LOCAL }} | |
| - key: mvn-${{ runner.os }}-initial | |
| + path: ~/.mimir/local | |
| + key: mimir-${{ runner.os }}-initial-${{ hashFiles('**/pom.xml') }} | |
| + restore-keys: | | |
| + mimir-${{ runner.os }}-initial- | |
| + mimir-${{ runner.os }}- | |
| - name: Set up Maven | |
| shell: bash | |
| - run: mvn --errors --batch-mode --show-version org.apache.maven.plugins:maven-wrapper-plugin:3.3.4:wrapper "-Dmaven=4.0.0-rc-4" | |
| - | |
| - - name: Prepare Mimir for Maven 4.x | |
| - shell: bash | |
| - run: | | |
| - rm .mvn/extensions.xml | |
| - mkdir -p ~/.m2 | |
| - cp .github/ci-extensions.xml ~/.m2/extensions.xml | |
| + run: mvn --errors --batch-mode --show-version org.apache.maven.plugins:maven-wrapper-plugin:3.3.2:wrapper "-Dmaven=4.0.0-rc-3" | |
| - name: Build Maven distributions | |
| shell: bash | |
| @@ -86,13 +74,6 @@ jobs: | |
| shell: bash | |
| run: ls -la apache-maven/target | |
| - - name: Save Mimir caches | |
| - uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| - if: ${{ github.event_name != 'pull_request' && !cancelled() && !failure() }} | |
| - with: | |
| - path: ${{ env.MIMIR_LOCAL }} | |
| - key: ${{ steps.restore-cache.outputs.cache-primary-key }} | |
| - | |
| - name: Upload Maven distributions | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| @@ -108,7 +89,7 @@ jobs: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| - java: ['17', '21', '25'] | |
| + java: ['17', '21', '24'] | |
| steps: | |
| - name: Set up JDK ${{ matrix.java }} | |
| uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5 | |
| @@ -133,24 +114,22 @@ jobs: | |
| with: | |
| persist-credentials: false | |
| - - name: Prepare Mimir for Maven 4.x | |
| + - name: Prepare Mimir | |
| shell: bash | |
| run: | | |
| - mkdir -p ${{ env.MIMIR_BASEDIR }} | |
| - cp .github/ci-mimir-session.properties ${{ env.MIMIR_BASEDIR }}/session.properties | |
| - cp .github/ci-mimir-daemon.properties ${{ env.MIMIR_BASEDIR }}/daemon.properties | |
| mkdir -p ~/.m2 | |
| + mkdir -p ~/.mimir | |
| cp .github/ci-extensions.xml ~/.m2/extensions.xml | |
| + cp .github/ci-mimir-daemon.properties ~/.mimir/daemon.properties | |
| - - name: Restore Mimir caches | |
| - uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| - id: restore-cache | |
| + - name: Handle Mimir caches | |
| + uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4 | |
| with: | |
| - path: ${{ env.MIMIR_LOCAL }} | |
| - key: mvn-full-${{ matrix.os }}-${{ matrix.java }} | |
| + path: ~/.mimir/local | |
| + key: mimir-${{ runner.os }}-full-${{ hashFiles('**/pom.xml') }} | |
| restore-keys: | | |
| - mvn-full-${{ matrix.os }}- | |
| - mvn-full- | |
| + mimir-${{ runner.os }}-full- | |
| + mimir-${{ runner.os }}- | |
| - name: Download Maven distribution | |
| uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v4 | |
| @@ -179,6 +158,10 @@ jobs: | |
| echo "MAVEN_HOME=$PWD/maven-local" >> $GITHUB_ENV | |
| echo "$PWD/maven-local/bin" >> $GITHUB_PATH | |
| + - name: Show IP | |
| + shell: bash | |
| + run: curl --silent https://api.ipify.org | |
| + | |
| - name: Build with downloaded Maven | |
| shell: bash | |
| run: mvn verify -Papache-release -Dgpg.skip=true -e -B -V | |
| @@ -187,21 +170,12 @@ jobs: | |
| shell: bash | |
| run: mvn site -e -B -V -Preporting | |
| - - name: Save Mimir caches | |
| - uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| - if: ${{ github.event_name != 'pull_request' && !cancelled() && !failure() }} | |
| - with: | |
| - path: ${{ env.MIMIR_LOCAL }} | |
| - key: ${{ steps.restore-cache.outputs.cache-primary-key }} | |
| - | |
| - name: Upload test artifacts | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| - if: failure() || cancelled() | |
| + if: failure() | |
| with: | |
| name: ${{ github.run_number }}-full-build-artifact-${{ runner.os }}-${{ matrix.java }} | |
| - path: | | |
| - **/target/surefire-reports/* | |
| - **/target/java_heapdump.hprof | |
| + path: '**/target/surefire-reports/*' | |
| integration-tests: | |
| needs: initial-build | |
| @@ -210,7 +184,7 @@ jobs: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| - java: ['17', '21', '25'] | |
| + java: ['17', '21', '24'] | |
| steps: | |
| - name: Set up JDK ${{ matrix.java }} | |
| uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5 | |
| @@ -223,24 +197,22 @@ jobs: | |
| with: | |
| persist-credentials: false | |
| - - name: Prepare Mimir for Maven 4.x | |
| + - name: Prepare Mimir | |
| shell: bash | |
| run: | | |
| - mkdir -p ${{ env.MIMIR_BASEDIR }} | |
| - cp .github/ci-mimir-session.properties ${{ env.MIMIR_BASEDIR }}/session.properties | |
| - cp .github/ci-mimir-daemon.properties ${{ env.MIMIR_BASEDIR }}/daemon.properties | |
| mkdir -p ~/.m2 | |
| + mkdir -p ~/.mimir | |
| cp .github/ci-extensions.xml ~/.m2/extensions.xml | |
| + cp .github/ci-mimir-daemon.properties ~/.mimir/daemon.properties | |
| - - name: Restore Mimir caches | |
| - uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| - id: restore-cache | |
| + - name: Handle Mimir caches | |
| + uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4 | |
| with: | |
| - path: ${{ env.MIMIR_LOCAL }} | |
| - key: mvn-its-${{ matrix.os }}-${{ matrix.java }} | |
| + path: ~/.mimir/local | |
| + key: mimir-${{ runner.os }}-its-${{ hashFiles('**/pom.xml') }} | |
| restore-keys: | | |
| - mvn-its-${{ matrix.os }}- | |
| - mvn-its- | |
| + mimir-${{ runner.os }}-its- | |
| + mimir-${{ runner.os }}- | |
| - name: Download Maven distribution | |
| uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v4 | |
| @@ -269,22 +241,17 @@ jobs: | |
| echo "MAVEN_HOME=$PWD/maven-local" >> $GITHUB_ENV | |
| echo "$PWD/maven-local/bin" >> $GITHUB_PATH | |
| + - name: Show IP | |
| + shell: bash | |
| + run: curl --silent https://api.ipify.org | |
| + | |
| - name: Build Maven and ITs and run them | |
| shell: bash | |
| run: mvn install -e -B -V -Prun-its,mimir | |
| - - name: Save Mimir caches | |
| - uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| - if: ${{ github.event_name != 'pull_request' && !cancelled() && !failure() }} | |
| - with: | |
| - path: ${{ env.MIMIR_LOCAL }} | |
| - key: ${{ steps.restore-cache.outputs.cache-primary-key }} | |
| - | |
| - name: Upload test artifacts | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| - if: failure() || cancelled() | |
| + if: failure() | |
| with: | |
| name: ${{ github.run_number }}-integration-test-artifact-${{ runner.os }}-${{ matrix.java }} | |
| - path: | | |
| - ./its/core-it-suite/target/test-classes/ | |
| - **/target/java_heapdump.hprof | |
| + path: ./its/core-it-suite/target/test-classes/ | |
| diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml | |
| index 96eaa60a0f..0af2d2b844 100644 | |
| --- a/.github/workflows/release-drafter.yml | |
| +++ b/.github/workflows/release-drafter.yml | |
| @@ -19,9 +19,11 @@ name: Release Drafter | |
| on: | |
| push: | |
| branches: | |
| - - master | |
| + - maven-4.0.x | |
| workflow_dispatch: | |
| jobs: | |
| update_release_draft: | |
| uses: apache/maven-gh-actions-shared/.github/workflows/release-drafter.yml@v4 | |
| + with: | |
| + commits-since: '2025-06-18T10:29:46Z' # date of first commit on maven-4.0.x branch, bed0f8174bf728978f86fac533aa38a9511f3872 | |
| diff --git a/.gitignore b/.gitignore | |
| index b3f36670ba..4e85f56fb4 100644 | |
| --- a/.gitignore | |
| +++ b/.gitignore | |
| @@ -14,6 +14,7 @@ | |
| .java-version | |
| .checkstyle | |
| .factorypath | |
| +repo/ | |
| # VSCode | |
| .vscode/ | |
| diff --git a/.mvn/maven.config b/.mvn/maven.config | |
| index c6f922ecc2..f3b0cd90b1 100644 | |
| --- a/.mvn/maven.config | |
| +++ b/.mvn/maven.config | |
| @@ -1 +1,2 @@ | |
| +# A hack to pass on this property for Maven 3 as well; Maven 4 supports this property out of the box | |
| -DsessionRootDirectory=${session.rootDirectory} | |
| \ No newline at end of file | |
| diff --git a/apache-maven/pom.xml b/apache-maven/pom.xml | |
| index 940657ce0d..28c4a2fcaf 100644 | |
| --- a/apache-maven/pom.xml | |
| +++ b/apache-maven/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>apache-maven</artifactId> | |
| diff --git a/apache-maven/src/assembly/maven/conf/maven-user.properties b/apache-maven/src/assembly/maven/conf/maven-user.properties | |
| index c664d06cc5..b218c3d138 100644 | |
| --- a/apache-maven/src/assembly/maven/conf/maven-user.properties | |
| +++ b/apache-maven/src/assembly/maven/conf/maven-user.properties | |
| @@ -27,36 +27,8 @@ | |
| # Comma-separated list of files to include. | |
| # Each item may be enclosed in quotes to gracefully include spaces. Items are trimmed before being loaded. | |
| # If the first character of an item is a question mark, the load will silently fail if the file does not exist. | |
| +# Note: the maven.properties will be removed in Maven 4.1.0 and only maven-user.properties will be loaded! | |
| ${includes} = ?"${maven.user.conf}/maven-user.properties", \ | |
| - ?"${maven.project.conf}/maven-user.properties" | |
| - | |
| -# | |
| -# Maven Cache Configuration | |
| -# | |
| -# Controls caching behavior for different request types during Maven builds. | |
| -# Format: RequestType { scope:SCOPE ref:REFERENCE_TYPE } | |
| -# | |
| -# SCOPE OPTIONS: | |
| -# session - Cache for entire Maven session (all modules in multi-module build) | |
| -# request - Cache only for current request + its child requests | |
| -# none - Disable caching entirely | |
| -# | |
| -# REFERENCE OPTIONS: | |
| -# hard - Strong reference (stays in memory, faster access) | |
| -# soft - Weak reference (can be garbage collected under memory pressure) | |
| -# | |
| -# CONFIGURATION BREAKDOWN: | |
| -# SourceCacheKey - File and RAW model requests (session/hard for consistent file access) | |
| -# DefaultArtifactResolverRequest - Artifact resolution results (session/hard to avoid re-resolving) | |
| -# DefaultVersionResolverRequest - Version resolution results (session/soft, less critical than artifacts) | |
| -# RgavCacheKey - BOM import caching (session/soft, typically resolved once) | |
| -# DefaultModelBuilderRequest - Model building operations (none, ensures fresh dynamic builds) | |
| -# * - Fallback for all other requests (request/soft for temporary child request caching) | |
| -# | |
| -maven.cache.config = \ | |
| - SourceCacheKey { scope:session ref:hard } \ | |
| - DefaultArtifactResolverRequest { scope:session ref:hard } \ | |
| - DefaultVersionResolverRequest { scope:session ref:soft } \ | |
| - RgavCacheKey { scope:session ref:soft } \ | |
| - DefaultModelBuilderRequest { scope:none } \ | |
| - * { scope:request ref:soft } | |
| + ?"${maven.user.conf}/maven.properties", \ | |
| + ?"${maven.project.conf}/maven-user.properties", \ | |
| + ?"${maven.project.conf}/maven.properties", | |
| diff --git a/api/maven-api-annotations/pom.xml b/api/maven-api-annotations/pom.xml | |
| index 350873e35a..40872a8f74 100644 | |
| --- a/api/maven-api-annotations/pom.xml | |
| +++ b/api/maven-api-annotations/pom.xml | |
| @@ -23,7 +23,7 @@ | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-api</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-api-annotations</artifactId> | |
| diff --git a/api/maven-api-cli/pom.xml b/api/maven-api-cli/pom.xml | |
| index 6ed5c71eff..509f0dad6b 100644 | |
| --- a/api/maven-api-cli/pom.xml | |
| +++ b/api/maven-api-cli/pom.xml | |
| @@ -23,7 +23,7 @@ | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-api</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-api-cli</artifactId> | |
| diff --git a/api/maven-api-core/pom.xml b/api/maven-api-core/pom.xml | |
| index 339ea83192..104d6375b7 100644 | |
| --- a/api/maven-api-core/pom.xml | |
| +++ b/api/maven-api-core/pom.xml | |
| @@ -23,7 +23,7 @@ | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-api</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-api-core</artifactId> | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java | |
| index d26972c006..7303e8e61c 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java | |
| @@ -39,7 +39,7 @@ | |
| @Immutable | |
| public interface Artifact { | |
| /** | |
| - * {@return a unique identifier for this artifact}. | |
| + * {@return a unique identifier for this artifact} | |
| * The identifier is composed of groupId, artifactId, extension, classifier, and version. | |
| * | |
| * @see ArtifactCoordinates#getId() | |
| @@ -58,7 +58,7 @@ default String key() { | |
| } | |
| /** | |
| - * {@return the group identifier of the artifact}. | |
| + * {@return the group identifier of the artifact} | |
| * | |
| * @see ArtifactCoordinates#getGroupId() | |
| */ | |
| @@ -66,7 +66,7 @@ default String key() { | |
| String getGroupId(); | |
| /** | |
| - * {@return the identifier of the artifact}. | |
| + * {@return the identifier of the artifact} | |
| * | |
| * @see ArtifactCoordinates#getArtifactId() | |
| */ | |
| @@ -74,7 +74,7 @@ default String key() { | |
| String getArtifactId(); | |
| /** | |
| - * {@return the version of the artifact}. | |
| + * {@return the version of the artifact} | |
| * Contrarily to {@link ArtifactCoordinates}, | |
| * each {@code Artifact} is associated to a specific version instead of a range of versions. | |
| * If the {@linkplain #getBaseVersion() base version} contains a meta-version such as {@code SNAPSHOT}, | |
| @@ -86,7 +86,7 @@ default String key() { | |
| Version getVersion(); | |
| /** | |
| - * {@return the version or meta-version of the artifact}. | |
| + * {@return the version or meta-version of the artifact} | |
| * A meta-version is a version suffixed with the {@code SNAPSHOT} keyword. | |
| * Meta-versions are represented in a base version by their symbols (e.g., {@code SNAPSHOT}), | |
| * while they are replaced by, for example, the actual timestamp in the {@linkplain #getVersion() version}. | |
| @@ -122,7 +122,7 @@ default String key() { | |
| boolean isSnapshot(); | |
| /** | |
| - * {@return coordinates with the same identifiers as this artifact}. | |
| + * {@return coordinates with the same identifiers as this artifact} | |
| * This is a shortcut for {@code session.createArtifactCoordinates(artifact)}. | |
| * | |
| * @see org.apache.maven.api.Session#createArtifactCoordinates(Artifact) | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/ArtifactCoordinates.java b/api/maven-api-core/src/main/java/org/apache/maven/api/ArtifactCoordinates.java | |
| index 89a7e37aa5..dab32ee48c 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/ArtifactCoordinates.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/ArtifactCoordinates.java | |
| @@ -33,13 +33,13 @@ | |
| @Immutable | |
| public interface ArtifactCoordinates { | |
| /** | |
| - * {@return the group identifier of the artifact}. | |
| + * {@return the group identifier of the artifact} | |
| */ | |
| @Nonnull | |
| String getGroupId(); | |
| /** | |
| - * {@return the identifier of the artifact}. | |
| + * {@return the identifier of the artifact} | |
| */ | |
| @Nonnull | |
| String getArtifactId(); | |
| @@ -53,7 +53,7 @@ public interface ArtifactCoordinates { | |
| String getClassifier(); | |
| /** | |
| - * {@return the specific version, range of versions, or meta-version of the artifact}. | |
| + * {@return the specific version, range of versions or meta-version of the artifact} | |
| * A meta-version is a version suffixed with the {@code SNAPSHOT} keyword. | |
| */ | |
| @Nonnull | |
| @@ -69,7 +69,7 @@ public interface ArtifactCoordinates { | |
| String getExtension(); | |
| /** | |
| - * {@return a unique string identifying this artifact}. | |
| + * {@return a unique string representation identifying this artifact} | |
| * | |
| * The default implementation returns a colon-separated list of group | |
| * identifier, artifact identifier, extension, classifier and version. | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Constants.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Constants.java | |
| index 8dc9bf106d..db96d3f7f6 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Constants.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Constants.java | |
| @@ -352,7 +352,6 @@ public final class Constants { | |
| * <li>"h" or "h(num)" - highest version or top list of highest ones filter</li> | |
| * <li>"l" or "l(num)" - lowest version or bottom list of lowest ones filter</li> | |
| * <li>"s" - contextual snapshot filter</li> | |
| - * <li>"ns" - unconditional snapshot filter (no snapshots selected from ranges)</li> | |
| * <li>"e(G:A:V)" - predicate filter (leaves out G:A:V from range, if hit, V can be range)</li> | |
| * </ul> | |
| * Example filter expression: <code>"h(5);s;e(org.foo:bar:1)</code> will cause: ranges are filtered for "top 5" (instead | |
| @@ -410,9 +409,9 @@ public final class Constants { | |
| /** | |
| * User property for selecting dependency manager behaviour regarding transitive dependencies and dependency | |
| - * management entries in their POMs. Maven 3 targeted full backward compatibility with Maven 2. Hence, it ignored | |
| - * dependency management entries in transitive dependency POMs. Maven 4 enables "transitivity" by default. Hence | |
| - * unlike Maven 3, it obeys dependency management entries deep in the dependency graph as well. | |
| + * management entries in their POMs. Maven 3 targeted full backward compatibility with Maven2, hence it ignored | |
| + * dependency management entries in transitive dependency POMs. Maven 4 enables "transitivity" by default, hence | |
| + * unlike Maven2, obeys dependency management entries deep in dependency graph as well. | |
| * <br/> | |
| * Default: <code>"true"</code>. | |
| * | |
| @@ -465,7 +464,7 @@ public final class Constants { | |
| /** | |
| * User property for controlling "maven personality". If activated Maven will behave | |
| - * like the previous major version, Maven 3. | |
| + * as previous major version, Maven 3. | |
| * | |
| * @since 4.0.0 | |
| */ | |
| @@ -495,19 +494,6 @@ public final class Constants { | |
| @Config(type = "java.lang.Integer") | |
| public static final String MAVEN_DEPLOY_SNAPSHOT_BUILD_NUMBER = "maven.deploy.snapshot.buildNumber"; | |
| - /** | |
| - * User property for controlling whether build POMs are deployed alongside consumer POMs. | |
| - * When set to <code>false</code>, only the consumer POM will be deployed, and the build POM | |
| - * will be excluded from deployment. This is useful to avoid deploying internal build information | |
| - * that is not needed by consumers of the artifact. | |
| - * <br/> | |
| - * Default: <code>"true"</code>. | |
| - * | |
| - * @since 4.1.0 | |
| - */ | |
| - @Config(type = "java.lang.Boolean", defaultValue = "true") | |
| - public static final String MAVEN_DEPLOY_BUILD_POM = "maven.deploy.buildPom"; | |
| - | |
| /** | |
| * User property used to store the build timestamp. | |
| * | |
| @@ -662,70 +648,5 @@ public final class Constants { | |
| */ | |
| public static final String MAVEN_LOGGER_LOG_PREFIX = MAVEN_LOGGER_PREFIX + "log."; | |
| - /** | |
| - * User property key for cache configuration. | |
| - * | |
| - * @since 4.1.0 | |
| - */ | |
| - public static final String MAVEN_CACHE_CONFIG_PROPERTY = "maven.cache.config"; | |
| - | |
| - /** | |
| - * User property to enable cache statistics display at the end of the build. | |
| - * When set to true, detailed cache statistics including hit/miss ratios, | |
| - * request type breakdowns, and retention policy effectiveness will be displayed | |
| - * when the build completes. | |
| - * | |
| - * @since 4.1.0 | |
| - */ | |
| - @Config(type = "java.lang.Boolean", defaultValue = "false") | |
| - public static final String MAVEN_CACHE_STATS = "maven.cache.stats"; | |
| - | |
| - /** | |
| - * User property to configure separate reference types for cache keys. | |
| - * This enables fine-grained analysis of cache misses caused by key vs value evictions. | |
| - * Supported values are {@code HARD}, {@code SOFT} and {@code WEAK}. | |
| - * | |
| - * @since 4.1.0 | |
| - */ | |
| - public static final String MAVEN_CACHE_KEY_REFS = "maven.cache.keyValueRefs"; | |
| - | |
| - /** | |
| - * User property to configure separate reference types for cache values. | |
| - * This enables fine-grained analysis of cache misses caused by key vs value evictions. | |
| - * Supported values are {@code HARD}, {@code SOFT} and {@code WEAK}. | |
| - * | |
| - * @since 4.1.0 | |
| - */ | |
| - public static final String MAVEN_CACHE_VALUE_REFS = "maven.cache.keyValueRefs"; | |
| - | |
| - /** | |
| - * User property key for configuring which object types are pooled by ModelObjectProcessor. | |
| - * Value should be a comma-separated list of simple class names (e.g., "Dependency,Plugin,Build"). | |
| - * Default is "Dependency" for backward compatibility. | |
| - * | |
| - * @since 4.1.0 | |
| - */ | |
| - @Config(defaultValue = "Dependency") | |
| - public static final String MAVEN_MODEL_PROCESSOR_POOLED_TYPES = "maven.model.processor.pooledTypes"; | |
| - | |
| - /** | |
| - * User property key for configuring the default reference type used by ModelObjectProcessor. | |
| - * Valid values are: "SOFT", "HARD", "WEAK", "NONE". | |
| - * Default is "HARD" for optimal performance. | |
| - * | |
| - * @since 4.1.0 | |
| - */ | |
| - @Config(defaultValue = "HARD") | |
| - public static final String MAVEN_MODEL_PROCESSOR_REFERENCE_TYPE = "maven.model.processor.referenceType"; | |
| - | |
| - /** | |
| - * User property key prefix for configuring per-object-type reference types. | |
| - * Format: maven.model.processor.referenceType.{ClassName} = {ReferenceType} | |
| - * Example: maven.model.processor.referenceType.Dependency = SOFT | |
| - * | |
| - * @since 4.1.0 | |
| - */ | |
| - public static final String MAVEN_MODEL_PROCESSOR_REFERENCE_TYPE_PREFIX = "maven.model.processor.referenceType."; | |
| - | |
| private Constants() {} | |
| } | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java | |
| index 95dc5d689e..5a2ad2b9d4 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java | |
| @@ -36,7 +36,7 @@ | |
| @Immutable | |
| public interface Dependency extends Artifact { | |
| /** | |
| - * {@return the type of the dependency}. | |
| + * {@return the type of the dependency} | |
| * A dependency can be a <abbr>JAR</abbr> file, | |
| * a modular-<abbr>JAR</abbr> if it is intended to be placed on the module path, | |
| * a <abbr>JAR</abbr> containing test classes, <i>etc.</i> | |
| @@ -47,7 +47,7 @@ public interface Dependency extends Artifact { | |
| Type getType(); | |
| /** | |
| - * {@return the time at which the dependency will be used}. | |
| + * {@return the time at which the dependency will be used} | |
| * It may be, for example, at compile time only, at run time or at test time. | |
| * | |
| * @see DependencyCoordinates#getScope() | |
| @@ -66,7 +66,7 @@ public interface Dependency extends Artifact { | |
| boolean isOptional(); | |
| /** | |
| - * {@return coordinates with the same identifiers as this dependency}. | |
| + * {@return coordinates with the same identifiers as this dependency} | |
| */ | |
| @Nonnull | |
| @Override | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/DownloadedArtifact.java b/api/maven-api-core/src/main/java/org/apache/maven/api/DownloadedArtifact.java | |
| index f01cb2acb9..10e9deb898 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/DownloadedArtifact.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/DownloadedArtifact.java | |
| @@ -33,7 +33,7 @@ | |
| public interface DownloadedArtifact extends Artifact { | |
| /** | |
| - * {@return the a path to the file that has been downloaded to the file system}. | |
| + * {@return the actual file that has been downloaded in the file system} | |
| */ | |
| Path getPath(); | |
| } | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/JavaPathType.java b/api/maven-api-core/src/main/java/org/apache/maven/api/JavaPathType.java | |
| index b2e98ed3c6..7c11ec36da 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/JavaPathType.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/JavaPathType.java | |
| @@ -263,8 +263,8 @@ final String[] format(String moduleName, Iterable<? extends Path> paths) { | |
| if (option == null) { | |
| throw new IllegalStateException("No option is associated to this path type."); | |
| } | |
| - String prefix = (moduleName == null) ? "\"" : (moduleName + "=\""); | |
| - StringJoiner joiner = new StringJoiner(File.pathSeparator, prefix, "\""); | |
| + String prefix = (moduleName == null) ? "" : (moduleName + '='); | |
| + StringJoiner joiner = new StringJoiner(File.pathSeparator, prefix, ""); | |
| joiner.setEmptyValue(""); | |
| for (Path p : paths) { | |
| joiner.add(p.toString()); | |
| @@ -376,25 +376,6 @@ public String[] option(Iterable<? extends Path> paths) { | |
| return format(moduleName, paths); | |
| } | |
| - /** | |
| - * {@return a hash code value based on the raw type and module name}. | |
| - */ | |
| - @Override | |
| - public int hashCode() { | |
| - return rawType().hashCode() + 17 * moduleName.hashCode(); | |
| - } | |
| - | |
| - /** | |
| - * {@return whether the given object represents the same type of path as this object}. | |
| - */ | |
| - @Override | |
| - public boolean equals(Object obj) { | |
| - if (obj instanceof Modular m) { | |
| - return rawType() == m.rawType() && moduleName.equals(m.moduleName); | |
| - } | |
| - return false; | |
| - } | |
| - | |
| /** | |
| * Returns the programmatic name of this path type, including the module to patch. | |
| * For example, if this type was created by {@code JavaPathType.patchModule("foo.bar")}, | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/SourceRoot.java b/api/maven-api-core/src/main/java/org/apache/maven/api/SourceRoot.java | |
| index 4a4aa4f561..c60f6befda 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/SourceRoot.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/SourceRoot.java | |
| @@ -68,8 +68,9 @@ default Path directory() { | |
| * If no syntax is specified, or if its length is 1 character (interpreted as a Windows drive), | |
| * the default is a Maven-specific variation of the {@code "glob"} pattern. | |
| * | |
| - * <p>The default implementation returns an empty list, which means to apply a language-dependent pattern. | |
| - * For example, for the Java language, the pattern includes all files with the {@code .java} suffix.</p> | |
| + * <p> | |
| + * The default implementation returns an empty list, which means to apply a language-dependent pattern. | |
| + * For example, for the Java language, the pattern includes all files with the {@code .java} suffix. | |
| * | |
| * @see java.nio.file.FileSystem#getPathMatcher(String) | |
| */ | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/feature/Features.java b/api/maven-api-core/src/main/java/org/apache/maven/api/feature/Features.java | |
| index acc3d92f5c..91f6b9f350 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/feature/Features.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/feature/Features.java | |
| @@ -19,6 +19,7 @@ | |
| package org.apache.maven.api.feature; | |
| import java.util.Map; | |
| +import java.util.Properties; | |
| import org.apache.maven.api.Constants; | |
| import org.apache.maven.api.annotations.Nullable; | |
| @@ -47,11 +48,8 @@ public static boolean consumerPom(@Nullable Map<String, ?> userProperties) { | |
| return doGet(userProperties, Constants.MAVEN_CONSUMER_POM, !mavenMaven3Personality(userProperties)); | |
| } | |
| - /** | |
| - * Check if build POM deployment is enabled. | |
| - */ | |
| - public static boolean deployBuildPom(@Nullable Map<String, ?> userProperties) { | |
| - return doGet(userProperties, Constants.MAVEN_DEPLOY_BUILD_POM, true); | |
| + private static boolean doGet(Properties userProperties, String key, boolean def) { | |
| + return doGet(userProperties != null ? userProperties.get(key) : null, def); | |
| } | |
| private static boolean doGet(Map<String, ?> userProperties, String key, boolean def) { | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java | |
| index c17884fd97..6604c0392a 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -28,6 +30,12 @@ | |
| @Experimental | |
| public class ArtifactDeployerException extends MavenException { | |
| + /** | |
| + * | |
| + */ | |
| + @Serial | |
| + private static final long serialVersionUID = 7421964724059077698L; | |
| + | |
| /** | |
| * @param message the message of the error | |
| * @param e {@link Exception} | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java | |
| index c683928810..8405fc3017 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -26,6 +28,12 @@ | |
| @Experimental | |
| public class ArtifactInstallerException extends MavenException { | |
| + /** | |
| + * | |
| + */ | |
| + @Serial | |
| + private static final long serialVersionUID = 3652561971360586373L; | |
| + | |
| /** | |
| * @param message the message of the error | |
| * @param e {@link Exception} | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java | |
| index 22d5af16f3..22f398c065 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -28,6 +30,9 @@ | |
| @Experimental | |
| public class ArtifactResolverException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = 7252294837746943917L; | |
| + | |
| private final ArtifactResolverResult result; | |
| /** | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java | |
| index 7e832a95e4..fb012fab30 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java | |
| @@ -40,11 +40,14 @@ | |
| */ | |
| @Experimental | |
| @Immutable | |
| -public interface ArtifactResolverRequest extends RepositoryAwareRequest { | |
| +public interface ArtifactResolverRequest extends Request<Session> { | |
| @Nonnull | |
| Collection<? extends ArtifactCoordinates> getCoordinates(); | |
| + @Nullable | |
| + List<RemoteRepository> getRepositories(); | |
| + | |
| @Nonnull | |
| static ArtifactResolverRequestBuilder builder() { | |
| return new ArtifactResolverRequestBuilder(); | |
| @@ -124,7 +127,7 @@ private static class DefaultArtifactResolverRequest extends BaseRequest<Session> | |
| @Nonnull List<RemoteRepository> repositories) { | |
| super(session, trace); | |
| this.coordinates = List.copyOf(requireNonNull(coordinates, "coordinates cannot be null")); | |
| - this.repositories = validate(repositories); | |
| + this.repositories = repositories; | |
| } | |
| @Nonnull | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ChecksumAlgorithmServiceException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ChecksumAlgorithmServiceException.java | |
| index 7aaed5632f..a42546e828 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ChecksumAlgorithmServiceException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ChecksumAlgorithmServiceException.java | |
| @@ -18,11 +18,16 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| @Experimental | |
| public class ChecksumAlgorithmServiceException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = 1201171469179367694L; | |
| + | |
| public ChecksumAlgorithmServiceException(String message, Throwable cause) { | |
| super(message, cause); | |
| } | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java | |
| index a26a88c6f7..3bc03d1190 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java | |
| @@ -18,11 +18,16 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| @Experimental | |
| public class DependencyResolverException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = 1101171569179057614L; | |
| + | |
| public DependencyResolverException(String message, Throwable cause) { | |
| super(message, cause); | |
| } | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java | |
| index 5be250824d..f419d7ff60 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java | |
| @@ -34,8 +34,6 @@ | |
| import org.apache.maven.api.Project; | |
| import org.apache.maven.api.RemoteRepository; | |
| import org.apache.maven.api.Session; | |
| -import org.apache.maven.api.SourceRoot; | |
| -import org.apache.maven.api.Version; | |
| import org.apache.maven.api.annotations.Experimental; | |
| import org.apache.maven.api.annotations.Immutable; | |
| import org.apache.maven.api.annotations.Nonnull; | |
| @@ -55,7 +53,7 @@ | |
| */ | |
| @Experimental | |
| @Immutable | |
| -public interface DependencyResolverRequest extends RepositoryAwareRequest { | |
| +public interface DependencyResolverRequest extends Request<Session> { | |
| enum RequestType { | |
| COLLECT, | |
| @@ -97,27 +95,8 @@ enum RequestType { | |
| @Nullable | |
| Predicate<PathType> getPathTypeFilter(); | |
| - /** | |
| - * Returns the version of the platform where the code will be executed. | |
| - * It should be the highest value of the {@code <targetVersion>} elements | |
| - * inside the {@code <source>} elements of a <abbr>POM</abbr> file. | |
| - * | |
| - * <h4>Application to Java</h4> | |
| - * In the context of a Java project, this is the value given to the {@code --release} compiler option. | |
| - * This value can determine whether a dependency will be placed on the class-path or on the module-path. | |
| - * For example, if the {@code module-info.class} entry of a <abbr>JAR</abbr> file exists only in the | |
| - * {@code META-INF/versions/17/} sub-directory, then the default location of that dependency will be | |
| - * the module-path only if the {@code --release} option is equal or greater than 17. | |
| - * | |
| - * <p>If this value is not provided, then the default value in the context of Java projects | |
| - * is the Java version on which Maven is running, as given by {@link Runtime#version()}.</p> | |
| - * | |
| - * @return version of the platform where the code will be executed, or {@code null} for default | |
| - * | |
| - * @see SourceRoot#targetVersion() | |
| - */ | |
| @Nullable | |
| - Version getTargetVersion(); | |
| + List<RemoteRepository> getRepositories(); | |
| @Nonnull | |
| static DependencyResolverRequestBuilder builder() { | |
| @@ -202,7 +181,6 @@ class DependencyResolverRequestBuilder { | |
| boolean verbose; | |
| PathScope pathScope; | |
| Predicate<PathType> pathTypeFilter; | |
| - Version targetVersion; | |
| List<RemoteRepository> repositories; | |
| DependencyResolverRequestBuilder() {} | |
| @@ -367,18 +345,6 @@ public DependencyResolverRequestBuilder pathTypeFilter(@Nonnull Collection<? ext | |
| return pathTypeFilter(desiredTypes::contains); | |
| } | |
| - /** | |
| - * Sets the version of the platform where the code will be executed. | |
| - * | |
| - * @param target version of the platform where the code will be executed, or {@code null} for the default | |
| - * @return {@code this} for method call chaining | |
| - */ | |
| - @Nonnull | |
| - public DependencyResolverRequestBuilder targetVersion(@Nullable Version target) { | |
| - targetVersion = target; | |
| - return this; | |
| - } | |
| - | |
| @Nonnull | |
| public DependencyResolverRequestBuilder repositories(@Nonnull List<RemoteRepository> repositories) { | |
| this.repositories = repositories; | |
| @@ -399,7 +365,6 @@ public DependencyResolverRequest build() { | |
| verbose, | |
| pathScope, | |
| pathTypeFilter, | |
| - targetVersion, | |
| repositories); | |
| } | |
| @@ -439,7 +404,6 @@ public String toString() { | |
| private final boolean verbose; | |
| private final PathScope pathScope; | |
| private final Predicate<PathType> pathTypeFilter; | |
| - private final Version targetVersion; | |
| private final List<RemoteRepository> repositories; | |
| /** | |
| @@ -462,7 +426,6 @@ public String toString() { | |
| boolean verbose, | |
| @Nullable PathScope pathScope, | |
| @Nullable Predicate<PathType> pathTypeFilter, | |
| - @Nullable Version targetVersion, | |
| @Nullable List<RemoteRepository> repositories) { | |
| super(session, trace); | |
| this.requestType = requireNonNull(requestType, "requestType cannot be null"); | |
| @@ -475,8 +438,7 @@ public String toString() { | |
| this.verbose = verbose; | |
| this.pathScope = requireNonNull(pathScope, "pathScope cannot be null"); | |
| this.pathTypeFilter = (pathTypeFilter != null) ? pathTypeFilter : DEFAULT_FILTER; | |
| - this.targetVersion = targetVersion; | |
| - this.repositories = validate(repositories); | |
| + this.repositories = repositories; | |
| if (verbose && requestType != RequestType.COLLECT) { | |
| throw new IllegalArgumentException("verbose cannot only be true when collecting dependencies"); | |
| } | |
| @@ -533,11 +495,6 @@ public Predicate<PathType> getPathTypeFilter() { | |
| return pathTypeFilter; | |
| } | |
| - @Override | |
| - public Version getTargetVersion() { | |
| - return targetVersion; | |
| - } | |
| - | |
| @Override | |
| public List<RemoteRepository> getRepositories() { | |
| return repositories; | |
| @@ -555,7 +512,6 @@ public boolean equals(Object o) { | |
| && Objects.equals(managedDependencies, that.managedDependencies) | |
| && Objects.equals(pathScope, that.pathScope) | |
| && Objects.equals(pathTypeFilter, that.pathTypeFilter) | |
| - && Objects.equals(targetVersion, that.targetVersion) | |
| && Objects.equals(repositories, that.repositories); | |
| } | |
| @@ -571,7 +527,6 @@ public int hashCode() { | |
| verbose, | |
| pathScope, | |
| pathTypeFilter, | |
| - targetVersion, | |
| repositories); | |
| } | |
| @@ -586,8 +541,7 @@ public String toString() { | |
| + managedDependencies + ", verbose=" | |
| + verbose + ", pathScope=" | |
| + pathScope + ", pathTypeFilter=" | |
| - + pathTypeFilter + ", targetVersion=" | |
| - + targetVersion + ", repositories=" | |
| + + pathTypeFilter + ", repositories=" | |
| + repositories + ']'; | |
| } | |
| } | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/InterpolatorException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/InterpolatorException.java | |
| index e3e100ecc0..b7ca808a78 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/InterpolatorException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/InterpolatorException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -29,6 +31,9 @@ | |
| @Experimental | |
| public class InterpolatorException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = -1219149033636851813L; | |
| + | |
| /** | |
| * Constructs a new InterpolatorException with {@code null} as its | |
| * detail message. The cause is not initialized, and may subsequently be | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java | |
| index ee67fa9bdc..97670213c1 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -28,6 +30,9 @@ | |
| @Experimental | |
| public class LookupException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = -6259322450070320286L; | |
| + | |
| public LookupException(String message) { | |
| super(message); | |
| } | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java | |
| index cdd9ced96c..5121ce8c75 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -28,6 +30,9 @@ | |
| @Experimental | |
| public class MavenException extends RuntimeException { | |
| + @Serial | |
| + private static final long serialVersionUID = 9027638326336093132L; | |
| + | |
| public MavenException() {} | |
| public MavenException(String message) { | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilder.java | |
| index ea8e263392..f13a60def8 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilder.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilder.java | |
| @@ -29,9 +29,7 @@ public interface ModelBuilder extends Service { | |
| String MODEL_VERSION_4_1_0 = "4.1.0"; | |
| - String MODEL_VERSION_4_2_0 = "4.2.0"; | |
| - | |
| - List<String> KNOWN_MODEL_VERSIONS = List.of(MODEL_VERSION_4_0_0, MODEL_VERSION_4_1_0, MODEL_VERSION_4_2_0); | |
| + List<String> KNOWN_MODEL_VERSIONS = List.of(MODEL_VERSION_4_0_0, MODEL_VERSION_4_1_0); | |
| ModelBuilderSession newSession(); | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderException.java | |
| index cd6b9b5062..c01fa138ab 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -28,6 +30,9 @@ | |
| @Experimental | |
| public class ModelBuilderException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = -1865447022070650896L; | |
| + | |
| private final ModelBuilderResult result; | |
| /** | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderRequest.java | |
| index 826ffe8fc4..14141a6d0c 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderRequest.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderRequest.java | |
| @@ -43,7 +43,7 @@ | |
| */ | |
| @Experimental | |
| @Immutable | |
| -public interface ModelBuilderRequest extends RepositoryAwareRequest { | |
| +public interface ModelBuilderRequest extends Request<Session> { | |
| /** | |
| * The possible request types for building a model. | |
| @@ -133,6 +133,9 @@ enum RepositoryMerging { | |
| @Nonnull | |
| RepositoryMerging getRepositoryMerging(); | |
| + @Nullable | |
| + List<RemoteRepository> getRepositories(); | |
| + | |
| @Nullable | |
| ModelTransformer getLifecycleBindingsInjector(); | |
| @@ -335,7 +338,7 @@ private static class DefaultModelBuilderRequest extends BaseRequest<Session> imp | |
| systemProperties != null ? Map.copyOf(systemProperties) : session.getSystemProperties(); | |
| this.userProperties = userProperties != null ? Map.copyOf(userProperties) : session.getUserProperties(); | |
| this.repositoryMerging = repositoryMerging; | |
| - this.repositories = repositories != null ? List.copyOf(validate(repositories)) : null; | |
| + this.repositories = repositories != null ? List.copyOf(repositories) : null; | |
| this.lifecycleBindingsInjector = lifecycleBindingsInjector; | |
| } | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelProblem.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelProblem.java | |
| index 63bad258bf..07ba7bbe92 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelProblem.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelProblem.java | |
| @@ -66,12 +66,7 @@ enum Version { | |
| /** | |
| * Validation for Maven 4.1 POM format. | |
| */ | |
| - V41, | |
| - | |
| - /** | |
| - * Validation for Maven 4.2 POM format. | |
| - */ | |
| - V42 | |
| + V41 | |
| } | |
| /** | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelSource.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelSource.java | |
| index a259ba52cd..325b1d4419 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelSource.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelSource.java | |
| @@ -42,22 +42,6 @@ | |
| */ | |
| public interface ModelSource extends Source { | |
| - /** | |
| - * Returns the model identifier in the format {@code groupId:artifactId:version} | |
| - * if this source represents a resolved artifact with known coordinates. | |
| - * <p> | |
| - * This method is primarily used by resolved sources to provide the model ID | |
| - * without requiring the XML to be parsed. For build sources, this typically | |
| - * returns {@code null} since the coordinates are determined by parsing the POM. | |
| - * | |
| - * @return the model identifier, or {@code null} if not available or not applicable | |
| - * @since 4.0.0 | |
| - */ | |
| - @Nullable | |
| - default String getModelId() { | |
| - return null; | |
| - } | |
| - | |
| /** | |
| * Interface for locating POM files within a project structure. | |
| * Implementations of this interface provide the ability to find POM files | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProblemCollector.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProblemCollector.java | |
| index 11fbb4bce0..6e5a9d29f6 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProblemCollector.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProblemCollector.java | |
| @@ -26,7 +26,6 @@ | |
| import java.util.concurrent.CopyOnWriteArrayList; | |
| import java.util.concurrent.atomic.AtomicInteger; | |
| import java.util.concurrent.atomic.LongAdder; | |
| -import java.util.function.Predicate; | |
| import java.util.stream.Stream; | |
| import org.apache.maven.api.Constants; | |
| @@ -182,27 +181,13 @@ public Stream<P> problems(BuilderProblem.Severity severity) { | |
| static <P extends BuilderProblem> ProblemCollector<P> create(@Nullable ProtoSession protoSession) { | |
| if (protoSession != null | |
| && protoSession.getUserProperties().containsKey(Constants.MAVEN_BUILDER_MAX_PROBLEMS)) { | |
| - int limit = Integer.parseInt(protoSession.getUserProperties().get(Constants.MAVEN_BUILDER_MAX_PROBLEMS)); | |
| - return create(limit, p -> true); | |
| + return new Impl<>( | |
| + Integer.parseInt(protoSession.getUserProperties().get(Constants.MAVEN_BUILDER_MAX_PROBLEMS))); | |
| } else { | |
| return create(100); | |
| } | |
| } | |
| - /** | |
| - * Creates new instance of problem collector with the specified maximum problem count limit, | |
| - * but only preserves problems that match the given filter. | |
| - * | |
| - * @param <P> the type of problem | |
| - * @param maxCountLimit the maximum number of problems to preserve | |
| - * @param filter predicate to decide which problems to record | |
| - * @return a new filtered problem collector instance | |
| - */ | |
| - @Nonnull | |
| - static <P extends BuilderProblem> ProblemCollector<P> create(int maxCountLimit, Predicate<? super P> filter) { | |
| - return new Impl<>(maxCountLimit, filter); | |
| - } | |
| - | |
| /** | |
| * Creates new instance of problem collector with the specified maximum problem count limit. | |
| * Visible for testing only. | |
| @@ -213,7 +198,7 @@ static <P extends BuilderProblem> ProblemCollector<P> create(int maxCountLimit, | |
| */ | |
| @Nonnull | |
| static <P extends BuilderProblem> ProblemCollector<P> create(int maxCountLimit) { | |
| - return create(maxCountLimit, p -> true); | |
| + return new Impl<>(maxCountLimit); | |
| } | |
| /** | |
| @@ -227,14 +212,13 @@ static <P extends BuilderProblem> ProblemCollector<P> create(int maxCountLimit) | |
| private final AtomicInteger totalCount; | |
| private final ConcurrentMap<BuilderProblem.Severity, LongAdder> counters; | |
| private final ConcurrentMap<BuilderProblem.Severity, List<P>> problems; | |
| - private final Predicate<? super P> filter; | |
| private static final List<BuilderProblem.Severity> REVERSED_ORDER = Arrays.stream( | |
| BuilderProblem.Severity.values()) | |
| .sorted(Comparator.reverseOrder()) | |
| .toList(); | |
| - private Impl(int maxCountLimit, Predicate<? super P> filter) { | |
| + private Impl(int maxCountLimit) { | |
| if (maxCountLimit < 0) { | |
| throw new IllegalArgumentException("maxCountLimit must be non-negative"); | |
| } | |
| @@ -242,7 +226,6 @@ private Impl(int maxCountLimit, Predicate<? super P> filter) { | |
| this.totalCount = new AtomicInteger(); | |
| this.counters = new ConcurrentHashMap<>(); | |
| this.problems = new ConcurrentHashMap<>(); | |
| - this.filter = requireNonNull(filter, "filter"); | |
| } | |
| @Override | |
| @@ -262,11 +245,6 @@ public boolean problemsOverflow() { | |
| @Override | |
| public boolean reportProblem(P problem) { | |
| requireNonNull(problem, "problem"); | |
| - // first apply filter | |
| - if (!filter.test(problem)) { | |
| - // drop without counting towards preserved problems | |
| - return false; | |
| - } | |
| int currentCount = totalCount.incrementAndGet(); | |
| getCounter(problem.getSeverity()).increment(); | |
| if (currentCount <= maxCountLimit || dropProblemWithLowerSeverity(problem.getSeverity())) { | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java | |
| index baee35bd43..d6adcaee2a 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -28,6 +30,9 @@ | |
| @Experimental | |
| public class ProjectBuilderException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = -7629871850875943799L; | |
| + | |
| /** | |
| * @param message the message to give | |
| * @param e the {@link Exception} | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java | |
| index 307ee19559..82129b4f1b 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java | |
| @@ -43,7 +43,7 @@ | |
| */ | |
| @Experimental | |
| @Immutable | |
| -public interface ProjectBuilderRequest extends RepositoryAwareRequest { | |
| +public interface ProjectBuilderRequest extends Request<Session> { | |
| /** | |
| * Gets the path to the project to build. | |
| @@ -265,7 +265,7 @@ private static class DefaultProjectBuilderRequest extends BaseRequest<Session> | |
| this.allowStubModel = allowStubModel; | |
| this.recursive = recursive; | |
| this.processPlugins = processPlugins; | |
| - this.repositories = validate(repositories); | |
| + this.repositories = repositories; | |
| } | |
| @Nonnull | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java | |
| index 421baa8f76..ca17937dfc 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -28,6 +30,9 @@ | |
| @Experimental | |
| public class PrompterException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = -3505070928479515081L; | |
| + | |
| public PrompterException(String message) { | |
| super(message); | |
| } | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryAwareRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryAwareRequest.java | |
| deleted file mode 100644 | |
| index f948ecdea4..0000000000 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryAwareRequest.java | |
| +++ /dev/null | |
| @@ -1,117 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.api.services; | |
| - | |
| -import java.util.HashSet; | |
| -import java.util.List; | |
| -import java.util.Objects; | |
| - | |
| -import org.apache.maven.api.RemoteRepository; | |
| -import org.apache.maven.api.Session; | |
| -import org.apache.maven.api.annotations.Experimental; | |
| -import org.apache.maven.api.annotations.Immutable; | |
| -import org.apache.maven.api.annotations.Nullable; | |
| - | |
| -/** | |
| - * Base interface for service requests that involve remote repository operations. | |
| - * This interface provides common functionality for requests that need to specify | |
| - * and validate remote repositories for artifact resolution, dependency collection, | |
| - * model building, and other Maven operations. | |
| - * | |
| - * <p>Implementations of this interface can specify a list of remote repositories | |
| - * to be used during the operation. If no repositories are specified (null), | |
| - * the session's default remote repositories will be used. The repositories | |
| - * are validated to ensure they don't contain duplicates or null entries. | |
| - * | |
| - * <p>Remote repositories are used for: | |
| - * <ul> | |
| - * <li>Resolving artifacts and their metadata</li> | |
| - * <li>Downloading parent POMs and dependency POMs</li> | |
| - * <li>Retrieving version information and ranges</li> | |
| - * <li>Accessing plugin artifacts and their dependencies</li> | |
| - * </ul> | |
| - * | |
| - * <p>Repository validation ensures data integrity by: | |
| - * <ul> | |
| - * <li>Preventing duplicate repositories that could cause confusion</li> | |
| - * <li>Rejecting null repository entries that would cause failures</li> | |
| - * <li>Maintaining consistent repository ordering for reproducible builds</li> | |
| - * </ul> | |
| - * | |
| - * @since 4.0.0 | |
| - * @see RemoteRepository | |
| - * @see Session#getRemoteRepositories() | |
| - */ | |
| -@Experimental | |
| -@Immutable | |
| -public interface RepositoryAwareRequest extends Request<Session> { | |
| - | |
| - /** | |
| - * Returns the list of remote repositories to be used for this request. | |
| - * | |
| - * <p>If this method returns {@code null}, the session's default remote repositories | |
| - * will be used. If a non-null list is returned, it will be used instead of the | |
| - * session's repositories, allowing for request-specific repository configuration. | |
| - * | |
| - * <p>The returned list should not contain duplicate repositories (based on their | |
| - * equality) or null entries, as these will cause validation failures when the | |
| - * request is processed. | |
| - * | |
| - * @return the list of remote repositories to use, or {@code null} to use session defaults | |
| - * @see Session#getRemoteRepositories() | |
| - */ | |
| - @Nullable | |
| - List<RemoteRepository> getRepositories(); | |
| - | |
| - /** | |
| - * Validates a list of remote repositories to ensure data integrity. | |
| - * | |
| - * <p>This method performs the following validations: | |
| - * <ul> | |
| - * <li>Allows null input (returns null)</li> | |
| - * <li>Ensures no duplicate repositories exist in the list</li> | |
| - * <li>Ensures no null repository entries exist in the list</li> | |
| - * </ul> | |
| - * | |
| - * <p>Duplicate detection is based on the {@code RemoteRepository#equals(Object)} | |
| - * method, which typically compares repository IDs and URLs. | |
| - * | |
| - * @param repositories the list of repositories to validate, may be {@code null} | |
| - * @return the same list if validation passes, or {@code null} if input was {@code null} | |
| - * @throws IllegalArgumentException if the list contains duplicate repositories | |
| - * @throws IllegalArgumentException if the list contains null repository entries | |
| - */ | |
| - default List<RemoteRepository> validate(List<RemoteRepository> repositories) { | |
| - if (repositories == null) { | |
| - return null; | |
| - } | |
| - HashSet<RemoteRepository> set = new HashSet<>(repositories); | |
| - if (repositories.size() != set.size()) { | |
| - throw new IllegalArgumentException( | |
| - "Repository list contains duplicate entries. Each repository must be unique based on its ID and URL. " | |
| - + "Found " + repositories.size() + " repositories but only " + set.size() | |
| - + " unique entries."); | |
| - } | |
| - if (repositories.stream().anyMatch(Objects::isNull)) { | |
| - throw new IllegalArgumentException( | |
| - "Repository list contains null entries. All repository entries must be non-null RemoteRepository instances."); | |
| - } | |
| - return repositories; | |
| - } | |
| -} | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderException.java | |
| index 2c81d87399..a8ccd0f47f 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -28,6 +30,9 @@ | |
| @Experimental | |
| public class SettingsBuilderException extends MavenBuilderException { | |
| + @Serial | |
| + private static final long serialVersionUID = 4714858598345418083L; | |
| + | |
| /** | |
| * @param message the message to give | |
| * @param e the {@link Exception} | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/Sources.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Sources.java | |
| index 73d8978424..4acab6006a 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/Sources.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Sources.java | |
| @@ -84,13 +84,13 @@ public static ModelSource buildSource(@Nonnull Path path) { | |
| * other sources. | |
| * | |
| * @param path the path to the POM file or project directory | |
| - * @param modelId the modelId (groupId:artifactId:version coordinates) | |
| + * @param location optional logical location of the source, used for reporting purposes | |
| * @return a new ModelSource instance configured as a resolved source | |
| * @throws NullPointerException if path is null | |
| */ | |
| @Nonnull | |
| - public static ModelSource resolvedSource(@Nonnull Path path, @Nullable String modelId) { | |
| - return new ResolvedPathSource(requireNonNull(path, "path"), path.toString(), modelId); | |
| + public static ModelSource resolvedSource(@Nonnull Path path, @Nullable String location) { | |
| + return new ResolvedPathSource(requireNonNull(path, "path"), location); | |
| } | |
| /** | |
| @@ -170,12 +170,8 @@ public String toString() { | |
| * from repositories. Does not support resolving related sources. | |
| */ | |
| static class ResolvedPathSource extends PathSource implements ModelSource { | |
| - @Nullable | |
| - private final String modelId; | |
| - | |
| - ResolvedPathSource(Path path, String location, String modelId) { | |
| + ResolvedPathSource(Path path, String location) { | |
| super(path, location); | |
| - this.modelId = modelId; | |
| } | |
| @Override | |
| @@ -183,12 +179,6 @@ public Path getPath() { | |
| return null; | |
| } | |
| - @Override | |
| - @Nullable | |
| - public String getModelId() { | |
| - return modelId; | |
| - } | |
| - | |
| @Override | |
| public Source resolve(String relative) { | |
| return null; | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SuperPomProviderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SuperPomProviderException.java | |
| index 4aa6890ca3..8014e28b3a 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SuperPomProviderException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SuperPomProviderException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| /** | |
| * Exceptions thrown by the {@link SuperPomProvider} service. | |
| * | |
| @@ -25,6 +27,9 @@ | |
| */ | |
| public class SuperPomProviderException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = -8659892034004509331L; | |
| + | |
| public SuperPomProviderException() { | |
| super(); | |
| } | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java | |
| index 574f7dc144..38812cee2c 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -28,6 +30,9 @@ | |
| @Experimental | |
| public class ToolchainManagerException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = -9465854226608498L; | |
| + | |
| /** | |
| * @param message the message to give | |
| * @param e the {@link Exception} | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderException.java | |
| index 826cc5f7e9..10bd3b5dc5 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -28,6 +30,9 @@ | |
| @Experimental | |
| public class ToolchainsBuilderException extends MavenBuilderException { | |
| + @Serial | |
| + private static final long serialVersionUID = 7899871809665729349L; | |
| + | |
| /** | |
| * @param message the message to give | |
| * @param e the {@link Exception} | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/TransportProviderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/TransportProviderException.java | |
| index c78fa37e24..3347d73539 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/TransportProviderException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/TransportProviderException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Consumer; | |
| import org.apache.maven.api.annotations.Experimental; | |
| @@ -28,6 +30,9 @@ | |
| @Consumer | |
| public class TransportProviderException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = -6066070072576465969L; | |
| + | |
| public TransportProviderException(String message, Throwable cause) { | |
| super(message, cause); | |
| } | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java | |
| index e22235afa2..38bedc1275 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Experimental; | |
| /** | |
| @@ -28,6 +30,9 @@ | |
| @Experimental | |
| public class VersionParserException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = 1504740189114877333L; | |
| + | |
| /** | |
| * @param message the message to give | |
| * @param e the {@link Exception} | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverException.java | |
| index dd0746844f..d32d0fae87 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Consumer; | |
| import org.apache.maven.api.annotations.Experimental; | |
| @@ -28,6 +30,9 @@ | |
| @Consumer | |
| public class VersionRangeResolverException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = 4455478418692494141L; | |
| + | |
| public VersionRangeResolverException(String message, Throwable cause) { | |
| super(message, cause); | |
| } | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverRequest.java | |
| index 2f69c574a3..52abe9e89a 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverRequest.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverRequest.java | |
| @@ -36,11 +36,14 @@ | |
| * @since 4.0.0 | |
| */ | |
| @Experimental | |
| -public interface VersionRangeResolverRequest extends RepositoryAwareRequest { | |
| +public interface VersionRangeResolverRequest extends Request<Session> { | |
| @Nonnull | |
| ArtifactCoordinates getArtifactCoordinates(); | |
| + @Nullable | |
| + List<RemoteRepository> getRepositories(); | |
| + | |
| @Nonnull | |
| static VersionRangeResolverRequest build( | |
| @Nonnull Session session, @Nonnull ArtifactCoordinates artifactCoordinates) { | |
| @@ -108,7 +111,7 @@ private static class DefaultVersionResolverRequest extends BaseRequest<Session> | |
| @Nullable List<RemoteRepository> repositories) { | |
| super(session, trace); | |
| this.artifactCoordinates = artifactCoordinates; | |
| - this.repositories = validate(repositories); | |
| + this.repositories = repositories; | |
| } | |
| @Nonnull | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverException.java | |
| index 6eb5b0989c..3b650a135c 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverException.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverException.java | |
| @@ -18,6 +18,8 @@ | |
| */ | |
| package org.apache.maven.api.services; | |
| +import java.io.Serial; | |
| + | |
| import org.apache.maven.api.annotations.Consumer; | |
| import org.apache.maven.api.annotations.Experimental; | |
| @@ -28,6 +30,9 @@ | |
| @Consumer | |
| public class VersionResolverException extends MavenException { | |
| + @Serial | |
| + private static final long serialVersionUID = -2105433586719466573L; | |
| + | |
| public VersionResolverException(String message, Throwable cause) { | |
| super(message, cause); | |
| } | |
| diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverRequest.java | |
| index b510dcc2de..c8dee58a8f 100644 | |
| --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverRequest.java | |
| +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverRequest.java | |
| @@ -36,11 +36,14 @@ | |
| * @since 4.0.0 | |
| */ | |
| @Experimental | |
| -public interface VersionResolverRequest extends RepositoryAwareRequest { | |
| +public interface VersionResolverRequest extends Request<Session> { | |
| @Nonnull | |
| ArtifactCoordinates getArtifactCoordinates(); | |
| + @Nullable | |
| + List<RemoteRepository> getRepositories(); | |
| + | |
| @Nonnull | |
| static VersionResolverRequest build(@Nonnull Session session, @Nonnull ArtifactCoordinates artifactCoordinates) { | |
| return builder() | |
| @@ -110,7 +113,7 @@ private static class DefaultVersionResolverRequest extends BaseRequest<Session> | |
| @Nullable List<RemoteRepository> repositories) { | |
| super(session, trace); | |
| this.artifactCoordinates = artifactCoordinates; | |
| - this.repositories = validate(repositories); | |
| + this.repositories = repositories; | |
| } | |
| @Nonnull | |
| diff --git a/api/maven-api-core/src/test/java/org/apache/maven/api/JavaPathTypeTest.java b/api/maven-api-core/src/test/java/org/apache/maven/api/JavaPathTypeTest.java | |
| deleted file mode 100644 | |
| index 701a82775b..0000000000 | |
| --- a/api/maven-api-core/src/test/java/org/apache/maven/api/JavaPathTypeTest.java | |
| +++ /dev/null | |
| @@ -1,83 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.api; | |
| - | |
| -import java.io.File; | |
| -import java.nio.file.Path; | |
| -import java.util.List; | |
| - | |
| -import org.junit.jupiter.api.Test; | |
| - | |
| -import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertNotEquals; | |
| - | |
| -public class JavaPathTypeTest { | |
| - /** | |
| - * {@return dummy paths to use in tests}. | |
| - */ | |
| - private static List<Path> paths() { | |
| - return List.of(Path.of("src", "foo.java"), Path.of("src", "bar.java")); | |
| - } | |
| - | |
| - /** | |
| - * Converts paths from Unix style to platform-dependent style. | |
| - * | |
| - * @param expected the option value expected by the test | |
| - * @return the expected value with separators of the host | |
| - */ | |
| - private static String toPlatformSpecific(String expected) { | |
| - return expected.replace("/", File.separator).replace(":", File.pathSeparator); | |
| - } | |
| - | |
| - /** | |
| - * Tests the formatting of an option without module name. | |
| - */ | |
| - @Test | |
| - public void testOption() { | |
| - String[] formatted = JavaPathType.MODULES.option(paths()); | |
| - assertEquals(2, formatted.length); | |
| - assertEquals("--module-path", formatted[0]); | |
| - assertEquals(toPlatformSpecific("\"src/foo.java:src/bar.java\""), formatted[1]); | |
| - } | |
| - | |
| - /** | |
| - * Tests the formatting of an option with a module name. | |
| - */ | |
| - @Test | |
| - public void testModularOption() { | |
| - String[] formatted = JavaPathType.patchModule("my.module").option(paths()); | |
| - assertEquals(2, formatted.length); | |
| - assertEquals("--patch-module", formatted[0]); | |
| - assertEquals(toPlatformSpecific("my.module=\"src/foo.java:src/bar.java\""), formatted[1]); | |
| - } | |
| - | |
| - /** | |
| - * Tests the {@code equals} and {@code hashCode} methods of options. | |
| - */ | |
| - @Test | |
| - public void testEqualsHashCode() { | |
| - JavaPathType.Modular foo1 = JavaPathType.patchModule("foo"); | |
| - JavaPathType.Modular foo2 = JavaPathType.patchModule("foo"); | |
| - JavaPathType.Modular bar = JavaPathType.patchModule("bar"); | |
| - assertEquals(foo1, foo2); | |
| - assertEquals(foo1.hashCode(), foo2.hashCode()); | |
| - assertNotEquals(foo1, bar); | |
| - assertNotEquals(foo1.hashCode(), bar.hashCode()); | |
| - } | |
| -} | |
| diff --git a/api/maven-api-core/src/test/java/org/apache/maven/api/feature/FeaturesTest.java b/api/maven-api-core/src/test/java/org/apache/maven/api/feature/FeaturesTest.java | |
| deleted file mode 100644 | |
| index 0b938b9df3..0000000000 | |
| --- a/api/maven-api-core/src/test/java/org/apache/maven/api/feature/FeaturesTest.java | |
| +++ /dev/null | |
| @@ -1,194 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.api.feature; | |
| - | |
| -import java.util.HashMap; | |
| -import java.util.Map; | |
| - | |
| -import org.apache.maven.api.Constants; | |
| -import org.junit.jupiter.api.Test; | |
| - | |
| -import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| - | |
| -/** | |
| - * Unit tests for the Features class. | |
| - */ | |
| -class FeaturesTest { | |
| - | |
| - @Test | |
| - void testDeployBuildPomDefaultValue() { | |
| - // Test that deployBuildPom returns true by default (when property is not set) | |
| - Map<String, Object> emptyProperties = Map.of(); | |
| - assertTrue(Features.deployBuildPom(emptyProperties)); | |
| - | |
| - // Test with null properties | |
| - assertTrue(Features.deployBuildPom(null)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithStringTrue() { | |
| - // Test with string "true" | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "true"); | |
| - assertTrue(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithStringFalse() { | |
| - // Test with string "false" | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "false"); | |
| - assertFalse(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithBooleanTrue() { | |
| - // Test with Boolean.TRUE | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, Boolean.TRUE); | |
| - assertTrue(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithBooleanFalse() { | |
| - // Test with Boolean.FALSE | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, Boolean.FALSE); | |
| - assertFalse(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithStringTrueUpperCase() { | |
| - // Test case-insensitive string parsing - TRUE | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "TRUE"); | |
| - assertTrue(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithStringFalseUpperCase() { | |
| - // Test case-insensitive string parsing - FALSE | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "FALSE"); | |
| - assertFalse(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithStringTrueMixedCase() { | |
| - // Test case-insensitive string parsing - True | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "True"); | |
| - assertTrue(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithStringFalseMixedCase() { | |
| - // Test case-insensitive string parsing - False | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "False"); | |
| - assertFalse(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithInvalidStringValue() { | |
| - // Test that invalid string values default to false (Boolean.parseBoolean behavior) | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "invalid"); | |
| - assertFalse(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithEmptyString() { | |
| - // Test that empty string defaults to false | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, ""); | |
| - assertFalse(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithYesString() { | |
| - // Test that "yes" string defaults to false (not a valid boolean) | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "yes"); | |
| - assertFalse(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithNumericString() { | |
| - // Test that numeric string defaults to false | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "1"); | |
| - assertFalse(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithIntegerOne() { | |
| - // Test with integer 1 (should use toString() and then parseBoolean) | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, 1); | |
| - assertFalse(Features.deployBuildPom(properties)); // "1".parseBoolean() = false | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithIntegerZero() { | |
| - // Test with integer 0 (should use toString() and then parseBoolean) | |
| - Map<String, Object> properties = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, 0); | |
| - assertFalse(Features.deployBuildPom(properties)); // "0".parseBoolean() = false | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithMutableMap() { | |
| - // Test with a mutable map to ensure the method doesn't modify the input | |
| - Map<String, Object> properties = new HashMap<>(); | |
| - properties.put(Constants.MAVEN_DEPLOY_BUILD_POM, "false"); | |
| - | |
| - assertFalse(Features.deployBuildPom(properties)); | |
| - | |
| - // Verify the map wasn't modified | |
| - assertEquals(1, properties.size()); | |
| - assertEquals("false", properties.get(Constants.MAVEN_DEPLOY_BUILD_POM)); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithOtherProperties() { | |
| - // Test that other properties don't interfere | |
| - Map<String, Object> properties = Map.of( | |
| - Constants.MAVEN_CONSUMER_POM, | |
| - "false", | |
| - Constants.MAVEN_MAVEN3_PERSONALITY, | |
| - "true", | |
| - "some.other.property", | |
| - "value", | |
| - Constants.MAVEN_DEPLOY_BUILD_POM, | |
| - "false"); | |
| - | |
| - assertFalse(Features.deployBuildPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testConsistencyWithOtherFeatureMethodsFalse() { | |
| - // Test that deployBuildPom behaves consistently with other feature methods when false | |
| - Map<String, Object> properties = Map.of( | |
| - Constants.MAVEN_DEPLOY_BUILD_POM, "false", | |
| - Constants.MAVEN_CONSUMER_POM, "false"); | |
| - | |
| - assertFalse(Features.deployBuildPom(properties)); | |
| - assertFalse(Features.consumerPom(properties)); | |
| - } | |
| - | |
| - @Test | |
| - void testConsistencyWithOtherFeatureMethodsTrue() { | |
| - // Test that deployBuildPom behaves consistently with other feature methods when true | |
| - Map<String, Object> properties = Map.of( | |
| - Constants.MAVEN_DEPLOY_BUILD_POM, "true", | |
| - Constants.MAVEN_CONSUMER_POM, "true"); | |
| - | |
| - assertTrue(Features.deployBuildPom(properties)); | |
| - assertTrue(Features.consumerPom(properties)); | |
| - } | |
| -} | |
| diff --git a/api/maven-api-core/src/test/java/org/apache/maven/api/services/ModelSourceTest.java b/api/maven-api-core/src/test/java/org/apache/maven/api/services/ModelSourceTest.java | |
| deleted file mode 100644 | |
| index 7a293a255b..0000000000 | |
| --- a/api/maven-api-core/src/test/java/org/apache/maven/api/services/ModelSourceTest.java | |
| +++ /dev/null | |
| @@ -1,71 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.api.services; | |
| - | |
| -import java.nio.file.Path; | |
| -import java.nio.file.Paths; | |
| - | |
| -import org.junit.jupiter.api.Test; | |
| - | |
| -import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| -import static org.junit.jupiter.api.Assertions.assertNull; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| - | |
| -/** | |
| - * Test for ModelSource interface and its implementations. | |
| - */ | |
| -class ModelSourceTest { | |
| - | |
| - @Test | |
| - void testBuildSourceHasNoModelId() { | |
| - Path path = Paths.get("/tmp/pom.xml"); | |
| - ModelSource source = Sources.buildSource(path); | |
| - | |
| - assertNotNull(source); | |
| - assertNull(source.getModelId(), "Build sources should not have a modelId"); | |
| - assertEquals(path, source.getPath()); | |
| - } | |
| - | |
| - @Test | |
| - void testResolvedSourceWithModelId() { | |
| - String location = "/tmp/resolved-pom.xml"; | |
| - Path path = Paths.get(location); | |
| - String modelId = "org.apache.maven:maven-core:4.0.0"; | |
| - | |
| - ModelSource source = Sources.resolvedSource(path, modelId); | |
| - | |
| - assertNotNull(source); | |
| - assertEquals(modelId, source.getModelId(), "Resolved source should return the provided modelId"); | |
| - assertNull(source.getPath(), "Resolved sources should return null for getPath()"); | |
| - assertEquals(path.toString(), source.getLocation()); | |
| - } | |
| - | |
| - @Test | |
| - void testModelIdFormat() { | |
| - String location = "/tmp/test.xml"; | |
| - Path path = Paths.get(location); | |
| - String modelId = "com.example:test-artifact:1.2.3"; | |
| - | |
| - ModelSource source = Sources.resolvedSource(path, modelId); | |
| - | |
| - assertEquals(modelId, source.getModelId()); | |
| - assertTrue(modelId.matches("^[^:]+:[^:]+:[^:]+$"), "ModelId should follow groupId:artifactId:version format"); | |
| - } | |
| -} | |
| diff --git a/api/maven-api-core/src/test/java/org/apache/maven/api/services/RequestImplementationTest.java b/api/maven-api-core/src/test/java/org/apache/maven/api/services/RequestImplementationTest.java | |
| index 694956063e..eef64a1388 100644 | |
| --- a/api/maven-api-core/src/test/java/org/apache/maven/api/services/RequestImplementationTest.java | |
| +++ b/api/maven-api-core/src/test/java/org/apache/maven/api/services/RequestImplementationTest.java | |
| @@ -69,8 +69,8 @@ void testArtifactResolverRequestEquality() { | |
| // Test toString | |
| String toString = request1.toString(); | |
| - assertTrue(toString.contains("coordinates="), "Expected " + toString + " to contain " + "coordinates="); | |
| - assertTrue(toString.contains("repositories="), "Expected " + toString + " to contain " + "repositories="); | |
| + assertTrue(toString.contains("coordinates=")); | |
| + assertTrue(toString.contains("repositories=")); | |
| } | |
| @Test | |
| @@ -110,7 +110,7 @@ void testDependencyResolverRequestEquality() { | |
| assertNotEquals(request1, request3); | |
| String toString = request1.toString(); | |
| - assertTrue(toString.contains("requestType="), "Expected " + toString + " to contain " + "requestType="); | |
| - assertTrue(toString.contains("pathScope="), "Expected " + toString + " to contain " + "pathScope="); | |
| + assertTrue(toString.contains("requestType=")); | |
| + assertTrue(toString.contains("pathScope=")); | |
| } | |
| } | |
| diff --git a/api/maven-api-core/src/test/java/org/apache/maven/api/services/SourcesTest.java b/api/maven-api-core/src/test/java/org/apache/maven/api/services/SourcesTest.java | |
| index 58aec58f1e..f9abbe66d2 100644 | |
| --- a/api/maven-api-core/src/test/java/org/apache/maven/api/services/SourcesTest.java | |
| +++ b/api/maven-api-core/src/test/java/org/apache/maven/api/services/SourcesTest.java | |
| @@ -64,16 +64,14 @@ void testBuildSource() { | |
| @Test | |
| void testResolvedSource() { | |
| - String location = "/tmp"; | |
| - Path path = Paths.get(location); | |
| - String modelId = "org.example:test:1.0.0"; | |
| - ModelSource source = Sources.resolvedSource(path, modelId); | |
| + Path path = Paths.get("/tmp"); | |
| + String location = "custom-location"; | |
| + ModelSource source = Sources.resolvedSource(path, location); | |
| assertNotNull(source); | |
| assertInstanceOf(Sources.ResolvedPathSource.class, source); | |
| assertNull(source.getPath()); | |
| - assertEquals(path.toString(), source.getLocation()); | |
| - assertEquals(modelId, source.getModelId()); | |
| + assertEquals(location, source.getLocation()); | |
| } | |
| @Test | |
| @@ -111,14 +109,12 @@ void testBuildPathSourceFunctionality() { | |
| @Test | |
| void testResolvedPathSourceFunctionality() { | |
| // Test resolved source functionality | |
| - String location = "/tmp"; | |
| - Path path = Paths.get(location); | |
| - String modelId = "org.example:test:1.0.0"; | |
| - Sources.ResolvedPathSource source = (Sources.ResolvedPathSource) Sources.resolvedSource(path, modelId); | |
| + Path path = Paths.get("/tmp"); | |
| + String location = "custom-location"; | |
| + Sources.ResolvedPathSource source = (Sources.ResolvedPathSource) Sources.resolvedSource(path, location); | |
| assertNull(source.getPath()); | |
| - assertEquals(path.toString(), source.getLocation()); | |
| - assertEquals(modelId, source.getModelId()); | |
| + assertEquals(location, source.getLocation()); | |
| assertNull(source.resolve("subdir")); | |
| ModelSource.ModelLocator locator = mock(ModelSource.ModelLocator.class); | |
| @@ -144,6 +140,6 @@ void testStreamReading() throws IOException { | |
| void testNullHandling() { | |
| assertThrows(NullPointerException.class, () -> Sources.fromPath(null)); | |
| assertThrows(NullPointerException.class, () -> Sources.buildSource(null)); | |
| - assertThrows(NullPointerException.class, () -> Sources.resolvedSource(null, "modelId")); | |
| + assertThrows(NullPointerException.class, () -> Sources.resolvedSource(null, "location")); | |
| } | |
| } | |
| diff --git a/api/maven-api-di/pom.xml b/api/maven-api-di/pom.xml | |
| index d2341a7a42..c2cc62e36f 100644 | |
| --- a/api/maven-api-di/pom.xml | |
| +++ b/api/maven-api-di/pom.xml | |
| @@ -23,7 +23,7 @@ | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-api</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-api-di</artifactId> | |
| diff --git a/api/maven-api-metadata/pom.xml b/api/maven-api-metadata/pom.xml | |
| index 311aad02c4..174816e59e 100644 | |
| --- a/api/maven-api-metadata/pom.xml | |
| +++ b/api/maven-api-metadata/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-api</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-api-metadata</artifactId> | |
| diff --git a/api/maven-api-model/pom.xml b/api/maven-api-model/pom.xml | |
| index 8294a3e887..37e0555cbe 100644 | |
| --- a/api/maven-api-model/pom.xml | |
| +++ b/api/maven-api-model/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-api</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-api-model</artifactId> | |
| @@ -48,7 +48,7 @@ under the License. | |
| <groupId>org.codehaus.modello</groupId> | |
| <artifactId>modello-maven-plugin</artifactId> | |
| <configuration> | |
| - <version>4.2.0</version> | |
| + <version>4.1.0</version> | |
| <velocityBasedir>${project.basedir}/../../src/mdo</velocityBasedir> | |
| <models> | |
| <model>src/main/mdo/maven.mdo</model> | |
| @@ -59,8 +59,6 @@ under the License. | |
| <params> | |
| <param>packageModelV4=org.apache.maven.api.model</param> | |
| <param>isMavenModel=true</param> | |
| - <param>locationTracking=true</param> | |
| - <param>generateLocationClasses=true</param> | |
| </params> | |
| </configuration> | |
| <executions> | |
| diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java | |
| new file mode 100644 | |
| index 0000000000..cde5c51b23 | |
| --- /dev/null | |
| +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java | |
| @@ -0,0 +1,210 @@ | |
| +/* | |
| + * Licensed to the Apache Software Foundation (ASF) under one | |
| + * or more contributor license agreements. See the NOTICE file | |
| + * distributed with this work for additional information | |
| + * regarding copyright ownership. The ASF licenses this file | |
| + * to you under the Apache License, Version 2.0 (the | |
| + * "License"); you may not use this file except in compliance | |
| + * with the License. You may obtain a copy of the License at | |
| + * | |
| + * http://www.apache.org/licenses/LICENSE-2.0 | |
| + * | |
| + * Unless required by applicable law or agreed to in writing, | |
| + * software distributed under the License is distributed on an | |
| + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| + * KIND, either express or implied. See the License for the | |
| + * specific language governing permissions and limitations | |
| + * under the License. | |
| + */ | |
| +package org.apache.maven.api.model; | |
| + | |
| +import java.io.Serializable; | |
| +import java.util.Collection; | |
| +import java.util.Collections; | |
| +import java.util.LinkedHashMap; | |
| +import java.util.Map; | |
| +import java.util.Objects; | |
| + | |
| +/** | |
| + * Represents the location of an element within a model source file. | |
| + * <p> | |
| + * This class tracks the line and column numbers of elements in source files like POM files. | |
| + * It's used for error reporting and debugging to help identify where specific model elements | |
| + * are defined in the source files. | |
| + * | |
| + * @since 4.0.0 | |
| + */ | |
| +public class InputLocation implements Serializable, InputLocationTracker { | |
| + private final int lineNumber; | |
| + private final int columnNumber; | |
| + private final InputSource source; | |
| + private final Map<Object, InputLocation> locations; | |
| + private final InputLocation importedFrom; | |
| + | |
| + public InputLocation(InputSource source) { | |
| + this.lineNumber = -1; | |
| + this.columnNumber = -1; | |
| + this.source = source; | |
| + this.locations = Collections.singletonMap(0, this); | |
| + this.importedFrom = null; | |
| + } | |
| + | |
| + public InputLocation(int lineNumber, int columnNumber) { | |
| + this(lineNumber, columnNumber, null, null); | |
| + } | |
| + | |
| + public InputLocation(int lineNumber, int columnNumber, InputSource source) { | |
| + this(lineNumber, columnNumber, source, null); | |
| + } | |
| + | |
| + public InputLocation(int lineNumber, int columnNumber, InputSource source, Object selfLocationKey) { | |
| + this.lineNumber = lineNumber; | |
| + this.columnNumber = columnNumber; | |
| + this.source = source; | |
| + this.locations = | |
| + selfLocationKey != null ? Collections.singletonMap(selfLocationKey, this) : Collections.emptyMap(); | |
| + this.importedFrom = null; | |
| + } | |
| + | |
| + public InputLocation(int lineNumber, int columnNumber, InputSource source, Map<Object, InputLocation> locations) { | |
| + this.lineNumber = lineNumber; | |
| + this.columnNumber = columnNumber; | |
| + this.source = source; | |
| + this.locations = ImmutableCollections.copy(locations); | |
| + this.importedFrom = null; | |
| + } | |
| + | |
| + public InputLocation(InputLocation original) { | |
| + this.lineNumber = original.lineNumber; | |
| + this.columnNumber = original.columnNumber; | |
| + this.source = original.source; | |
| + this.locations = original.locations; | |
| + this.importedFrom = original.importedFrom; | |
| + } | |
| + | |
| + public int getLineNumber() { | |
| + return lineNumber; | |
| + } | |
| + | |
| + public int getColumnNumber() { | |
| + return columnNumber; | |
| + } | |
| + | |
| + public InputSource getSource() { | |
| + return source; | |
| + } | |
| + | |
| + @Override | |
| + public InputLocation getLocation(Object key) { | |
| + Objects.requireNonNull(key, "key"); | |
| + return locations != null ? locations.get(key) : null; | |
| + } | |
| + | |
| + public Map<Object, InputLocation> getLocations() { | |
| + return locations; | |
| + } | |
| + | |
| + /** | |
| + * Gets the parent InputLocation where this InputLocation may have been imported from. | |
| + * Can return {@code null}. | |
| + * | |
| + * @return InputLocation | |
| + * @since 4.0.0 | |
| + */ | |
| + @Override | |
| + public InputLocation getImportedFrom() { | |
| + return importedFrom; | |
| + } | |
| + | |
| + /** | |
| + * Merges the {@code source} location into the {@code target} location. | |
| + * | |
| + * @param target the target location | |
| + * @param source the source location | |
| + * @param sourceDominant the boolean indicating of {@code source} is dominant compared to {@code target} | |
| + * @return the merged location | |
| + */ | |
| + public static InputLocation merge(InputLocation target, InputLocation source, boolean sourceDominant) { | |
| + if (source == null) { | |
| + return target; | |
| + } else if (target == null) { | |
| + return source; | |
| + } | |
| + | |
| + Map<Object, InputLocation> locations; | |
| + Map<Object, InputLocation> sourceLocations = source.locations; | |
| + Map<Object, InputLocation> targetLocations = target.locations; | |
| + if (sourceLocations == null) { | |
| + locations = targetLocations; | |
| + } else if (targetLocations == null) { | |
| + locations = sourceLocations; | |
| + } else { | |
| + locations = new LinkedHashMap<>(); | |
| + locations.putAll(sourceDominant ? targetLocations : sourceLocations); | |
| + locations.putAll(sourceDominant ? sourceLocations : targetLocations); | |
| + } | |
| + | |
| + return new InputLocation(-1, -1, InputSource.merge(source.getSource(), target.getSource()), locations); | |
| + } // -- InputLocation merge( InputLocation, InputLocation, boolean ) | |
| + | |
| + /** | |
| + * Merges the {@code source} location into the {@code target} location. | |
| + * This method is used when the locations refer to lists and also merges the indices. | |
| + * | |
| + * @param target the target location | |
| + * @param source the source location | |
| + * @param indices the list of integers for the indices | |
| + * @return the merged location | |
| + */ | |
| + public static InputLocation merge(InputLocation target, InputLocation source, Collection<Integer> indices) { | |
| + if (source == null) { | |
| + return target; | |
| + } else if (target == null) { | |
| + return source; | |
| + } | |
| + | |
| + Map<Object, InputLocation> locations; | |
| + Map<Object, InputLocation> sourceLocations = source.locations; | |
| + Map<Object, InputLocation> targetLocations = target.locations; | |
| + if (sourceLocations == null) { | |
| + locations = targetLocations; | |
| + } else if (targetLocations == null) { | |
| + locations = sourceLocations; | |
| + } else { | |
| + locations = new LinkedHashMap<>(); | |
| + for (int index : indices) { | |
| + InputLocation location; | |
| + if (index < 0) { | |
| + location = sourceLocations.get(~index); | |
| + } else { | |
| + location = targetLocations.get(index); | |
| + } | |
| + locations.put(locations.size(), location); | |
| + } | |
| + } | |
| + | |
| + return new InputLocation(-1, -1, InputSource.merge(source.getSource(), target.getSource()), locations); | |
| + } // -- InputLocation merge( InputLocation, InputLocation, java.util.Collection ) | |
| + | |
| + /** | |
| + * Class StringFormatter. | |
| + * | |
| + * @version $Revision$ $Date$ | |
| + */ | |
| + public interface StringFormatter { | |
| + | |
| + // -----------/ | |
| + // - Methods -/ | |
| + // -----------/ | |
| + | |
| + /** | |
| + * Method toString. | |
| + */ | |
| + String toString(InputLocation location); | |
| + } | |
| + | |
| + @Override | |
| + public String toString() { | |
| + return String.format("%s @ %d:%d", source != null ? source.getLocation() : "n/a", lineNumber, columnNumber); | |
| + } | |
| +} | |
| diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java | |
| new file mode 100644 | |
| index 0000000000..65d43007d0 | |
| --- /dev/null | |
| +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java | |
| @@ -0,0 +1,48 @@ | |
| +/* | |
| + * Licensed to the Apache Software Foundation (ASF) under one | |
| + * or more contributor license agreements. See the NOTICE file | |
| + * distributed with this work for additional information | |
| + * regarding copyright ownership. The ASF licenses this file | |
| + * to you under the Apache License, Version 2.0 (the | |
| + * "License"); you may not use this file except in compliance | |
| + * with the License. You may obtain a copy of the License at | |
| + * | |
| + * http://www.apache.org/licenses/LICENSE-2.0 | |
| + * | |
| + * Unless required by applicable law or agreed to in writing, | |
| + * software distributed under the License is distributed on an | |
| + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| + * KIND, either express or implied. See the License for the | |
| + * specific language governing permissions and limitations | |
| + * under the License. | |
| + */ | |
| +package org.apache.maven.api.model; | |
| + | |
| +/** | |
| + * Tracks input source locations for model fields. | |
| + * <p> | |
| + * Implementations provide a mapping from keys (typically field names or indices) to | |
| + * {@link InputLocation} instances to support precise error reporting and diagnostics. | |
| + * Keys must be non-null. | |
| + * | |
| + * @since 4.0.0 | |
| + */ | |
| +public interface InputLocationTracker { | |
| + /** | |
| + * Gets the location of the specified field in the input source. | |
| + * | |
| + * @param field the key of the field, must not be {@code null} | |
| + * @return the location of the field in the input source or {@code null} if unknown | |
| + * @throws NullPointerException if {@code field} is {@code null} | |
| + */ | |
| + InputLocation getLocation(Object field); | |
| + | |
| + /** | |
| + * Gets the parent InputLocation where this InputLocation may have been imported from. | |
| + * Can return {@code null}. | |
| + * | |
| + * @return InputLocation | |
| + * @since 4.0.0 | |
| + */ | |
| + InputLocation getImportedFrom(); | |
| +} | |
| diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java | |
| new file mode 100644 | |
| index 0000000000..f4d5e7fc67 | |
| --- /dev/null | |
| +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java | |
| @@ -0,0 +1,125 @@ | |
| +/* | |
| + * Licensed to the Apache Software Foundation (ASF) under one | |
| + * or more contributor license agreements. See the NOTICE file | |
| + * distributed with this work for additional information | |
| + * regarding copyright ownership. The ASF licenses this file | |
| + * to you under the Apache License, Version 2.0 (the | |
| + * "License"); you may not use this file except in compliance | |
| + * with the License. You may obtain a copy of the License at | |
| + * | |
| + * http://www.apache.org/licenses/LICENSE-2.0 | |
| + * | |
| + * Unless required by applicable law or agreed to in writing, | |
| + * software distributed under the License is distributed on an | |
| + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| + * KIND, either express or implied. See the License for the | |
| + * specific language governing permissions and limitations | |
| + * under the License. | |
| + */ | |
| +package org.apache.maven.api.model; | |
| + | |
| +import java.io.Serializable; | |
| +import java.util.Collection; | |
| +import java.util.List; | |
| +import java.util.Objects; | |
| +import java.util.stream.Collectors; | |
| +import java.util.stream.Stream; | |
| + | |
| +/** | |
| + * Represents the source of a model input, such as a POM file. | |
| + * <p> | |
| + * This class tracks the origin of model elements, including their location in source files | |
| + * and relationships between imported models. It's used for error reporting and debugging | |
| + * to help identify where specific model elements came from. | |
| + * | |
| + * @since 4.0.0 | |
| + */ | |
| +public class InputSource implements Serializable { | |
| + | |
| + private final String modelId; | |
| + private final String location; | |
| + private final List<InputSource> inputs; | |
| + private final InputLocation importedFrom; | |
| + | |
| + public InputSource(String modelId, String location) { | |
| + this(modelId, location, null); | |
| + } | |
| + | |
| + public InputSource(String modelId, String location, InputLocation importedFrom) { | |
| + this.modelId = modelId; | |
| + this.location = location; | |
| + this.inputs = null; | |
| + this.importedFrom = importedFrom; | |
| + } | |
| + | |
| + public InputSource(Collection<InputSource> inputs) { | |
| + this.modelId = null; | |
| + this.location = null; | |
| + this.inputs = ImmutableCollections.copy(inputs); | |
| + this.importedFrom = null; | |
| + } | |
| + | |
| + /** | |
| + * Get the path/URL of the POM or {@code null} if unknown. | |
| + * | |
| + * @return the location | |
| + */ | |
| + public String getLocation() { | |
| + return this.location; | |
| + } | |
| + | |
| + /** | |
| + * Get the identifier of the POM in the format {@code <groupId>:<artifactId>:<version>}. | |
| + * | |
| + * @return the model id | |
| + */ | |
| + public String getModelId() { | |
| + return this.modelId; | |
| + } | |
| + | |
| + /** | |
| + * Gets the parent InputLocation where this InputLocation may have been imported from. | |
| + * Can return {@code null}. | |
| + * | |
| + * @return InputLocation | |
| + * @since 4.0.0 | |
| + */ | |
| + public InputLocation getImportedFrom() { | |
| + return importedFrom; | |
| + } | |
| + | |
| + @Override | |
| + public boolean equals(Object o) { | |
| + if (this == o) { | |
| + return true; | |
| + } | |
| + if (o == null || getClass() != o.getClass()) { | |
| + return false; | |
| + } | |
| + InputSource that = (InputSource) o; | |
| + return Objects.equals(modelId, that.modelId) | |
| + && Objects.equals(location, that.location) | |
| + && Objects.equals(inputs, that.inputs); | |
| + } | |
| + | |
| + @Override | |
| + public int hashCode() { | |
| + return Objects.hash(modelId, location, inputs); | |
| + } | |
| + | |
| + Stream<InputSource> sources() { | |
| + return inputs != null ? inputs.stream() : Stream.of(this); | |
| + } | |
| + | |
| + @Override | |
| + public String toString() { | |
| + if (inputs != null) { | |
| + return inputs.stream().map(InputSource::toString).collect(Collectors.joining(", ", "merged[", "]")); | |
| + } | |
| + return getModelId() + " " + getLocation(); | |
| + } | |
| + | |
| + public static InputSource merge(InputSource src1, InputSource src2) { | |
| + return new InputSource(Stream.concat(src1.sources(), src2.sources()).collect(Collectors.toSet())); | |
| + } | |
| +} | |
| diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/ModelObjectProcessor.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/ModelObjectProcessor.java | |
| deleted file mode 100644 | |
| index f1030709c0..0000000000 | |
| --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/ModelObjectProcessor.java | |
| +++ /dev/null | |
| @@ -1,114 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.api.model; | |
| - | |
| -import java.util.ServiceLoader; | |
| -import java.util.concurrent.atomic.AtomicReference; | |
| - | |
| -/** | |
| - * A pluggable service for processing model objects during model building. | |
| - * | |
| - * <p>This service allows implementations to:</p> | |
| - * <ul> | |
| - * <li>Pool identical objects to reduce memory footprint</li> | |
| - * <li>Intern objects for faster equality comparisons</li> | |
| - * <li>Apply custom optimization strategies</li> | |
| - * <li>Transform or modify objects during building</li> | |
| - * </ul> | |
| - * | |
| - * <p>Implementations are discovered via the Java ServiceLoader mechanism and should | |
| - * be registered in {@code META-INF/services/org.apache.maven.api.model.ModelObjectProcessor}.</p> | |
| - * | |
| - * <p>The service is called during model building for all model objects, allowing | |
| - * implementations to decide which objects to process and how to optimize them.</p> | |
| - * | |
| - * @since 4.0.0 | |
| - */ | |
| -public interface ModelObjectProcessor { | |
| - | |
| - /** | |
| - * Process a model object, potentially returning a pooled or optimized version. | |
| - * | |
| - * <p>This method is called during model building for various model objects. | |
| - * Implementations can:</p> | |
| - * <ul> | |
| - * <li>Return the same object if no processing is desired</li> | |
| - * <li>Return a pooled equivalent object to reduce memory usage</li> | |
| - * <li>Return a modified or optimized version of the object</li> | |
| - * </ul> | |
| - * | |
| - * <p>The implementation must ensure that the returned object is functionally | |
| - * equivalent to the input object from the perspective of the Maven model.</p> | |
| - * | |
| - * @param <T> the type of the model object | |
| - * @param object the model object to process | |
| - * @return the processed object (may be the same instance, a pooled instance, or a modified instance) | |
| - * @throws IllegalArgumentException if the object cannot be processed | |
| - */ | |
| - <T> T process(T object); | |
| - | |
| - /** | |
| - * Process a model object using the first available processor implementation. | |
| - * | |
| - * <p>This method discovers processor implementations via ServiceLoader and | |
| - * uses the first one found. If no implementations are available, the object | |
| - * is returned unchanged. The processor is cached for performance.</p> | |
| - * | |
| - * @param <T> the type of the model object | |
| - * @param object the model object to process | |
| - * @return the processed object | |
| - */ | |
| - static <T> T processObject(T object) { | |
| - class ProcessorHolder { | |
| - /** | |
| - * Cached processor instance for performance. | |
| - */ | |
| - private static final AtomicReference<ModelObjectProcessor> CACHED_PROCESSOR = new AtomicReference<>(); | |
| - } | |
| - | |
| - ModelObjectProcessor processor = ProcessorHolder.CACHED_PROCESSOR.get(); | |
| - if (processor == null) { | |
| - processor = loadProcessor(); | |
| - ProcessorHolder.CACHED_PROCESSOR.compareAndSet(null, processor); | |
| - processor = ProcessorHolder.CACHED_PROCESSOR.get(); | |
| - } | |
| - return processor.process(object); | |
| - } | |
| - | |
| - /** | |
| - * Load the first available processor implementation. | |
| - */ | |
| - private static ModelObjectProcessor loadProcessor() { | |
| - /* | |
| - * No-op processor that returns objects unchanged. | |
| - */ | |
| - class NoOpProcessor implements ModelObjectProcessor { | |
| - @Override | |
| - public <T> T process(T object) { | |
| - return object; | |
| - } | |
| - } | |
| - | |
| - ServiceLoader<ModelObjectProcessor> loader = ServiceLoader.load(ModelObjectProcessor.class); | |
| - for (ModelObjectProcessor processor : loader) { | |
| - return processor; | |
| - } | |
| - return new NoOpProcessor(); | |
| - } | |
| -} | |
| diff --git a/api/maven-api-model/src/main/mdo/maven.mdo b/api/maven-api-model/src/main/mdo/maven.mdo | |
| index 8863ef0164..48df570aec 100644 | |
| --- a/api/maven-api-model/src/main/mdo/maven.mdo | |
| +++ b/api/maven-api-model/src/main/mdo/maven.mdo | |
| @@ -111,20 +111,6 @@ | |
| </association> | |
| </field> | |
| - <!-- ====================================================================== --> | |
| - <!-- Mixins --> | |
| - <!-- ====================================================================== --> | |
| - | |
| - <field xdoc.separator="blank"> | |
| - <name>mixins</name> | |
| - <version>4.2.0+</version> | |
| - <description>Mixins...</description> | |
| - <association> | |
| - <type>Mixin</type> | |
| - <multiplicity>*</multiplicity> | |
| - </association> | |
| - </field> | |
| - | |
| <!-- ====================================================================== --> | |
| <!-- groupId/artifactId/Version/Packaging --> | |
| <!-- ====================================================================== --> | |
| @@ -540,7 +526,7 @@ | |
| <fields> | |
| <field xdoc.separator="blank"> | |
| <name>modules</name> | |
| - <version>4.0.0/4.2.0</version> | |
| + <version>4.0.0/4.1.0</version> | |
| <description> | |
| @deprecated Use {@link #subprojects} instead. | |
| </description> | |
| @@ -554,7 +540,7 @@ | |
| </field> | |
| <field xdoc.separator="blank"> | |
| <name>subprojects</name> | |
| - <version>4.1.0+</version> | |
| + <version>4.1.0</version> | |
| <description>The subprojects (formerly called modules) to build as a part of this | |
| project. Each subproject listed is a relative path to the directory containing the subproject. | |
| To be consistent with the way default URLs are calculated from parent, it is recommended | |
| @@ -1850,23 +1836,6 @@ | |
| </codeSegments> | |
| </class> | |
| - <class> | |
| - <name>Mixin</name> | |
| - <version>4.1.0+</version> | |
| - <superClass>Parent</superClass> | |
| - <fields> | |
| - <field> | |
| - <name>classifier</name> | |
| - <version>4.1.0+</version> | |
| - <type>String</type> | |
| - </field> | |
| - <field> | |
| - <name>extension</name> | |
| - <version>4.1.0+</version> | |
| - <type>String</type> | |
| - </field> | |
| - </fields> | |
| - </class> | |
| <class> | |
| <name>Scm</name> | |
| <version>4.0.0+</version> | |
| diff --git a/api/maven-api-plugin/pom.xml b/api/maven-api-plugin/pom.xml | |
| index 2e9c1706ed..ecc36001df 100644 | |
| --- a/api/maven-api-plugin/pom.xml | |
| +++ b/api/maven-api-plugin/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-api</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-api-plugin</artifactId> | |
| diff --git a/api/maven-api-settings/pom.xml b/api/maven-api-settings/pom.xml | |
| index a73c2ce1de..426a03af58 100644 | |
| --- a/api/maven-api-settings/pom.xml | |
| +++ b/api/maven-api-settings/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-api</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-api-settings</artifactId> | |
| diff --git a/api/maven-api-spi/pom.xml b/api/maven-api-spi/pom.xml | |
| index 19c06b04a2..9e11c42fe5 100644 | |
| --- a/api/maven-api-spi/pom.xml | |
| +++ b/api/maven-api-spi/pom.xml | |
| @@ -23,7 +23,7 @@ | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-api</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-api-spi</artifactId> | |
| diff --git a/api/maven-api-toolchain/pom.xml b/api/maven-api-toolchain/pom.xml | |
| index 64d53566d3..108275549d 100644 | |
| --- a/api/maven-api-toolchain/pom.xml | |
| +++ b/api/maven-api-toolchain/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-api</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-api-toolchain</artifactId> | |
| diff --git a/api/maven-api-xml/pom.xml b/api/maven-api-xml/pom.xml | |
| index 4842b6541f..5ce4808d44 100644 | |
| --- a/api/maven-api-xml/pom.xml | |
| +++ b/api/maven-api-xml/pom.xml | |
| @@ -23,7 +23,7 @@ | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-api</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-api-xml</artifactId> | |
| diff --git a/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/ImmutableCollections.java b/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/ImmutableCollections.java | |
| index 80abc22030..ca1c4707e8 100644 | |
| --- a/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/ImmutableCollections.java | |
| +++ b/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/ImmutableCollections.java | |
| @@ -19,31 +19,45 @@ | |
| package org.apache.maven.api.xml; | |
| import java.io.Serializable; | |
| +import java.util.AbstractList; | |
| import java.util.AbstractMap; | |
| import java.util.AbstractSet; | |
| import java.util.Collection; | |
| +import java.util.Comparator; | |
| import java.util.Iterator; | |
| import java.util.List; | |
| +import java.util.ListIterator; | |
| import java.util.Map; | |
| import java.util.NoSuchElementException; | |
| +import java.util.Properties; | |
| +import java.util.RandomAccess; | |
| import java.util.Set; | |
| import java.util.function.BiFunction; | |
| import java.util.function.Function; | |
| import java.util.function.Predicate; | |
| +import java.util.function.UnaryOperator; | |
| -/** | |
| - * This should be removed when https://bugs.openjdk.org/browse/JDK-8323729 | |
| - * is released in our minimum JDK. | |
| - */ | |
| class ImmutableCollections { | |
| - private static final Map<?, ?> EMPTY_MAP = new AbstractImmutableMap<>() { | |
| + private static final List<?> EMPTY_LIST = new AbstractImmutableList<Object>() { | |
| + @Override | |
| + public Object get(int index) { | |
| + throw new IndexOutOfBoundsException(); | |
| + } | |
| + | |
| + @Override | |
| + public int size() { | |
| + return 0; | |
| + } | |
| + }; | |
| + | |
| + private static final Map<?, ?> EMPTY_MAP = new AbstractImmutableMap<Object, Object>() { | |
| @Override | |
| public Set<Entry<Object, Object>> entrySet() { | |
| - return new AbstractImmutableSet<>() { | |
| + return new AbstractImmutableSet<Entry<Object, Object>>() { | |
| @Override | |
| public Iterator<Entry<Object, Object>> iterator() { | |
| - return new Iterator<>() { | |
| + return new Iterator<Entry<Object, Object>>() { | |
| @Override | |
| public boolean hasNext() { | |
| return false; | |
| @@ -64,8 +78,31 @@ public int size() { | |
| } | |
| }; | |
| - static <E1, E2 extends E1> List<E1> copy(Collection<E2> collection) { | |
| - return collection == null ? List.of() : List.copyOf(collection); | |
| + static <E> List<E> copy(Collection<E> collection) { | |
| + if (collection == null) { | |
| + return emptyList(); | |
| + } else if (collection instanceof AbstractImmutableList) { | |
| + return (List<E>) collection; | |
| + } else { | |
| + return switch (collection.size()) { | |
| + case 0 -> emptyList(); | |
| + case 1 -> singletonList(collection.iterator().next()); | |
| + case 2 -> { | |
| + Iterator<E> it = collection.iterator(); | |
| + yield new List2<>(it.next(), it.next()); | |
| + } | |
| + default -> new ListN<>(collection); | |
| + }; | |
| + } | |
| + } | |
| + | |
| + @SuppressWarnings("unchecked") | |
| + static <E> List<E> emptyList() { | |
| + return (List<E>) EMPTY_LIST; | |
| + } | |
| + | |
| + static <E> List<E> singletonList(E element) { | |
| + return new List1<>(element); | |
| } | |
| static <K, V> Map<K, V> copy(Map<K, V> map) { | |
| @@ -74,15 +111,14 @@ static <K, V> Map<K, V> copy(Map<K, V> map) { | |
| } else if (map instanceof AbstractImmutableMap) { | |
| return map; | |
| } else { | |
| - switch (map.size()) { | |
| - case 0: | |
| - return emptyMap(); | |
| - case 1: | |
| + return switch (map.size()) { | |
| + case 0 -> emptyMap(); | |
| + case 1 -> { | |
| Map.Entry<K, V> entry = map.entrySet().iterator().next(); | |
| - return singletonMap(entry.getKey(), entry.getValue()); | |
| - default: | |
| - return new MapN<>(map); | |
| - } | |
| + yield singletonMap(entry.getKey(), entry.getValue()); | |
| + } | |
| + default -> new MapN<>(map); | |
| + }; | |
| } | |
| } | |
| @@ -95,6 +131,315 @@ static <K, V> Map<K, V> singletonMap(K key, V value) { | |
| return new Map1<>(key, value); | |
| } | |
| + static Properties copy(Properties properties) { | |
| + if (properties instanceof ROProperties) { | |
| + return properties; | |
| + } | |
| + return new ROProperties(properties); | |
| + } | |
| + | |
| + private static class List1<E> extends AbstractImmutableList<E> { | |
| + private final E element; | |
| + | |
| + private List1(E element) { | |
| + this.element = element; | |
| + } | |
| + | |
| + @Override | |
| + public E get(int index) { | |
| + if (index == 0) { | |
| + return element; | |
| + } | |
| + throw outOfBounds(index); | |
| + } | |
| + | |
| + @Override | |
| + public int size() { | |
| + return 1; | |
| + } | |
| + } | |
| + | |
| + private static class List2<E> extends AbstractImmutableList<E> { | |
| + private final E element1; | |
| + private final E element2; | |
| + | |
| + private List2(E element1, E element2) { | |
| + this.element1 = element1; | |
| + this.element2 = element2; | |
| + } | |
| + | |
| + @Override | |
| + public E get(int index) { | |
| + if (index == 0) { | |
| + return element1; | |
| + } else if (index == 1) { | |
| + return element2; | |
| + } | |
| + throw outOfBounds(index); | |
| + } | |
| + | |
| + @Override | |
| + public int size() { | |
| + return 2; | |
| + } | |
| + } | |
| + | |
| + private static class ListN<E> extends AbstractImmutableList<E> { | |
| + private final Object[] elements; | |
| + | |
| + private ListN(Collection<E> elements) { | |
| + this.elements = elements.toArray(); | |
| + } | |
| + | |
| + @SuppressWarnings("unchecked") | |
| + @Override | |
| + public E get(int index) { | |
| + return (E) elements[index]; | |
| + } | |
| + | |
| + @Override | |
| + public int size() { | |
| + return elements.length; | |
| + } | |
| + } | |
| + | |
| + private abstract static class AbstractImmutableList<E> extends AbstractList<E> | |
| + implements RandomAccess, Serializable { | |
| + @Override | |
| + public boolean add(E e) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public boolean remove(Object o) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public boolean addAll(Collection<? extends E> c) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public boolean removeAll(Collection<?> c) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public boolean retainAll(Collection<?> c) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public void clear() { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public boolean removeIf(Predicate<? super E> filter) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public void replaceAll(UnaryOperator<E> operator) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public void sort(Comparator<? super E> c) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public Iterator<E> iterator() { | |
| + return new Itr(0); | |
| + } | |
| + | |
| + @Override | |
| + public ListIterator<E> listIterator() { | |
| + return new Itr(0); | |
| + } | |
| + | |
| + @Override | |
| + public ListIterator<E> listIterator(int index) { | |
| + if (index < 0 || index > size()) { | |
| + throw outOfBounds(index); | |
| + } | |
| + return new Itr(index); | |
| + } | |
| + | |
| + @Override | |
| + public List<E> subList(int fromIndex, int toIndex) { | |
| + if (fromIndex < 0) { | |
| + throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); | |
| + } | |
| + if (toIndex > size()) { | |
| + throw new IndexOutOfBoundsException("toIndex = " + toIndex); | |
| + } | |
| + if (fromIndex > toIndex) { | |
| + throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); | |
| + } | |
| + return new SubList(fromIndex, toIndex); | |
| + } | |
| + | |
| + protected IndexOutOfBoundsException outOfBounds(int index) { | |
| + return new IndexOutOfBoundsException("Index: " + index + ", Size: " + size()); | |
| + } | |
| + | |
| + private class SubList extends AbstractImmutableList<E> { | |
| + private final int fromIndex; | |
| + private final int toIndex; | |
| + | |
| + private SubList(int fromIndex, int toIndex) { | |
| + this.fromIndex = fromIndex; | |
| + this.toIndex = toIndex; | |
| + } | |
| + | |
| + @Override | |
| + public E get(int index) { | |
| + if (index < 0 || index > size()) { | |
| + throw outOfBounds(index); | |
| + } | |
| + return AbstractImmutableList.this.get(fromIndex + index); | |
| + } | |
| + | |
| + @Override | |
| + public int size() { | |
| + return toIndex - fromIndex; | |
| + } | |
| + } | |
| + | |
| + private class Itr implements ListIterator<E> { | |
| + int index; | |
| + | |
| + private Itr(int index) { | |
| + this.index = index; | |
| + } | |
| + | |
| + @Override | |
| + public boolean hasNext() { | |
| + return index < size(); | |
| + } | |
| + | |
| + @Override | |
| + public E next() { | |
| + return get(index++); | |
| + } | |
| + | |
| + @Override | |
| + public boolean hasPrevious() { | |
| + return index > 0; | |
| + } | |
| + | |
| + @Override | |
| + public E previous() { | |
| + return get(--index); | |
| + } | |
| + | |
| + @Override | |
| + public int nextIndex() { | |
| + return index; | |
| + } | |
| + | |
| + @Override | |
| + public int previousIndex() { | |
| + return index - 1; | |
| + } | |
| + | |
| + @Override | |
| + public void remove() { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public void set(E e) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public void add(E e) { | |
| + throw uoe(); | |
| + } | |
| + } | |
| + } | |
| + | |
| + private static class ROProperties extends Properties { | |
| + private ROProperties(Properties props) { | |
| + super(); | |
| + if (props != null) { | |
| + // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException | |
| + for (Map.Entry<Object, Object> e : props.entrySet()) { | |
| + super.put(e.getKey(), e.getValue()); | |
| + } | |
| + } | |
| + } | |
| + | |
| + @Override | |
| + public Object put(Object key, Object value) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public Object remove(Object key) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public void putAll(Map<?, ?> t) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public void clear() { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public void replaceAll(BiFunction<? super Object, ? super Object, ?> function) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public Object putIfAbsent(Object key, Object value) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public boolean remove(Object key, Object value) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public boolean replace(Object key, Object oldValue, Object newValue) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public Object replace(Object key, Object value) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public Object computeIfAbsent(Object key, Function<? super Object, ?> mappingFunction) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public Object computeIfPresent(Object key, BiFunction<? super Object, ? super Object, ?> remappingFunction) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public Object compute(Object key, BiFunction<? super Object, ? super Object, ?> remappingFunction) { | |
| + throw uoe(); | |
| + } | |
| + | |
| + @Override | |
| + public Object merge(Object key, Object value, BiFunction<? super Object, ? super Object, ?> remappingFunction) { | |
| + throw uoe(); | |
| + } | |
| + } | |
| + | |
| private static class Map1<K, V> extends AbstractImmutableMap<K, V> { | |
| private final Entry<K, V> entry; | |
| @@ -104,10 +449,10 @@ private Map1(K key, V value) { | |
| @Override | |
| public Set<Entry<K, V>> entrySet() { | |
| - return new AbstractImmutableSet<>() { | |
| + return new AbstractImmutableSet<Entry<K, V>>() { | |
| @Override | |
| public Iterator<Entry<K, V>> iterator() { | |
| - return new Iterator<>() { | |
| + return new Iterator<Entry<K, V>>() { | |
| int index = 0; | |
| @Override | |
| @@ -150,10 +495,10 @@ private MapN(Map<K, V> map) { | |
| @Override | |
| public Set<Entry<K, V>> entrySet() { | |
| - return new AbstractImmutableSet<>() { | |
| + return new AbstractImmutableSet<Entry<K, V>>() { | |
| @Override | |
| public Iterator<Entry<K, V>> iterator() { | |
| - return new Iterator<>() { | |
| + return new Iterator<Entry<K, V>>() { | |
| int index = 0; | |
| @Override | |
| diff --git a/api/pom.xml b/api/pom.xml | |
| index b90c9f605c..ba5c47f3a1 100644 | |
| --- a/api/pom.xml | |
| +++ b/api/pom.xml | |
| @@ -23,7 +23,7 @@ | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-api</artifactId> | |
| diff --git a/compat/maven-artifact/pom.xml b/compat/maven-artifact/pom.xml | |
| index 42d5bf80f5..381253f437 100644 | |
| --- a/compat/maven-artifact/pom.xml | |
| +++ b/compat/maven-artifact/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-artifact</artifactId> | |
| diff --git a/compat/maven-artifact/src/main/java/org/apache/maven/artifact/DefaultArtifact.java b/compat/maven-artifact/src/main/java/org/apache/maven/artifact/DefaultArtifact.java | |
| index 2dc3cf5ac0..af1203095b 100644 | |
| --- a/compat/maven-artifact/src/main/java/org/apache/maven/artifact/DefaultArtifact.java | |
| +++ b/compat/maven-artifact/src/main/java/org/apache/maven/artifact/DefaultArtifact.java | |
| @@ -184,7 +184,7 @@ private void validateIdentity() { | |
| } | |
| public static boolean empty(String value) { | |
| - return value == null || value.isBlank(); | |
| + return (value == null) || (value.trim().length() < 1); | |
| } | |
| @Override | |
| diff --git a/compat/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java b/compat/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java | |
| index df3c034528..e92e0bb450 100644 | |
| --- a/compat/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java | |
| +++ b/compat/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java | |
| @@ -607,7 +607,7 @@ public int compareTo(Item item) { | |
| public String toString() { | |
| StringBuilder buffer = new StringBuilder(); | |
| for (Item item : this) { | |
| - if (!buffer.isEmpty()) { | |
| + if (buffer.length() > 0) { | |
| buffer.append((item instanceof ListItem) ? '-' : '.'); | |
| } | |
| buffer.append(item); | |
| diff --git a/compat/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/VersionRange.java b/compat/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/VersionRange.java | |
| index 152e8365c6..1869dcc584 100644 | |
| --- a/compat/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/VersionRange.java | |
| +++ b/compat/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/VersionRange.java | |
| @@ -255,7 +255,7 @@ public VersionRange restrict(VersionRange restriction) { | |
| } | |
| ArtifactVersion version = null; | |
| - if (!restrictions.isEmpty()) { | |
| + if (restrictions.size() > 0) { | |
| for (Restriction r : restrictions) { | |
| if (recommendedVersion != null && r.containsVersion(recommendedVersion)) { | |
| // if we find the original, use that | |
| @@ -398,7 +398,7 @@ public ArtifactVersion getSelectedVersion(Artifact artifact) throws OverConstrai | |
| if (recommendedVersion != null) { | |
| version = recommendedVersion; | |
| } else { | |
| - if (restrictions.isEmpty()) { | |
| + if (restrictions.size() == 0) { | |
| throw new OverConstrainedVersionException("The artifact has no valid ranges", artifact); | |
| } | |
| @@ -412,7 +412,7 @@ public boolean isSelectedVersionKnown(Artifact artifact) throws OverConstrainedV | |
| if (recommendedVersion != null) { | |
| value = true; | |
| } else { | |
| - if (restrictions.isEmpty()) { | |
| + if (restrictions.size() == 0) { | |
| throw new OverConstrainedVersionException("The artifact has no valid ranges", artifact); | |
| } | |
| } | |
| diff --git a/compat/maven-artifact/src/test/java/org/apache/maven/artifact/versioning/DefaultArtifactVersionTest.java b/compat/maven-artifact/src/test/java/org/apache/maven/artifact/versioning/DefaultArtifactVersionTest.java | |
| index c1530cbe20..370b0f0c5c 100644 | |
| --- a/compat/maven-artifact/src/test/java/org/apache/maven/artifact/versioning/DefaultArtifactVersionTest.java | |
| +++ b/compat/maven-artifact/src/test/java/org/apache/maven/artifact/versioning/DefaultArtifactVersionTest.java | |
| @@ -176,7 +176,7 @@ void testSnapshotVsReleases() { | |
| void testHashCode() { | |
| ArtifactVersion v1 = newArtifactVersion("1"); | |
| ArtifactVersion v2 = newArtifactVersion("1.0"); | |
| - assertTrue(v1.equals(v2), "Expected " + v1 + " to equal " + v2); | |
| + assertTrue(v1.equals(v2)); | |
| assertEquals(v1.hashCode(), v2.hashCode()); | |
| } | |
| diff --git a/compat/maven-builder-support/pom.xml b/compat/maven-builder-support/pom.xml | |
| index 2f4b6bd61a..2297ad4d72 100644 | |
| --- a/compat/maven-builder-support/pom.xml | |
| +++ b/compat/maven-builder-support/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-builder-support</artifactId> | |
| diff --git a/compat/maven-builder-support/src/main/java/org/apache/maven/building/DefaultProblem.java b/compat/maven-builder-support/src/main/java/org/apache/maven/building/DefaultProblem.java | |
| index 8cfa77d3c7..ad5c72e5a2 100644 | |
| --- a/compat/maven-builder-support/src/main/java/org/apache/maven/building/DefaultProblem.java | |
| +++ b/compat/maven-builder-support/src/main/java/org/apache/maven/building/DefaultProblem.java | |
| @@ -82,21 +82,21 @@ public String getLocation() { | |
| StringBuilder buffer = new StringBuilder(256); | |
| if (!getSource().isEmpty()) { | |
| - if (!buffer.isEmpty()) { | |
| + if (buffer.length() > 0) { | |
| buffer.append(", "); | |
| } | |
| buffer.append(getSource()); | |
| } | |
| if (getLineNumber() > 0) { | |
| - if (!buffer.isEmpty()) { | |
| + if (buffer.length() > 0) { | |
| buffer.append(", "); | |
| } | |
| buffer.append("line ").append(getLineNumber()); | |
| } | |
| if (getColumnNumber() > 0) { | |
| - if (!buffer.isEmpty()) { | |
| + if (buffer.length() > 0) { | |
| buffer.append(", "); | |
| } | |
| buffer.append("column ").append(getColumnNumber()); | |
| diff --git a/compat/maven-builder-support/src/test/java/org/apache/maven/building/ProblemCollectorFactoryTest.java b/compat/maven-builder-support/src/test/java/org/apache/maven/building/ProblemCollectorFactoryTest.java | |
| index 140035bb03..6705992bef 100644 | |
| --- a/compat/maven-builder-support/src/test/java/org/apache/maven/building/ProblemCollectorFactoryTest.java | |
| +++ b/compat/maven-builder-support/src/test/java/org/apache/maven/building/ProblemCollectorFactoryTest.java | |
| @@ -19,7 +19,6 @@ | |
| package org.apache.maven.building; | |
| import java.util.Collections; | |
| -import java.util.List; | |
| import org.junit.jupiter.api.Test; | |
| @@ -39,18 +38,4 @@ void testNewInstance() { | |
| assertEquals(0, collector1.getProblems().size()); | |
| assertEquals(1, collector2.getProblems().size()); | |
| } | |
| - | |
| - @Test | |
| - void testAddProblem() { | |
| - ProblemCollector collector = ProblemCollectorFactory.newInstance(null); | |
| - collector.setSource("pom.xml"); | |
| - collector.add(Problem.Severity.ERROR, "Error message", 10, 5, null); | |
| - collector.add(Problem.Severity.WARNING, "Warning message", 15, 3, null); | |
| - | |
| - List<Problem> problems = collector.getProblems(); | |
| - assertEquals(2, problems.size(), "Should collect both problems"); | |
| - assertEquals(Problem.Severity.ERROR, problems.get(0).getSeverity(), "First problem should be ERROR"); | |
| - assertEquals("Error message", problems.get(0).getMessage(), "First problem should have correct message"); | |
| - assertEquals(Problem.Severity.WARNING, problems.get(1).getSeverity(), "Second problem should be WARNING"); | |
| - } | |
| } | |
| diff --git a/compat/maven-compat/pom.xml b/compat/maven-compat/pom.xml | |
| index e102a5c674..ee2f6cdd5b 100644 | |
| --- a/compat/maven-compat/pom.xml | |
| +++ b/compat/maven-compat/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-compat</artifactId> | |
| @@ -161,7 +161,7 @@ under the License. | |
| <dependency> | |
| <groupId>org.codehaus.plexus</groupId> | |
| <artifactId>plexus-component-annotations</artifactId> | |
| - <version>2.1.0</version> | |
| + <version>2.2.0</version> | |
| </dependency> | |
| <dependency> | |
| <groupId>org.eclipse.sisu</groupId> | |
| @@ -174,7 +174,11 @@ under the License. | |
| <artifactId>junit-jupiter-api</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| - | |
| + <dependency> | |
| + <groupId>org.hamcrest</groupId> | |
| + <artifactId>hamcrest</artifactId> | |
| + <scope>test</scope> | |
| + </dependency> | |
| <dependency> | |
| <groupId>com.google.inject</groupId> | |
| <artifactId>guice</artifactId> | |
| diff --git a/compat/maven-compat/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java b/compat/maven-compat/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java | |
| index 568bc263e8..66d11b5187 100644 | |
| --- a/compat/maven-compat/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java | |
| +++ b/compat/maven-compat/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java | |
| @@ -203,8 +203,8 @@ public ResolutionGroup retrieve(MetadataResolutionRequest request) throws Artifa | |
| if (session.getProjects() != null) { | |
| pomRepositories = session.getProjects().stream() | |
| .filter(p -> artifact.equals(p.getArtifact())) | |
| - .findFirst() | |
| .map(MavenProject::getRemoteArtifactRepositories) | |
| + .findFirst() | |
| .orElseGet(() -> getRepositoriesFromModel(repositorySession, model)); | |
| } else { | |
| pomRepositories = getRepositoriesFromModel(repositorySession, model); | |
| diff --git a/compat/maven-compat/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java b/compat/maven-compat/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java | |
| index c7cea8d13b..c9d941a446 100644 | |
| --- a/compat/maven-compat/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java | |
| +++ b/compat/maven-compat/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java | |
| @@ -264,9 +264,7 @@ private void traverseObjectWithParents(Class<?> cls, Object target) throws Model | |
| private boolean isQualifiedForInterpolation(Class<?> cls) { | |
| return !cls.getPackage().getName().startsWith("java") | |
| - && !cls.getPackage().getName().startsWith("sun.nio.fs") | |
| - // org.apache.maven.api.model.InputLocation can be self-referencing | |
| - && !cls.getName().equals("org.apache.maven.api.model.InputLocation"); | |
| + && !cls.getPackage().getName().startsWith("sun.nio.fs"); | |
| } | |
| private boolean isQualifiedForInterpolation(Field field, Class<?> fieldType) { | |
| diff --git a/compat/maven-compat/src/main/java/org/apache/maven/project/validation/ModelValidationResult.java b/compat/maven-compat/src/main/java/org/apache/maven/project/validation/ModelValidationResult.java | |
| index 693227ebcc..feae2be0ca 100644 | |
| --- a/compat/maven-compat/src/main/java/org/apache/maven/project/validation/ModelValidationResult.java | |
| +++ b/compat/maven-compat/src/main/java/org/apache/maven/project/validation/ModelValidationResult.java | |
| @@ -59,7 +59,7 @@ public String toString() { | |
| } | |
| public String render(String indentation) { | |
| - if (messages.isEmpty()) { | |
| + if (messages.size() == 0) { | |
| return indentation + "There were no validation errors."; | |
| } | |
| diff --git a/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/ClasspathContainer.java b/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/ClasspathContainer.java | |
| index 37c6b9f423..4a0b44fb12 100644 | |
| --- a/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/ClasspathContainer.java | |
| +++ b/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/ClasspathContainer.java | |
| @@ -70,7 +70,7 @@ public List<ArtifactMetadata> getClasspath() { | |
| // ------------------------------------------------------------------------------------------- | |
| public MetadataTreeNode getClasspathAsTree() throws MetadataResolutionException { | |
| - if (classpath == null || classpath.isEmpty()) { | |
| + if (classpath == null || classpath.size() < 1) { | |
| return null; | |
| } | |
| diff --git a/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/DefaultClasspathTransformation.java b/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/DefaultClasspathTransformation.java | |
| index e7bc8f9f96..e0b5fb64e6 100644 | |
| --- a/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/DefaultClasspathTransformation.java | |
| +++ b/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/DefaultClasspathTransformation.java | |
| @@ -104,7 +104,7 @@ protected void visit(MetadataGraphVertex node) { | |
| List<MetadataGraphEdge> exits = graph.getExcidentEdges(node); | |
| - if (exits != null && !exits.isEmpty()) { | |
| + if (exits != null && exits.size() > 0) { | |
| MetadataGraphEdge[] sortedExits = exits.toArray(new MetadataGraphEdge[0]); | |
| Arrays.sort(sortedExits, (e1, e2) -> { | |
| if (e1.getDepth() == e2.getDepth()) { | |
| diff --git a/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/DefaultGraphConflictResolver.java b/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/DefaultGraphConflictResolver.java | |
| index d4d3a1e3a1..35a0e06168 100644 | |
| --- a/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/DefaultGraphConflictResolver.java | |
| +++ b/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/DefaultGraphConflictResolver.java | |
| @@ -144,7 +144,7 @@ private MetadataGraph findLinkedSubgraph(MetadataGraph g) { | |
| } | |
| } | |
| - if (dropList.isEmpty()) { | |
| + if (dropList.size() < 1) { | |
| return g; | |
| } | |
| @@ -167,7 +167,7 @@ private void visit(MetadataGraphVertex from, List<MetadataGraphVertex> visited, | |
| List<MetadataGraphEdge> exitList = graph.getExcidentEdges(from); | |
| // String s = "|---> "+from.getMd().toString()+" - "+(exitList == null ? -1 : exitList.size()) + " exit links"; | |
| - if (exitList != null && !exitList.isEmpty()) { | |
| + if (exitList != null && exitList.size() > 0) { | |
| for (MetadataGraphEdge e : graph.getExcidentEdges(from)) { | |
| visit(e.getTarget(), visited, graph); | |
| } | |
| diff --git a/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/MetadataGraph.java b/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/MetadataGraph.java | |
| index fe785515a1..e6e0024f80 100644 | |
| --- a/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/MetadataGraph.java | |
| +++ b/compat/maven-compat/src/main/java/org/apache/maven/repository/metadata/MetadataGraph.java | |
| @@ -152,7 +152,7 @@ private void processTreeNodes(MetadataGraphVertex parentVertex, MetadataTreeNode | |
| } | |
| // ------------------------------------------------------------------------ | |
| public MetadataGraphVertex findVertex(ArtifactMetadata md) { | |
| - if (md == null || vertices == null || vertices.isEmpty()) { | |
| + if (md == null || vertices == null || vertices.size() < 1) { | |
| return null; | |
| } | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/ProjectDependenciesResolverTest.java b/compat/maven-compat/src/test/java/org/apache/maven/ProjectDependenciesResolverTest.java | |
| index 7f4f445aa2..723ef0111d 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/ProjectDependenciesResolverTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/ProjectDependenciesResolverTest.java | |
| @@ -32,8 +32,9 @@ | |
| import org.junit.jupiter.api.Test; | |
| import static org.codehaus.plexus.testing.PlexusExtension.getBasedir; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.endsWith; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| @Deprecated | |
| class ProjectDependenciesResolverTest extends AbstractCoreMavenComponentTestCase { | |
| @@ -81,6 +82,6 @@ void testSystemScopeDependencyIsPresentInTheCompileClasspathElements() throws Ex | |
| @SuppressWarnings("deprecation") | |
| List<Artifact> artifacts = project.getCompileArtifacts(); | |
| assertEquals(1, artifacts.size()); | |
| - assertTrue(artifacts.get(0).getFile().getName().endsWith("tools.jar")); | |
| + assertThat(artifacts.get(0).getFile().getName(), endsWith("tools.jar")); | |
| } | |
| } | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/artifact/deployer/ArtifactDeployerTest.java b/compat/maven-compat/src/test/java/org/apache/maven/artifact/deployer/ArtifactDeployerTest.java | |
| index 367ec6bcd2..0435e11952 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/artifact/deployer/ArtifactDeployerTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/artifact/deployer/ArtifactDeployerTest.java | |
| @@ -67,7 +67,7 @@ void testArtifactInstallation() throws Exception { | |
| ArtifactRepository remoteRepository = remoteRepository(); | |
| File deployedFile = new File(remoteRepository.getBasedir(), remoteRepository.pathOf(artifact)); | |
| - assertTrue(deployedFile.exists(), "Expected " + deployedFile + ".exists() to return true"); | |
| + assertTrue(deployedFile.exists()); | |
| assertEquals("dummy", new String(Files.readAllBytes(deployedFile.toPath()), StandardCharsets.UTF_8).trim()); | |
| } finally { | |
| sessionScope.exit(); | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/artifact/repository/MavenArtifactRepositoryTest.java b/compat/maven-compat/src/test/java/org/apache/maven/artifact/repository/MavenArtifactRepositoryTest.java | |
| index 2b005e1599..f529ae822b 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/artifact/repository/MavenArtifactRepositoryTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/artifact/repository/MavenArtifactRepositoryTest.java | |
| @@ -47,10 +47,10 @@ void testHashCodeEquals() { | |
| assertTrue(r1.hashCode() == r2.hashCode()); | |
| assertFalse(r1.hashCode() == r3.hashCode()); | |
| - assertTrue(r1.equals(r2), "Expected " + r1 + " to equal " + r2); | |
| - assertTrue(r2.equals(r1), "Expected " + r2 + " to equal " + r1); | |
| + assertTrue(r1.equals(r2)); | |
| + assertTrue(r2.equals(r1)); | |
| - assertFalse(r1.equals(r3), "Expected " + r1 + " to not equal " + r3); | |
| - assertFalse(r3.equals(r1), "Expected " + r3 + " to not equal " + r1); | |
| + assertFalse(r1.equals(r3)); | |
| + assertFalse(r3.equals(r1)); | |
| } | |
| } | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/artifact/resolver/filter/AndArtifactFilterTest.java b/compat/maven-compat/src/test/java/org/apache/maven/artifact/resolver/filter/AndArtifactFilterTest.java | |
| index cfcd65eab4..fe0343c857 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/artifact/resolver/filter/AndArtifactFilterTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/artifact/resolver/filter/AndArtifactFilterTest.java | |
| @@ -42,11 +42,11 @@ void testEquals() { | |
| AndArtifactFilter filter2 = new AndArtifactFilter(Arrays.asList(newSubFilter())); | |
| - assertFalse(filter1.equals(null), "Expected " + filter1 + " to not equal " + null); | |
| - assertTrue(filter1.equals(filter1), "Expected " + filter1 + " to equal " + filter1); | |
| + assertFalse(filter1.equals(null)); | |
| + assertTrue(filter1.equals(filter1)); | |
| assertEquals(filter1.hashCode(), filter1.hashCode()); | |
| - assertFalse(filter1.equals(filter2), "Expected " + filter1 + " to not equal " + filter2); | |
| - assertFalse(filter2.equals(filter1), "Expected " + filter2 + " to not equal " + filter1); | |
| + assertFalse(filter1.equals(filter2)); | |
| + assertFalse(filter2.equals(filter1)); | |
| } | |
| } | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/artifact/resolver/filter/FilterHashEqualsTest.java b/compat/maven-compat/src/test/java/org/apache/maven/artifact/resolver/filter/FilterHashEqualsTest.java | |
| index 3ccb13e85a..53a26db4ea 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/artifact/resolver/filter/FilterHashEqualsTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/artifact/resolver/filter/FilterHashEqualsTest.java | |
| @@ -37,12 +37,12 @@ void testIncludesExcludesArtifactFilter() { | |
| IncludesArtifactFilter f2 = new IncludesArtifactFilter(patterns); | |
| - assertTrue(f1.equals(f2), "Expected " + f1 + " to equal " + f2); | |
| - assertTrue(f2.equals(f1), "Expected " + f2 + " to equal " + f1); | |
| + assertTrue(f1.equals(f2)); | |
| + assertTrue(f2.equals(f1)); | |
| assertTrue(f1.hashCode() == f2.hashCode()); | |
| IncludesArtifactFilter f3 = new IncludesArtifactFilter(Arrays.asList("d", "c", "e")); | |
| - assertTrue(f1.equals(f3), "Expected " + f1 + " to equal " + f3); | |
| + assertTrue(f1.equals(f3)); | |
| assertTrue(f1.hashCode() == f3.hashCode()); | |
| } | |
| } | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/artifact/resolver/filter/OrArtifactFilterTest.java b/compat/maven-compat/src/test/java/org/apache/maven/artifact/resolver/filter/OrArtifactFilterTest.java | |
| index 2ca82a783b..6c8cda6802 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/artifact/resolver/filter/OrArtifactFilterTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/artifact/resolver/filter/OrArtifactFilterTest.java | |
| @@ -43,11 +43,11 @@ void testEquals() { | |
| OrArtifactFilter filter2 = new OrArtifactFilter(Arrays.asList(newSubFilter())); | |
| - assertFalse(filter1.equals(null), "Expected " + filter1 + " to not equal " + null); | |
| - assertTrue(filter1.equals(filter1), "Expected " + filter1 + " to equal " + filter1); | |
| + assertFalse(filter1.equals(null)); | |
| + assertTrue(filter1.equals(filter1)); | |
| assertEquals(filter1.hashCode(), filter1.hashCode()); | |
| - assertFalse(filter1.equals(filter2), "Expected " + filter1 + " to not equal " + filter2); | |
| - assertFalse(filter2.equals(filter1), "Expected " + filter2 + " to not equal " + filter1); | |
| + assertFalse(filter1.equals(filter2)); | |
| + assertFalse(filter2.equals(filter1)); | |
| } | |
| } | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/artifact/testutils/TestFileManager.java b/compat/maven-compat/src/test/java/org/apache/maven/artifact/testutils/TestFileManager.java | |
| index 1e41a1f679..47372855ca 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/artifact/testutils/TestFileManager.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/artifact/testutils/TestFileManager.java | |
| @@ -120,9 +120,9 @@ public void assertFileExistence(File dir, String filename, boolean shouldExist) | |
| File file = new File(dir, filename); | |
| if (shouldExist) { | |
| - assertTrue(file.exists(), "Expected " + file + ".exists() to return true"); | |
| + assertTrue(file.exists()); | |
| } else { | |
| - assertFalse(file.exists(), "Expected " + file + ".exists() to return false"); | |
| + assertFalse(file.exists()); | |
| } | |
| } | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t04/ProjectInheritanceTest.java b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t04/ProjectInheritanceTest.java | |
| index 0cbcfc7bfc..e6ffa7cf23 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t04/ProjectInheritanceTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t04/ProjectInheritanceTest.java | |
| @@ -27,7 +27,6 @@ | |
| import org.junit.jupiter.api.Test; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| import static org.junit.jupiter.api.Assertions.assertTrue; | |
| @@ -69,7 +68,7 @@ void testDependencyManagementOverridesTransitiveDependencyVersion() throws Excep | |
| assertEquals(pom0Basedir, project1.getParent().getBasedir()); | |
| Set set = project1.getArtifacts(); | |
| assertNotNull(set, "No artifacts"); | |
| - assertFalse(set.isEmpty(), "No Artifacts"); | |
| + assertTrue(set.size() > 0, "No Artifacts"); | |
| assertTrue(set.size() == 3, "Set size should be 3, is " + set.size()); | |
| for (Object aSet : set) { | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t05/ProjectInheritanceTest.java b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t05/ProjectInheritanceTest.java | |
| index c97114514e..a0d610d210 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t05/ProjectInheritanceTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t05/ProjectInheritanceTest.java | |
| @@ -27,7 +27,6 @@ | |
| import org.junit.jupiter.api.Test; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| import static org.junit.jupiter.api.Assertions.assertTrue; | |
| @@ -65,7 +64,7 @@ void testDependencyManagement() throws Exception { | |
| assertEquals(pom0Basedir, project1.getParent().getBasedir()); | |
| Set set = project1.getArtifacts(); | |
| assertNotNull(set, "No artifacts"); | |
| - assertFalse(set.isEmpty(), "No Artifacts"); | |
| + assertTrue(set.size() > 0, "No Artifacts"); | |
| for (Object aSet : set) { | |
| Artifact artifact = (Artifact) aSet; | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t06/ProjectInheritanceTest.java b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t06/ProjectInheritanceTest.java | |
| index 7dd2159889..43a666040f 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t06/ProjectInheritanceTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t06/ProjectInheritanceTest.java | |
| @@ -28,7 +28,6 @@ | |
| import org.junit.jupiter.api.Test; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| import static org.junit.jupiter.api.Assertions.assertTrue; | |
| @@ -66,7 +65,7 @@ void testDependencyManagement() throws Exception { | |
| assertEquals(pom0Basedir, project1.getParent().getBasedir()); | |
| Set set = project1.getArtifacts(); | |
| assertNotNull(set, "No artifacts"); | |
| - assertFalse(set.isEmpty(), "No Artifacts"); | |
| + assertTrue(set.size() > 0, "No Artifacts"); | |
| Iterator iter = set.iterator(); | |
| assertTrue(set.size() == 4, "Set size should be 4, is " + set.size()); | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t07/ProjectInheritanceTest.java b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t07/ProjectInheritanceTest.java | |
| index a25950845e..2d1bc2a940 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t07/ProjectInheritanceTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t07/ProjectInheritanceTest.java | |
| @@ -64,7 +64,7 @@ void testDependencyManagement() throws Exception { | |
| System.out.println("Project " + project1.getId() + " " + project1); | |
| Set set = project1.getArtifacts(); | |
| assertNotNull(set, "No artifacts"); | |
| - assertFalse(set.isEmpty(), "No Artifacts"); | |
| + assertTrue(set.size() > 0, "No Artifacts"); | |
| assertTrue(set.size() == 3, "Set size should be 3, is " + set.size()); | |
| for (Object aSet : set) { | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t08/ProjectInheritanceTest.java b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t08/ProjectInheritanceTest.java | |
| index aa5277a7ff..5158f52e29 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t08/ProjectInheritanceTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t08/ProjectInheritanceTest.java | |
| @@ -28,7 +28,6 @@ | |
| import org.junit.jupiter.api.Test; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| import static org.junit.jupiter.api.Assertions.assertTrue; | |
| @@ -67,7 +66,7 @@ void testDependencyManagement() throws Exception { | |
| System.out.println("Project " + project1.getId() + " " + project1); | |
| Set set = project1.getArtifacts(); | |
| assertNotNull(set, "No artifacts"); | |
| - assertFalse(set.isEmpty(), "No Artifacts"); | |
| + assertTrue(set.size() > 0, "No Artifacts"); | |
| Iterator iter = set.iterator(); | |
| assertTrue(set.size() == 4, "Set size should be 4, is " + set.size()); | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t09/ProjectInheritanceTest.java b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t09/ProjectInheritanceTest.java | |
| index 7236385f90..149b7b04e1 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t09/ProjectInheritanceTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t09/ProjectInheritanceTest.java | |
| @@ -78,7 +78,7 @@ void testDependencyManagementExclusionsExcludeTransitively() throws Exception { | |
| Map map = project1.getArtifactMap(); | |
| assertNotNull(map, "No artifacts"); | |
| - assertFalse(map.isEmpty(), "No Artifacts"); | |
| + assertTrue(map.size() > 0, "No Artifacts"); | |
| assertTrue(map.size() == 2, "Set size should be 2, is " + map.size()); | |
| assertTrue(map.containsKey("maven-test:t09-a"), "maven-test:t09-a is not in the project"); | |
| @@ -111,7 +111,7 @@ void testDependencyManagementExclusionDoesNotOverrideGloballyForTransitives() th | |
| assertEquals(pom0Basedir, project2.getParent().getBasedir()); | |
| Map map = project2.getArtifactMap(); | |
| assertNotNull(map, "No artifacts"); | |
| - assertFalse(map.isEmpty(), "No Artifacts"); | |
| + assertTrue(map.size() > 0, "No Artifacts"); | |
| assertTrue(map.size() == 4, "Set size should be 4, is " + map.size()); | |
| assertTrue(map.containsKey("maven-test:t09-a"), "maven-test:t09-a is not in the project"); | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t10/ProjectInheritanceTest.java b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t10/ProjectInheritanceTest.java | |
| index 3fa5698a3b..e9004e0113 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t10/ProjectInheritanceTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/project/inheritance/t10/ProjectInheritanceTest.java | |
| @@ -27,7 +27,6 @@ | |
| import org.junit.jupiter.api.Test; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| import static org.junit.jupiter.api.Assertions.assertTrue; | |
| @@ -72,7 +71,7 @@ void testDependencyManagementOverridesTransitiveDependencyVersion() throws Excep | |
| System.out.println("Project " + project1.getId() + " " + project1); | |
| Map map = project1.getArtifactMap(); | |
| assertNotNull(map, "No artifacts"); | |
| - assertFalse(map.isEmpty(), "No Artifacts"); | |
| + assertTrue(map.size() > 0, "No Artifacts"); | |
| assertTrue(map.size() == 3, "Set size should be 3, is " + map.size()); | |
| Artifact a = (Artifact) map.get("maven-test:t10-a"); | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/project/interpolation/StringSearchModelInterpolatorTest.java b/compat/maven-compat/src/test/java/org/apache/maven/project/interpolation/StringSearchModelInterpolatorTest.java | |
| deleted file mode 100644 | |
| index b5c1f64188..0000000000 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/project/interpolation/StringSearchModelInterpolatorTest.java | |
| +++ /dev/null | |
| @@ -1,41 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.project.interpolation; | |
| - | |
| -import java.util.Map; | |
| - | |
| -import org.apache.maven.api.model.InputLocation; | |
| -import org.apache.maven.api.model.InputSource; | |
| -import org.apache.maven.api.model.Model; | |
| -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; | |
| -import org.junit.jupiter.api.Test; | |
| - | |
| -class StringSearchModelInterpolatorTest { | |
| - | |
| - @Test | |
| - void interpolate() throws ModelInterpolationException, InitializationException { | |
| - Model model = Model.newBuilder() | |
| - .groupId("group") | |
| - .location("groupId", InputLocation.of(InputSource.of("model", null))) | |
| - .build(); | |
| - StringSearchModelInterpolator interpolator = new StringSearchModelInterpolator(); | |
| - interpolator.initialize(); | |
| - interpolator.interpolate(new org.apache.maven.model.Model(model), Map.of()); | |
| - } | |
| -} | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java b/compat/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java | |
| index dbdb15523b..8f9709a175 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java | |
| @@ -185,7 +185,7 @@ public void setPath(ProducedArtifact artifact, Path path) { | |
| // | |
| d.setScope(Artifact.SCOPE_SYSTEM); | |
| File file = new File(getBasedir(), "src/test/repository-system/maven-core-2.1.0.jar"); | |
| - assertTrue(file.exists(), "Expected " + file + ".exists() to return true"); | |
| + assertTrue(file.exists()); | |
| d.setSystemPath(file.getCanonicalPath()); | |
| artifact = repositorySystem.createDependencyArtifact(d); | |
| @@ -208,7 +208,7 @@ public void setPath(ProducedArtifact artifact, Path path) { | |
| // Put in a bogus file to make sure missing files cause the resolution to fail. | |
| // | |
| file = new File(getBasedir(), "src/test/repository-system/maven-monkey-2.1.0.jar"); | |
| - assertFalse(file.exists(), "Expected " + file + ".exists() to return false"); | |
| + assertFalse(file.exists()); | |
| d.setSystemPath(file.getCanonicalPath()); | |
| artifact = repositorySystem.createDependencyArtifact(d); | |
| @@ -226,7 +226,7 @@ public void setPath(ProducedArtifact artifact, Path path) { | |
| result = repositorySystem.resolve(request); | |
| resolutionErrorHandler.throwErrors(request, result); | |
| } catch (Exception e) { | |
| - assertTrue(result.hasMissingArtifacts(), "Expected " + result + ".hasMissingArtifacts() to return true"); | |
| + assertTrue(result.hasMissingArtifacts()); | |
| } | |
| } | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/repository/legacy/DefaultUpdateCheckManagerTest.java b/compat/maven-compat/src/test/java/org/apache/maven/repository/legacy/DefaultUpdateCheckManagerTest.java | |
| index 6e61442f3a..e06318c1db 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/repository/legacy/DefaultUpdateCheckManagerTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/repository/legacy/DefaultUpdateCheckManagerTest.java | |
| @@ -108,7 +108,7 @@ void testMissingArtifact() throws Exception { | |
| assertFalse(updateCheckManager.isUpdateRequired(a, remoteRepository)); | |
| - assertFalse(file.exists(), "Expected " + file + ".exists() to return false"); | |
| + assertFalse(file.exists()); | |
| assertNotNull( | |
| updateCheckManager.readLastUpdated(touchFile, updateCheckManager.getRepositoryKey(remoteRepository))); | |
| } | |
| @@ -161,7 +161,7 @@ void testMissingPom() throws Exception { | |
| assertFalse(updateCheckManager.isUpdateRequired(a, remoteRepository)); | |
| - assertFalse(file.exists(), "Expected " + file + ".exists() to return false"); | |
| + assertFalse(file.exists()); | |
| assertNotNull( | |
| updateCheckManager.readLastUpdated(touchFile, updateCheckManager.getRepositoryKey(remoteRepository))); | |
| } | |
| diff --git a/compat/maven-compat/src/test/java/org/apache/maven/repository/legacy/resolver/DefaultArtifactCollectorTest.java b/compat/maven-compat/src/test/java/org/apache/maven/repository/legacy/resolver/DefaultArtifactCollectorTest.java | |
| index 72209b3dce..641d3034df 100644 | |
| --- a/compat/maven-compat/src/test/java/org/apache/maven/repository/legacy/resolver/DefaultArtifactCollectorTest.java | |
| +++ b/compat/maven-compat/src/test/java/org/apache/maven/repository/legacy/resolver/DefaultArtifactCollectorTest.java | |
| @@ -333,7 +333,7 @@ void testIncompatibleRanges() throws ArtifactResolutionException, InvalidVersion | |
| ArtifactResolutionResult res = collect(a); | |
| - assertTrue(res.hasVersionRangeViolations(), "Expected " + res + ".hasVersionRangeViolations() to return true"); | |
| + assertTrue(res.hasVersionRangeViolations()); | |
| } | |
| @Test | |
| @@ -346,7 +346,7 @@ void testUnboundedRangeWhenVersionUnavailable() | |
| ArtifactResolutionResult res = collect(a); | |
| - assertTrue(res.hasVersionRangeViolations(), "Expected " + res + ".hasVersionRangeViolations() to return true"); | |
| + assertTrue(res.hasVersionRangeViolations()); | |
| } | |
| @Test | |
| @@ -371,7 +371,7 @@ void testUnboundedRangeAboveLastRelease() throws ArtifactResolutionException, In | |
| ArtifactResolutionResult res = collect(a); | |
| - assertTrue(res.hasVersionRangeViolations(), "Expected " + res + ".hasVersionRangeViolations() to return true"); | |
| + assertTrue(res.hasVersionRangeViolations()); | |
| } | |
| @Test | |
| @@ -665,7 +665,7 @@ void testSnapshotNotIncluded() throws ArtifactResolutionException, InvalidVersio | |
| ArtifactResolutionResult res = collect(a); | |
| - assertTrue(res.hasVersionRangeViolations(), "Expected " + res + ".hasVersionRangeViolations() to return true"); | |
| + assertTrue(res.hasVersionRangeViolations()); | |
| /* | |
| * try { ArtifactResolutionResult res = collect( a ); fail( "Expected b not to resolve: " + res ); } catch ( | |
| diff --git a/compat/maven-embedder/pom.xml b/compat/maven-embedder/pom.xml | |
| index 2df8588ec1..7c1045dfcf 100644 | |
| --- a/compat/maven-embedder/pom.xml | |
| +++ b/compat/maven-embedder/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-embedder</artifactId> | |
| @@ -205,7 +205,11 @@ under the License. | |
| <artifactId>junit-jupiter-params</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| - | |
| + <dependency> | |
| + <groupId>org.hamcrest</groupId> | |
| + <artifactId>hamcrest</artifactId> | |
| + <scope>test</scope> | |
| + </dependency> | |
| <dependency> | |
| <groupId>org.mockito</groupId> | |
| <artifactId>mockito-core</artifactId> | |
| diff --git a/compat/maven-embedder/src/examples/simple-project/settings.xml b/compat/maven-embedder/src/examples/simple-project/settings.xml | |
| index 63cf96e1fd..39709fdef3 100644 | |
| --- a/compat/maven-embedder/src/examples/simple-project/settings.xml | |
| +++ b/compat/maven-embedder/src/examples/simple-project/settings.xml | |
| @@ -18,7 +18,7 @@ specific language governing permissions and limitations | |
| under the License. | |
| --> | |
| -<settings xmlns='http://maven.apache.org/SETTINGS/1.0.0'> | |
| +<settings> | |
| <pluginGroups> | |
| <pluginGroup>org.codehaus.tycho</pluginGroup> | |
| <pluginGroup>org.sonatype.pwt</pluginGroup> | |
| diff --git a/compat/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java b/compat/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java | |
| index 3d930b10cf..3cc0d38a67 100644 | |
| --- a/compat/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java | |
| +++ b/compat/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java | |
| @@ -188,7 +188,7 @@ public CLIManager() { | |
| options.addOption(Option.builder(Character.toString(ACTIVATE_PROFILES)) | |
| .longOpt("activate-profiles") | |
| .desc( | |
| - "Comma-delimited list of profiles to activate. Don't use spaces between commas or double quote the full list. Prefixing a profile with ! excludes it, and ? marks it as optional.") | |
| + "Comma-delimited list of profiles to activate. Prefixing a profile with ! excludes it, and ? marks it as optional") | |
| .hasArg() | |
| .build()); | |
| options.addOption(Option.builder(Character.toString(BATCH_MODE)) | |
| @@ -271,7 +271,7 @@ public CLIManager() { | |
| options.addOption(Option.builder(PROJECT_LIST) | |
| .longOpt("projects") | |
| .desc( | |
| - "Comma-delimited list of specified reactor projects to build instead of all projects. Don't use spaces between commas or double quote the full list. A project can be specified by [groupId]:artifactId or by its relative path. Prefixing a project with ! excludes it, and ? marks it as optional.") | |
| + "Comma-delimited list of specified reactor projects to build instead of all projects. A project can be specified by [groupId]:artifactId or by its relative path. Prefixing a project with ! excludes it, and ? marks it as optional") | |
| .hasArg() | |
| .build()); | |
| options.addOption(Option.builder(ALSO_MAKE) | |
| diff --git a/compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java | |
| index 9e1d1a1932..648d96a158 100644 | |
| --- a/compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java | |
| +++ b/compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java | |
| @@ -860,7 +860,7 @@ private List<CoreExtension> readCoreExtensionsDescriptor(String extensionsFile) | |
| if (Files.exists(extensionsPath)) { | |
| try (InputStream is = Files.newInputStream(extensionsPath)) { | |
| return new CoreExtensionsStaxReader() | |
| - .read(is, true, InputSource.of(extensionsFile)) | |
| + .read(is, true, new InputSource(extensionsFile)) | |
| .getExtensions(); | |
| } | |
| } | |
| @@ -1675,6 +1675,9 @@ void populateProperties( | |
| Path userPropertiesFile = mavenConf.resolve("maven-user.properties"); | |
| MavenPropertiesLoader.loadProperties(userProperties, userPropertiesFile, callback, false); | |
| + // Warn about deprecated maven.properties files | |
| + warnAboutDeprecatedPropertiesFiles(systemProperties); | |
| + | |
| // ---------------------------------------------------------------------- | |
| // I'm leaving the setting of system properties here as not to break | |
| // the SystemPropertyProfileActivator. This won't harm embedding. jvz. | |
| @@ -1753,6 +1756,29 @@ protected ModelProcessor createModelProcessor(PlexusContainer container) throws | |
| return container.lookup(ModelProcessor.class); | |
| } | |
| + private void warnAboutDeprecatedPropertiesFiles(Properties systemProperties) { | |
| + // Check for deprecated ~/.m2/maven.properties | |
| + String userConfig = systemProperties.getProperty("maven.user.conf"); | |
| + Path userMavenProperties = userConfig != null ? Path.of(userConfig).resolve("maven.properties") : null; | |
| + if (userMavenProperties != null && Files.exists(userMavenProperties)) { | |
| + slf4jLogger.warn( | |
| + "Loading deprecated properties file: {}. " + "Please rename to 'maven-user.properties'. " | |
| + + "Support for 'maven.properties' will be removed in Maven 4.1.0.", | |
| + userMavenProperties); | |
| + } | |
| + | |
| + // Check for deprecated .mvn/maven.properties in project directory | |
| + String projectConfig = systemProperties.getProperty("maven.project.conf"); | |
| + Path projectMavenProperties = | |
| + projectConfig != null ? Path.of(projectConfig).resolve("maven.properties") : null; | |
| + if (projectMavenProperties != null && Files.exists(projectMavenProperties)) { | |
| + slf4jLogger.warn( | |
| + "Loading deprecated properties file: {}. " + "Please rename to 'maven-user.properties'. " | |
| + + "Support for 'maven.properties' will be removed in Maven 4.1.0.", | |
| + projectMavenProperties); | |
| + } | |
| + } | |
| + | |
| public void setFileSystem(FileSystem fileSystem) { | |
| this.fileSystem = fileSystem; | |
| } | |
| diff --git a/compat/maven-embedder/src/main/java/org/apache/maven/cli/props/MavenProperties.java b/compat/maven-embedder/src/main/java/org/apache/maven/cli/props/MavenProperties.java | |
| index f35d49d2fb..63c6c09d4b 100644 | |
| --- a/compat/maven-embedder/src/main/java/org/apache/maven/cli/props/MavenProperties.java | |
| +++ b/compat/maven-embedder/src/main/java/org/apache/maven/cli/props/MavenProperties.java | |
| @@ -871,7 +871,7 @@ public String readProperty() throws IOException { | |
| line = line.substring(0, line.length() - 1); | |
| } | |
| valueLines.add(line); | |
| - while (!line.isEmpty() && contains(WHITE_SPACE, line.charAt(0))) { | |
| + while (line.length() > 0 && contains(WHITE_SPACE, line.charAt(0))) { | |
| line = line.substring(1, line.length()); | |
| } | |
| buffer.append(line); | |
| diff --git a/compat/maven-embedder/src/main/java/org/eclipse/sisu/plexus/PlexusXmlBeanConverter.java b/compat/maven-embedder/src/main/java/org/eclipse/sisu/plexus/PlexusXmlBeanConverter.java | |
| index 0ff3f5b60d..5f06757069 100644 | |
| --- a/compat/maven-embedder/src/main/java/org/eclipse/sisu/plexus/PlexusXmlBeanConverter.java | |
| +++ b/compat/maven-embedder/src/main/java/org/eclipse/sisu/plexus/PlexusXmlBeanConverter.java | |
| @@ -391,6 +391,6 @@ private Object convertText(final String value, final TypeLiteral<?> toType) { | |
| } | |
| // last chance => attempt to create an instance of the expected type: use the string if non-empty | |
| - return text.isEmpty() ? newImplementation(rawType) : newImplementation(rawType, text); | |
| + return text.length() == 0 ? newImplementation(rawType) : newImplementation(rawType, text); | |
| } | |
| } | |
| diff --git a/compat/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java b/compat/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java | |
| index bbaa3e622d..5867a4537c 100644 | |
| --- a/compat/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java | |
| +++ b/compat/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java | |
| @@ -26,7 +26,6 @@ | |
| import java.nio.file.Files; | |
| import java.nio.file.Path; | |
| import java.nio.file.Paths; | |
| -import java.util.Collection; | |
| import java.util.Collections; | |
| import java.util.List; | |
| import java.util.stream.Stream; | |
| @@ -57,6 +56,7 @@ | |
| import org.codehaus.plexus.DefaultPlexusContainer; | |
| import org.codehaus.plexus.PlexusContainer; | |
| import org.eclipse.aether.transfer.TransferListener; | |
| +import org.hamcrest.CoreMatchers; | |
| import org.junit.jupiter.api.AfterEach; | |
| import org.junit.jupiter.api.BeforeEach; | |
| import org.junit.jupiter.api.Test; | |
| @@ -68,11 +68,14 @@ | |
| import static java.util.Arrays.asList; | |
| import static org.apache.maven.cli.MavenCli.performProfileActivation; | |
| import static org.apache.maven.cli.MavenCli.performProjectActivation; | |
| -import static org.junit.jupiter.api.Assertions.assertArrayEquals; | |
| +import static org.hamcrest.CoreMatchers.equalTo; | |
| +import static org.hamcrest.CoreMatchers.is; | |
| +import static org.hamcrest.CoreMatchers.notNullValue; | |
| +import static org.hamcrest.CoreMatchers.nullValue; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| import static org.junit.jupiter.api.Assertions.assertFalse; | |
| -import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| -import static org.junit.jupiter.api.Assertions.assertNull; | |
| import static org.junit.jupiter.api.Assertions.assertThrows; | |
| import static org.junit.jupiter.api.Assertions.assertTrue; | |
| import static org.junit.jupiter.api.Assumptions.assumeTrue; | |
| @@ -102,14 +105,6 @@ void tearDown() throws Exception { | |
| } | |
| } | |
| - // Helper method for containsExactlyInAnyOrder assertion | |
| - private static <T> void assertContainsExactlyInAnyOrder(Collection<T> actual, T... expected) { | |
| - assertEquals(expected.length, actual.size(), "Collection size mismatch"); | |
| - for (T item : expected) { | |
| - assertTrue(actual.contains(item), "Collection should contain: " + item); | |
| - } | |
| - } | |
| - | |
| @Test | |
| void testPerformProfileActivation() throws ParseException { | |
| final CommandLineParser parser = new DefaultParser(); | |
| @@ -123,19 +118,19 @@ void testPerformProfileActivation() throws ParseException { | |
| activation = new ProfileActivation(); | |
| performProfileActivation(parser.parse(options, new String[] {"-P", "test1,+test2,?test3,+?test4"}), activation); | |
| - assertContainsExactlyInAnyOrder(activation.getRequiredActiveProfileIds(), "test1", "test2"); | |
| - assertContainsExactlyInAnyOrder(activation.getOptionalActiveProfileIds(), "test3", "test4"); | |
| + assertThat(activation.getRequiredActiveProfileIds(), containsInAnyOrder("test1", "test2")); | |
| + assertThat(activation.getOptionalActiveProfileIds(), containsInAnyOrder("test3", "test4")); | |
| activation = new ProfileActivation(); | |
| performProfileActivation( | |
| parser.parse(options, new String[] {"-P", "!test1,-test2,-?test3,!?test4"}), activation); | |
| - assertContainsExactlyInAnyOrder(activation.getRequiredInactiveProfileIds(), "test1", "test2"); | |
| - assertContainsExactlyInAnyOrder(activation.getOptionalInactiveProfileIds(), "test3", "test4"); | |
| + assertThat(activation.getRequiredInactiveProfileIds(), containsInAnyOrder("test1", "test2")); | |
| + assertThat(activation.getOptionalInactiveProfileIds(), containsInAnyOrder("test3", "test4")); | |
| activation = new ProfileActivation(); | |
| performProfileActivation(parser.parse(options, new String[] {"-P", "-test1,+test2"}), activation); | |
| - assertContainsExactlyInAnyOrder(activation.getRequiredActiveProfileIds(), "test2"); | |
| - assertContainsExactlyInAnyOrder(activation.getRequiredInactiveProfileIds(), "test1"); | |
| + assertThat(activation.getRequiredActiveProfileIds(), containsInAnyOrder("test2")); | |
| + assertThat(activation.getRequiredInactiveProfileIds(), containsInAnyOrder("test1")); | |
| } | |
| @Test | |
| @@ -150,19 +145,19 @@ void testDetermineProjectActivation() throws ParseException { | |
| activation = new ProjectActivation(); | |
| performProjectActivation( | |
| parser.parse(options, new String[] {"-pl", "test1,+test2,?test3,+?test4"}), activation); | |
| - assertContainsExactlyInAnyOrder(activation.getRequiredActiveProjectSelectors(), "test1", "test2"); | |
| - assertContainsExactlyInAnyOrder(activation.getOptionalActiveProjectSelectors(), "test3", "test4"); | |
| + assertThat(activation.getRequiredActiveProjectSelectors(), containsInAnyOrder("test1", "test2")); | |
| + assertThat(activation.getOptionalActiveProjectSelectors(), containsInAnyOrder("test3", "test4")); | |
| activation = new ProjectActivation(); | |
| performProjectActivation( | |
| parser.parse(options, new String[] {"-pl", "!test1,-test2,-?test3,!?test4"}), activation); | |
| - assertContainsExactlyInAnyOrder(activation.getRequiredInactiveProjectSelectors(), "test1", "test2"); | |
| - assertContainsExactlyInAnyOrder(activation.getOptionalInactiveProjectSelectors(), "test3", "test4"); | |
| + assertThat(activation.getRequiredInactiveProjectSelectors(), containsInAnyOrder("test1", "test2")); | |
| + assertThat(activation.getOptionalInactiveProjectSelectors(), containsInAnyOrder("test3", "test4")); | |
| activation = new ProjectActivation(); | |
| performProjectActivation(parser.parse(options, new String[] {"-pl", "-test1,+test2"}), activation); | |
| - assertContainsExactlyInAnyOrder(activation.getRequiredActiveProjectSelectors(), "test2"); | |
| - assertContainsExactlyInAnyOrder(activation.getRequiredInactiveProjectSelectors(), "test1"); | |
| + assertThat(activation.getRequiredActiveProjectSelectors(), containsInAnyOrder("test2")); | |
| + assertThat(activation.getRequiredInactiveProjectSelectors(), containsInAnyOrder("test1")); | |
| } | |
| @Test | |
| @@ -352,21 +347,21 @@ void testStyleColors() throws Exception { | |
| cli.cli(request); | |
| cli.properties(request); | |
| cli.logging(request); | |
| - assertFalse(MessageUtils.isColorEnabled(), "Expected MessageUtils.isColorEnabled() to return false"); | |
| + assertFalse(MessageUtils.isColorEnabled()); | |
| MessageUtils.setColorEnabled(true); | |
| request = new CliRequest(new String[] {"--non-interactive"}, null); | |
| cli.cli(request); | |
| cli.properties(request); | |
| cli.logging(request); | |
| - assertFalse(MessageUtils.isColorEnabled(), "Expected MessageUtils.isColorEnabled() to return false"); | |
| + assertFalse(MessageUtils.isColorEnabled()); | |
| MessageUtils.setColorEnabled(true); | |
| request = new CliRequest(new String[] {"--force-interactive", "--non-interactive"}, null); | |
| cli.cli(request); | |
| cli.properties(request); | |
| cli.logging(request); | |
| - assertTrue(MessageUtils.isColorEnabled(), "Expected MessageUtils.isColorEnabled() to return true"); | |
| + assertTrue(MessageUtils.isColorEnabled()); | |
| MessageUtils.setColorEnabled(true); | |
| request = new CliRequest(new String[] {"-l", "target/temp/mvn.log"}, null); | |
| @@ -374,21 +369,21 @@ void testStyleColors() throws Exception { | |
| cli.cli(request); | |
| cli.properties(request); | |
| cli.logging(request); | |
| - assertFalse(MessageUtils.isColorEnabled(), "Expected MessageUtils.isColorEnabled() to return false"); | |
| + assertFalse(MessageUtils.isColorEnabled()); | |
| MessageUtils.setColorEnabled(false); | |
| request = new CliRequest(new String[] {"-Dstyle.color=always"}, null); | |
| cli.cli(request); | |
| cli.properties(request); | |
| cli.logging(request); | |
| - assertTrue(MessageUtils.isColorEnabled(), "Expected MessageUtils.isColorEnabled() to return true"); | |
| + assertTrue(MessageUtils.isColorEnabled()); | |
| MessageUtils.setColorEnabled(true); | |
| request = new CliRequest(new String[] {"-Dstyle.color=never"}, null); | |
| cli.cli(request); | |
| cli.properties(request); | |
| cli.logging(request); | |
| - assertFalse(MessageUtils.isColorEnabled(), "Expected MessageUtils.isColorEnabled() to return false"); | |
| + assertFalse(MessageUtils.isColorEnabled()); | |
| MessageUtils.setColorEnabled(false); | |
| request = new CliRequest(new String[] {"-Dstyle.color=always", "-B", "-l", "target/temp/mvn.log"}, null); | |
| @@ -396,7 +391,7 @@ void testStyleColors() throws Exception { | |
| cli.cli(request); | |
| cli.properties(request); | |
| cli.logging(request); | |
| - assertTrue(MessageUtils.isColorEnabled(), "Expected MessageUtils.isColorEnabled() to return true"); | |
| + assertTrue(MessageUtils.isColorEnabled()); | |
| MessageUtils.setColorEnabled(false); | |
| CliRequest maybeColorRequest = | |
| @@ -450,7 +445,7 @@ void resumeFromSelectorIsSuggestedWithoutGroupId() { | |
| String selector = cli.getResumeFromSelector(allProjects, failedProject); | |
| - assertEquals(":module-a", selector); | |
| + assertThat(selector, is(":module-a")); | |
| } | |
| @Test | |
| @@ -461,7 +456,7 @@ void resumeFromSelectorContainsGroupIdWhenArtifactIdIsNotUnique() { | |
| String selector = cli.getResumeFromSelector(allProjects, failedProject); | |
| - assertEquals("group-a:module", selector); | |
| + assertThat(selector, is("group-a:module")); | |
| } | |
| @Test | |
| @@ -474,23 +469,19 @@ void verifyLocalRepositoryPath() throws Exception { | |
| // Use default | |
| cli.cli(request); | |
| executionRequest = cli.populateRequest(request); | |
| - assertNull(executionRequest.getLocalRepositoryPath()); | |
| + assertThat(executionRequest.getLocalRepositoryPath(), is(nullValue())); | |
| // System-properties override default | |
| request.getSystemProperties().setProperty(Constants.MAVEN_REPO_LOCAL, "." + File.separatorChar + "custom1"); | |
| executionRequest = cli.populateRequest(request); | |
| - assertNotNull(executionRequest.getLocalRepositoryPath()); | |
| - assertEquals( | |
| - "." + File.separatorChar + "custom1", | |
| - executionRequest.getLocalRepositoryPath().toString()); | |
| + assertThat(executionRequest.getLocalRepositoryPath(), is(notNullValue())); | |
| + assertThat(executionRequest.getLocalRepositoryPath().toString(), is("." + File.separatorChar + "custom1")); | |
| // User-properties override system properties | |
| request.getUserProperties().setProperty(Constants.MAVEN_REPO_LOCAL, "." + File.separatorChar + "custom2"); | |
| executionRequest = cli.populateRequest(request); | |
| - assertNotNull(executionRequest.getLocalRepositoryPath()); | |
| - assertEquals( | |
| - "." + File.separatorChar + "custom2", | |
| - executionRequest.getLocalRepositoryPath().toString()); | |
| + assertThat(executionRequest.getLocalRepositoryPath(), is(notNullValue())); | |
| + assertThat(executionRequest.getLocalRepositoryPath().toString(), is("." + File.separatorChar + "custom2")); | |
| } | |
| /** | |
| @@ -531,7 +522,7 @@ void populatePropertiesCanContainEqualsSign() throws Exception { | |
| cli.properties(request); | |
| // Assert | |
| - assertEquals("x=y", request.getUserProperties().getProperty("w")); | |
| + assertThat(request.getUserProperties().getProperty("w"), is("x=y")); | |
| } | |
| @Test | |
| @@ -544,7 +535,7 @@ void populatePropertiesSpace() throws Exception { | |
| cli.properties(request); | |
| // Assert | |
| - assertEquals("2", request.getUserProperties().getProperty("z")); | |
| + assertThat(request.getUserProperties().getProperty("z"), is("2")); | |
| } | |
| @Test | |
| @@ -557,7 +548,7 @@ void populatePropertiesShorthand() throws Exception { | |
| cli.properties(request); | |
| // Assert | |
| - assertEquals("true", request.getUserProperties().getProperty("x")); | |
| + assertThat(request.getUserProperties().getProperty("x"), is("true")); | |
| } | |
| @Test | |
| @@ -570,8 +561,8 @@ void populatePropertiesMultiple() throws Exception { | |
| cli.properties(request); | |
| // Assert | |
| - assertEquals("1", request.getUserProperties().getProperty("x")); | |
| - assertEquals("true", request.getUserProperties().getProperty("y")); | |
| + assertThat(request.getUserProperties().getProperty("x"), is("1")); | |
| + assertThat(request.getUserProperties().getProperty("y"), is("true")); | |
| } | |
| @Test | |
| @@ -584,7 +575,7 @@ void populatePropertiesOverwrite() throws Exception { | |
| cli.properties(request); | |
| // Assert | |
| - assertEquals("false", request.getUserProperties().getProperty("x")); | |
| + assertThat(request.getUserProperties().getProperty("x"), is("false")); | |
| } | |
| @Test | |
| @@ -637,20 +628,18 @@ public void testPropertiesInterpolation() throws Exception { | |
| cli.properties(request); | |
| // Assert | |
| - assertTrue(request.getUserProperties().getProperty("fro").startsWith("chti")); | |
| - assertEquals("sbari", request.getUserProperties().getProperty("valFound")); | |
| - assertEquals("s${foz}i", request.getUserProperties().getProperty("valNotFound")); | |
| - assertEquals("C:\\myRootDirectory/.mvn/foo", request.getUserProperties().getProperty("valRootDirectory")); | |
| - assertEquals( | |
| - "C:\\myRootDirectory\\myTopDirectory/pom.xml", | |
| - request.getUserProperties().getProperty("valTopDirectory")); | |
| - assertEquals("C:\\myRootDirectory/my-child", request.getCommandLine().getOptionValue('f')); | |
| - assertArrayEquals( | |
| - new String[] {"prefix:3.0.0:bar", "validate"}, | |
| - request.getCommandLine().getArgs()); | |
| + assertThat(request.getUserProperties().getProperty("fro"), CoreMatchers.startsWith("chti")); | |
| + assertThat(request.getUserProperties().getProperty("valFound"), is("sbari")); | |
| + assertThat(request.getUserProperties().getProperty("valNotFound"), is("s${foz}i")); | |
| + assertThat(request.getUserProperties().getProperty("valRootDirectory"), is("C:\\myRootDirectory/.mvn/foo")); | |
| + assertThat( | |
| + request.getUserProperties().getProperty("valTopDirectory"), | |
| + is("C:\\myRootDirectory\\myTopDirectory/pom.xml")); | |
| + assertThat(request.getCommandLine().getOptionValue('f'), is("C:\\myRootDirectory/my-child")); | |
| + assertThat(request.getCommandLine().getArgs(), equalTo(new String[] {"prefix:3.0.0:bar", "validate"})); | |
| Path p = fs.getPath(request.getUserProperties().getProperty("valTopDirectory")); | |
| - assertEquals("C:\\myRootDirectory\\myTopDirectory\\pom.xml", p.toString()); | |
| + assertThat(p.toString(), is("C:\\myRootDirectory\\myTopDirectory\\pom.xml")); | |
| } | |
| @Test | |
| @@ -678,7 +667,7 @@ public void activateBatchMode(boolean ciEnv, String[] cliArgs, boolean isBatchMo | |
| boolean batchMode = !cli.populateRequest(request).isInteractiveMode(); | |
| - assertEquals(isBatchMode, batchMode); | |
| + assertThat(batchMode, is(isBatchMode)); | |
| } | |
| public static Stream<Arguments> activateBatchModeArguments() { | |
| @@ -710,7 +699,7 @@ public void calculateTransferListener(boolean ciEnv, String[] cliArgs, Class<Tra | |
| transferListener = simplexTransferListener.getDelegate(); | |
| } | |
| - assertEquals(expectedSubClass, transferListener.getClass()); | |
| + assertThat(transferListener.getClass(), is(expectedSubClass)); | |
| } | |
| public static Stream<Arguments> calculateTransferListenerArguments() { | |
| diff --git a/compat/maven-model-builder/pom.xml b/compat/maven-model-builder/pom.xml | |
| index 79ebf1b143..8c2719f1f6 100644 | |
| --- a/compat/maven-model-builder/pom.xml | |
| +++ b/compat/maven-model-builder/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-model-builder</artifactId> | |
| @@ -86,10 +86,14 @@ under the License. | |
| <artifactId>junit-jupiter-api</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| - | |
| + <dependency> | |
| + <groupId>org.hamcrest</groupId> | |
| + <artifactId>hamcrest</artifactId> | |
| + <scope>test</scope> | |
| + </dependency> | |
| <dependency> | |
| <groupId>org.xmlunit</groupId> | |
| - <artifactId>xmlunit-core</artifactId> | |
| + <artifactId>xmlunit-matchers</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| </dependencies> | |
| diff --git a/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblem.java b/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblem.java | |
| index 97cdab3bb6..7c42f2b237 100644 | |
| --- a/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblem.java | |
| +++ b/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblem.java | |
| @@ -140,7 +140,7 @@ public Exception getException() { | |
| public String getMessage() { | |
| String msg; | |
| - if (message != null && !message.isEmpty()) { | |
| + if (message != null && message.length() > 0) { | |
| msg = message; | |
| } else { | |
| msg = exception.getMessage(); | |
| diff --git a/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java b/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java | |
| index d623217abe..9055ca8b91 100644 | |
| --- a/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java | |
| +++ b/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java | |
| @@ -138,12 +138,6 @@ protected void mergeModel_Profiles( | |
| .collect(Collectors.toList())); | |
| } | |
| - @Override | |
| - protected void mergeModel_Mixins( | |
| - Model.Builder builder, Model target, Model source, boolean sourceDominant, Map<Object, Object> context) { | |
| - // don't merge | |
| - } | |
| - | |
| @Override | |
| protected void mergeModelBase_Dependencies( | |
| ModelBase.Builder builder, | |
| diff --git a/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java b/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java | |
| index 28c6618e03..540d891002 100644 | |
| --- a/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java | |
| +++ b/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java | |
| @@ -138,7 +138,7 @@ static String toMessage(String modelId, List<ModelProblem> problems) { | |
| writer.print(problems.size()); | |
| writer.print((problems.size() == 1) ? " problem was " : " problems were "); | |
| writer.print("encountered while building the effective model"); | |
| - if (modelId != null && !modelId.isEmpty()) { | |
| + if (modelId != null && modelId.length() > 0) { | |
| writer.print(" for "); | |
| writer.print(modelId); | |
| } | |
| diff --git a/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java b/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java | |
| index 1956c941e4..8a694d122c 100644 | |
| --- a/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java | |
| +++ b/compat/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java | |
| @@ -100,11 +100,11 @@ static String toId(Model model) { | |
| static String toId(String groupId, String artifactId, String version) { | |
| StringBuilder buffer = new StringBuilder(128); | |
| - buffer.append((groupId != null && !groupId.isEmpty()) ? groupId : "[unknown-group-id]"); | |
| + buffer.append((groupId != null && groupId.length() > 0) ? groupId : "[unknown-group-id]"); | |
| buffer.append(':'); | |
| - buffer.append((artifactId != null && !artifactId.isEmpty()) ? artifactId : "[unknown-artifact-id]"); | |
| + buffer.append((artifactId != null && artifactId.length() > 0) ? artifactId : "[unknown-artifact-id]"); | |
| buffer.append(':'); | |
| - buffer.append((version != null && !version.isEmpty()) ? version : "[unknown-version]"); | |
| + buffer.append((version != null && version.length() > 0) ? version : "[unknown-version]"); | |
| return buffer.toString(); | |
| } | |
| @@ -125,8 +125,8 @@ public static String formatLocation(ModelProblem problem, String projectId) { | |
| if (!problem.getModelId().equals(projectId)) { | |
| buffer.append(problem.getModelId()); | |
| - if (!problem.getSource().isEmpty()) { | |
| - if (!buffer.isEmpty()) { | |
| + if (problem.getSource().length() > 0) { | |
| + if (buffer.length() > 0) { | |
| buffer.append(", "); | |
| } | |
| buffer.append(problem.getSource()); | |
| @@ -134,14 +134,14 @@ public static String formatLocation(ModelProblem problem, String projectId) { | |
| } | |
| if (problem.getLineNumber() > 0) { | |
| - if (!buffer.isEmpty()) { | |
| + if (buffer.length() > 0) { | |
| buffer.append(", "); | |
| } | |
| buffer.append("line ").append(problem.getLineNumber()); | |
| } | |
| if (problem.getColumnNumber() > 0) { | |
| - if (!buffer.isEmpty()) { | |
| + if (buffer.length() > 0) { | |
| buffer.append(", "); | |
| } | |
| buffer.append("column ").append(problem.getColumnNumber()); | |
| diff --git a/compat/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java b/compat/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java | |
| index d165f12959..1057d87695 100644 | |
| --- a/compat/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java | |
| +++ b/compat/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java | |
| @@ -154,7 +154,7 @@ private String appendPath(String parentUrl, String childPath, String pathAdjustm | |
| StringBuilder url = new StringBuilder(parentUrl.length() | |
| + pathAdjustment.length() | |
| + childPath.length() | |
| - + ((pathAdjustment.isEmpty()) ? 1 : 2)); | |
| + + ((pathAdjustment.length() == 0) ? 1 : 2)); | |
| url.append(parentUrl); | |
| concatPath(url, pathAdjustment); | |
| @@ -164,7 +164,7 @@ private String appendPath(String parentUrl, String childPath, String pathAdjustm | |
| } | |
| private void concatPath(StringBuilder url, String path) { | |
| - if (!path.isEmpty()) { | |
| + if (path.length() > 0) { | |
| boolean initialUrlEndsWithSlash = url.charAt(url.length() - 1) == '/'; | |
| boolean pathStartsWithSlash = path.charAt(0) == '/'; | |
| diff --git a/compat/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/ProblemDetectingValueSource.java b/compat/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/ProblemDetectingValueSource.java | |
| index a69c269583..828b347965 100644 | |
| --- a/compat/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/ProblemDetectingValueSource.java | |
| +++ b/compat/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/ProblemDetectingValueSource.java | |
| @@ -56,7 +56,7 @@ public Object getValue(String expression) { | |
| if (value != null && expression.startsWith(bannedPrefix)) { | |
| String msg = "The expression ${" + expression + "} is deprecated."; | |
| - if (newPrefix != null && !newPrefix.isEmpty()) { | |
| + if (newPrefix != null && newPrefix.length() > 0) { | |
| msg += " Please use ${" + newPrefix + expression.substring(bannedPrefix.length()) + "} instead."; | |
| } | |
| problems.add(new ModelProblemCollectorRequest(Severity.WARNING, Version.V20).setMessage(msg)); | |
| diff --git a/compat/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java b/compat/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java | |
| index 4bde6c4998..5e2d47329d 100644 | |
| --- a/compat/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java | |
| +++ b/compat/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java | |
| @@ -785,10 +785,10 @@ private void validateEffectiveDependencies( | |
| prefix, "version", problems, errOn30, Version.V20, d.getVersion(), d.getManagementKey(), d); | |
| /* | |
| - * Extensions like Flex Mojos use custom scopes like "merged", "internal", "external", etc. In | |
| - * order to not break backward-compat with those, only warn but don't error out. | |
| + * TODO Extensions like Flex Mojos use custom scopes like "merged", "internal", "external", etc. In | |
| + * order to don't break backward-compat with those, only warn but don't error out. | |
| */ | |
| - validateDependencyScope( | |
| + validateEnum( | |
| prefix, | |
| "scope", | |
| problems, | |
| @@ -797,11 +797,15 @@ private void validateEffectiveDependencies( | |
| d.getScope(), | |
| d.getManagementKey(), | |
| d, | |
| - false); | |
| + "provided", | |
| + "compile", | |
| + "runtime", | |
| + "test", | |
| + "system"); | |
| validateEffectiveModelAgainstDependency(prefix, problems, m, d, request); | |
| } else { | |
| - validateDependencyScope( | |
| + validateEnum( | |
| prefix, | |
| "scope", | |
| problems, | |
| @@ -810,7 +814,12 @@ private void validateEffectiveDependencies( | |
| d.getScope(), | |
| d.getManagementKey(), | |
| d, | |
| - true); | |
| + "provided", | |
| + "compile", | |
| + "runtime", | |
| + "test", | |
| + "system", | |
| + "import"); | |
| } | |
| } | |
| } | |
| @@ -1328,7 +1337,7 @@ private boolean validateStringNotEmpty( | |
| return false; | |
| } | |
| - if (!string.isEmpty()) { | |
| + if (string.length() > 0) { | |
| return true; | |
| } | |
| @@ -1453,58 +1462,6 @@ private boolean validateEnum( | |
| return false; | |
| } | |
| - @SuppressWarnings("checkstyle:parameternumber") | |
| - private boolean validateDependencyScope( | |
| - String prefix, | |
| - String fieldName, | |
| - ModelProblemCollector problems, | |
| - Severity severity, | |
| - Version version, | |
| - String scope, | |
| - String sourceHint, | |
| - InputLocationTracker tracker, | |
| - boolean isDependencyManagement) { | |
| - if (scope == null || scope.length() <= 0) { | |
| - return true; | |
| - } | |
| - | |
| - String[] validScopes; | |
| - if (isDependencyManagement) { | |
| - validScopes = new String[] {"provided", "compile", "runtime", "test", "system", "import"}; | |
| - } else { | |
| - validScopes = new String[] {"provided", "compile", "runtime", "test", "system"}; | |
| - } | |
| - | |
| - List<String> values = Arrays.asList(validScopes); | |
| - | |
| - if (values.contains(scope)) { | |
| - return true; | |
| - } | |
| - | |
| - // Provide a more helpful error message for the 'import' scope | |
| - if ("import".equals(scope) && !isDependencyManagement) { | |
| - addViolation( | |
| - problems, | |
| - severity, | |
| - version, | |
| - prefix + fieldName, | |
| - sourceHint, | |
| - "has scope 'import'. The 'import' scope is only valid in <dependencyManagement> sections.", | |
| - tracker); | |
| - } else { | |
| - addViolation( | |
| - problems, | |
| - severity, | |
| - version, | |
| - prefix + fieldName, | |
| - sourceHint, | |
| - "must be one of " + values + " but is '" + scope + "'.", | |
| - tracker); | |
| - } | |
| - | |
| - return false; | |
| - } | |
| - | |
| @SuppressWarnings("checkstyle:parameternumber") | |
| private boolean validateModelVersion( | |
| ModelProblemCollector problems, String string, InputLocationTracker tracker, String... validVersions) { | |
| diff --git a/compat/maven-model-builder/src/main/resources/org/apache/maven/model/pom-4.1.0.xml b/compat/maven-model-builder/src/main/resources/org/apache/maven/model/pom-4.1.0.xml | |
| index 754912f099..ff7738614f 100644 | |
| --- a/compat/maven-model-builder/src/main/resources/org/apache/maven/model/pom-4.1.0.xml | |
| +++ b/compat/maven-model-builder/src/main/resources/org/apache/maven/model/pom-4.1.0.xml | |
| @@ -20,10 +20,8 @@ under the License. | |
| --> | |
| <!-- START SNIPPET: superpom --> | |
| -<project xmlns="http://maven.apache.org/POM/4.1.0" | |
| - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| - xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 https://maven.apache.org/xsd/maven-4.1.0.xsd"> | |
| - <modelVersion>4.1.0</modelVersion> | |
| +<project> | |
| + <modelVersion>4.0.0</modelVersion> | |
| <properties> | |
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
| diff --git a/compat/maven-model-builder/src/main/resources/org/apache/maven/model/pom-4.2.0.xml b/compat/maven-model-builder/src/main/resources/org/apache/maven/model/pom-4.2.0.xml | |
| deleted file mode 100644 | |
| index 9b1b358f80..0000000000 | |
| --- a/compat/maven-model-builder/src/main/resources/org/apache/maven/model/pom-4.2.0.xml | |
| +++ /dev/null | |
| @@ -1,68 +0,0 @@ | |
| -<?xml version="1.0" encoding="UTF-8"?> | |
| - | |
| -<!-- | |
| -Licensed to the Apache Software Foundation (ASF) under one | |
| -or more contributor license agreements. See the NOTICE file | |
| -distributed with this work for additional information | |
| -regarding copyright ownership. The ASF licenses this file | |
| -to you under the Apache License, Version 2.0 (the | |
| -"License"); you may not use this file except in compliance | |
| -with the License. You may obtain a copy of the License at | |
| - | |
| - http://www.apache.org/licenses/LICENSE-2.0 | |
| - | |
| -Unless required by applicable law or agreed to in writing, | |
| -software distributed under the License is distributed on an | |
| -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| -KIND, either express or implied. See the License for the | |
| -specific language governing permissions and limitations | |
| -under the License. | |
| ---> | |
| - | |
| -<!-- START SNIPPET: superpom --> | |
| -<project xmlns="http://maven.apache.org/POM/4.2.0" | |
| - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| - xsi:schemaLocation="http://maven.apache.org/POM/4.2.0 https://maven.apache.org/xsd/maven-4.2.0.xsd"> | |
| - <modelVersion>4.2.0</modelVersion> | |
| - | |
| - <properties> | |
| - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
| - <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | |
| - <!-- Fixed date for reproducible build --> | |
| - <project.build.outputTimestamp>1980-02-01T00:00:00Z</project.build.outputTimestamp> | |
| - </properties> | |
| - | |
| - <build> | |
| - <directory>${project.basedir}/target</directory> | |
| - <outputDirectory>${project.build.directory}/classes</outputDirectory> | |
| - <finalName>${project.artifactId}-${project.version}</finalName> | |
| - <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory> | |
| - <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory> | |
| - <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory> | |
| - <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory> | |
| - <resources> | |
| - <resource> | |
| - <directory>${project.basedir}/src/main/resources</directory> | |
| - </resource> | |
| - <resource> | |
| - <directory>${project.basedir}/src/main/resources-filtered</directory> | |
| - <filtering>true</filtering> | |
| - </resource> | |
| - </resources> | |
| - <testResources> | |
| - <testResource> | |
| - <directory>${project.basedir}/src/test/resources</directory> | |
| - </testResource> | |
| - <testResource> | |
| - <directory>${project.basedir}/src/test/resources-filtered</directory> | |
| - <filtering>true</filtering> | |
| - </testResource> | |
| - </testResources> | |
| - </build> | |
| - | |
| - <reporting> | |
| - <outputDirectory>${project.build.directory}/site</outputDirectory> | |
| - </reporting> | |
| - | |
| -</project> | |
| -<!-- END SNIPPET: superpom --> | |
| diff --git a/compat/maven-model-builder/src/test/java/org/apache/maven/model/building/FileModelSourceTest.java b/compat/maven-model-builder/src/test/java/org/apache/maven/model/building/FileModelSourceTest.java | |
| index 9f5d43427f..a03184de6b 100644 | |
| --- a/compat/maven-model-builder/src/test/java/org/apache/maven/model/building/FileModelSourceTest.java | |
| +++ b/compat/maven-model-builder/src/test/java/org/apache/maven/model/building/FileModelSourceTest.java | |
| @@ -43,9 +43,9 @@ void testEquals() throws Exception { | |
| File tempFile = createTempFile("pomTest"); | |
| FileModelSource instance = new FileModelSource(tempFile); | |
| - assertFalse(instance.equals(null), "Expected " + instance + " to not equal " + null); | |
| + assertFalse(instance.equals(null)); | |
| assertFalse(instance.equals(new Object())); | |
| - assertTrue(instance.equals(instance), "Expected " + instance + " to equal " + instance); | |
| + assertTrue(instance.equals(instance)); | |
| assertTrue(instance.equals(new FileModelSource(tempFile))); | |
| } | |
| @@ -60,9 +60,7 @@ void testWindowsPaths() throws Exception { | |
| FileModelSource upperCaseFileSource = new FileModelSource(upperCaseFile); | |
| FileModelSource lowerCaseFileSource = new FileModelSource(lowerCaseFile); | |
| - assertTrue( | |
| - upperCaseFileSource.equals(lowerCaseFileSource), | |
| - "Expected " + upperCaseFileSource + " to equal " + lowerCaseFileSource); | |
| + assertTrue(upperCaseFileSource.equals(lowerCaseFileSource)); | |
| } | |
| private File createTempFile(String name) throws IOException { | |
| diff --git a/compat/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java b/compat/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java | |
| index 640579cb88..e5ad5b01d3 100644 | |
| --- a/compat/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java | |
| +++ b/compat/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java | |
| @@ -28,7 +28,8 @@ | |
| import org.apache.maven.model.v4.MavenMerger; | |
| import org.junit.jupiter.api.Test; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.hasItems; | |
| @Deprecated | |
| class FileToRawModelMergerTest { | |
| @@ -64,8 +65,6 @@ void testOverriddenMergeMethods() { | |
| .filter(m -> m.startsWith("merge")) | |
| .collect(Collectors.toList()); | |
| - assertTrue( | |
| - overriddenMethods.containsAll(methodNames), | |
| - "Expected overriddenMethods " + overriddenMethods + " to contain all methodNames " + methodNames); | |
| + assertThat(overriddenMethods, hasItems(methodNames.toArray(new String[0]))); | |
| } | |
| } | |
| diff --git a/compat/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java b/compat/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java | |
| index cf3e45267f..72d742a136 100644 | |
| --- a/compat/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java | |
| +++ b/compat/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java | |
| @@ -28,10 +28,9 @@ | |
| import org.apache.maven.model.io.ModelWriter; | |
| import org.junit.jupiter.api.BeforeEach; | |
| import org.junit.jupiter.api.Test; | |
| -import org.xmlunit.builder.DiffBuilder; | |
| -import org.xmlunit.diff.Diff; | |
| +import org.xmlunit.matchers.CompareMatcher; | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| import static org.junit.jupiter.api.Assertions.assertThrows; | |
| import static org.junit.jupiter.api.Assertions.assertTrue; | |
| @@ -191,12 +190,8 @@ public void testInheritance(String baseName, boolean fromRepo) throws IOExceptio | |
| // check with getPom( baseName + "-expected" ) | |
| File expected = getPom(baseName + "-expected"); | |
| - Diff diff = DiffBuilder.compare(expected) | |
| - .withTest(actual) | |
| - .ignoreComments() | |
| - .ignoreWhitespace() | |
| - .build(); | |
| - assertFalse(diff.hasDifferences(), "XML files should be identical: " + diff.toString()); | |
| + assertThat( | |
| + actual, CompareMatcher.isIdenticalTo(expected).ignoreComments().ignoreWhitespace()); | |
| } | |
| @Test | |
| @@ -216,11 +211,7 @@ void testModulePathNotArtifactId() throws IOException { | |
| // check with getPom( "module-path-not-artifactId-effective" ) | |
| File expected = getPom("module-path-not-artifactId-expected"); | |
| - Diff diff = DiffBuilder.compare(expected) | |
| - .withTest(actual) | |
| - .ignoreComments() | |
| - .ignoreWhitespace() | |
| - .build(); | |
| - assertFalse(diff.hasDifferences(), "XML files should be identical: " + diff.toString()); | |
| + assertThat( | |
| + actual, CompareMatcher.isIdenticalTo(expected).ignoreComments().ignoreWhitespace()); | |
| } | |
| } | |
| diff --git a/compat/maven-model-builder/src/test/java/org/apache/maven/model/profile/DefaultProfileSelectorTest.java b/compat/maven-model-builder/src/test/java/org/apache/maven/model/profile/DefaultProfileSelectorTest.java | |
| index a5ba09c686..84f5d4390a 100644 | |
| --- a/compat/maven-model-builder/src/test/java/org/apache/maven/model/profile/DefaultProfileSelectorTest.java | |
| +++ b/compat/maven-model-builder/src/test/java/org/apache/maven/model/profile/DefaultProfileSelectorTest.java | |
| @@ -64,8 +64,7 @@ public boolean presentInConfig( | |
| DefaultProfileActivationContext context = new DefaultProfileActivationContext(); | |
| SimpleProblemCollector problems = new SimpleProblemCollector(); | |
| List<Profile> active = selector.getActiveProfiles(profiles, context, problems); | |
| - assertTrue( | |
| - active.isEmpty(), "Expected collection to be empty but had " + active.size() + " elements: " + active); | |
| + assertTrue(active.isEmpty()); | |
| assertEquals(1, problems.getErrors().size()); | |
| assertEquals( | |
| "Failed to determine activation for profile one: BOOM", | |
| diff --git a/compat/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java b/compat/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java | |
| index a5f5d8548c..cdfa9caac1 100644 | |
| --- a/compat/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java | |
| +++ b/compat/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java | |
| @@ -267,18 +267,10 @@ void testMissingAll() throws Exception { | |
| List<String> messages = result.getErrors(); | |
| - assertTrue( | |
| - messages.contains("'modelVersion' is missing."), | |
| - "Expected " + messages + " to contain " + "'modelVersion' is missing."); | |
| - assertTrue( | |
| - messages.contains("'groupId' is missing."), | |
| - "Expected " + messages + " to contain " + "'groupId' is missing."); | |
| - assertTrue( | |
| - messages.contains("'artifactId' is missing."), | |
| - "Expected " + messages + " to contain " + "'artifactId' is missing."); | |
| - assertTrue( | |
| - messages.contains("'version' is missing."), | |
| - "Expected " + messages + " to contain " + "'version' is missing."); | |
| + assertTrue(messages.contains("'modelVersion' is missing.")); | |
| + assertTrue(messages.contains("'groupId' is missing.")); | |
| + assertTrue(messages.contains("'artifactId' is missing.")); | |
| + assertTrue(messages.contains("'version' is missing.")); | |
| // type is inherited from the super pom | |
| } | |
| @@ -363,10 +355,6 @@ void testBadDependencyScope() throws Exception { | |
| assertViolations(result, 0, 0, 2); | |
| assertTrue(result.getWarnings().get(0).contains("test:f")); | |
| - // Check that the import scope error message is more helpful | |
| - assertTrue(result.getWarnings() | |
| - .get(0) | |
| - .contains("has scope 'import'. The 'import' scope is only valid in <dependencyManagement> sections")); | |
| assertTrue(result.getWarnings().get(1).contains("test:g")); | |
| } | |
| diff --git a/compat/maven-model/pom.xml b/compat/maven-model/pom.xml | |
| index fc1eecff4b..772ddcec12 100644 | |
| --- a/compat/maven-model/pom.xml | |
| +++ b/compat/maven-model/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-model</artifactId> | |
| @@ -63,6 +63,11 @@ under the License. | |
| <artifactId>junit-jupiter-api</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| + <dependency> | |
| + <groupId>org.hamcrest</groupId> | |
| + <artifactId>hamcrest</artifactId> | |
| + <scope>test</scope> | |
| + </dependency> | |
| <dependency> | |
| <groupId>org.openjdk.jmh</groupId> | |
| <artifactId>jmh-core</artifactId> | |
| diff --git a/compat/maven-model/src/main/java/org/apache/maven/model/InputLocation.java b/compat/maven-model/src/main/java/org/apache/maven/model/InputLocation.java | |
| index 080f73f963..70ef9bb688 100644 | |
| --- a/compat/maven-model/src/main/java/org/apache/maven/model/InputLocation.java | |
| +++ b/compat/maven-model/src/main/java/org/apache/maven/model/InputLocation.java | |
| @@ -64,21 +64,10 @@ public final class InputLocation implements java.io.Serializable, Cloneable, Inp | |
| */ | |
| private InputLocation importedFrom; | |
| - /** | |
| - * Cached hashCode for performance. | |
| - */ | |
| - private volatile int hashCode = 0; | |
| - | |
| // ----------------/ | |
| // - Constructors -/ | |
| // ----------------/ | |
| - /** | |
| - * Creates a new InputLocation from an API model InputLocation. | |
| - * This constructor is used for converting between the API model and the compat model. | |
| - * | |
| - * @param location the API model InputLocation to convert from | |
| - */ | |
| public InputLocation(org.apache.maven.api.model.InputLocation location) { | |
| this.lineNumber = location.getLineNumber(); | |
| this.columnNumber = location.getColumnNumber(); | |
| @@ -148,10 +137,10 @@ public int getLineNumber() { | |
| } // -- int getLineNumber() | |
| /** | |
| - * Gets the InputLocation for a specific nested element key. | |
| * | |
| - * @param key the key to look up | |
| - * @return the InputLocation for the specified key, or null if not found | |
| + * | |
| + * @param key | |
| + * @return InputLocation | |
| */ | |
| @Override | |
| public InputLocation getLocation(Object key) { | |
| @@ -170,19 +159,19 @@ public InputLocation getLocation(Object key) { | |
| } // -- InputLocation getLocation( Object ) | |
| /** | |
| - * Gets the map of nested element locations within this location. | |
| * | |
| - * @return a map of keys to InputLocation instances for nested elements, or null if none | |
| + * | |
| + * @return Map | |
| */ | |
| public java.util.Map<Object, InputLocation> getLocations() { | |
| return locations; | |
| } // -- java.util.Map<Object, InputLocation> getLocations() | |
| /** | |
| - * Sets the InputLocation for a specific nested element key. | |
| * | |
| - * @param key the key to set the location for | |
| - * @param location the InputLocation to associate with the key | |
| + * | |
| + * @param key | |
| + * @param location | |
| */ | |
| @Override | |
| public void setLocation(Object key, InputLocation location) { | |
| @@ -203,11 +192,10 @@ public void setLocation(Object key, InputLocation location) { | |
| } // -- void setLocation( Object, InputLocation ) | |
| /** | |
| - * Sets the InputLocation for a specific nested element key in the locations map. | |
| - * This is a helper method that manages the internal locations map. | |
| * | |
| - * @param key the key to set the location for | |
| - * @param location the InputLocation to associate with the key | |
| + * | |
| + * @param key | |
| + * @param location | |
| */ | |
| public void setOtherLocation(Object key, InputLocation location) { | |
| if (location != null) { | |
| @@ -343,26 +331,20 @@ public void setLocations(java.util.Map<Object, InputLocation> locations) { | |
| this.locations = locations; | |
| } // -- void setLocations( java.util.Map ) | |
| - /** | |
| - * Converts this compat model InputLocation to an API model InputLocation. | |
| - * This method is used for converting between the compat model and the API model. | |
| - * | |
| - * @return the equivalent API model InputLocation | |
| - */ | |
| public org.apache.maven.api.model.InputLocation toApiLocation() { | |
| if (locations != null && locations.values().contains(this)) { | |
| if (locations.size() == 1 && locations.values().iterator().next() == this) { | |
| - return org.apache.maven.api.model.InputLocation.of( | |
| + return new org.apache.maven.api.model.InputLocation( | |
| lineNumber, | |
| columnNumber, | |
| source != null ? source.toApiSource() : null, | |
| locations.keySet().iterator().next()); | |
| } else { | |
| - return org.apache.maven.api.model.InputLocation.of( | |
| + return new org.apache.maven.api.model.InputLocation( | |
| lineNumber, columnNumber, source != null ? source.toApiSource() : null); | |
| } | |
| } else { | |
| - return org.apache.maven.api.model.InputLocation.of( | |
| + return new org.apache.maven.api.model.InputLocation( | |
| lineNumber, | |
| columnNumber, | |
| source != null ? source.toApiSource() : null, | |
| @@ -397,32 +379,6 @@ public abstract static class StringFormatter { | |
| public abstract String toString(InputLocation location); | |
| } | |
| - @Override | |
| - public boolean equals(Object o) { | |
| - if (this == o) { | |
| - return true; | |
| - } | |
| - if (o == null || getClass() != o.getClass()) { | |
| - return false; | |
| - } | |
| - InputLocation that = (InputLocation) o; | |
| - return lineNumber == that.lineNumber | |
| - && columnNumber == that.columnNumber | |
| - && java.util.Objects.equals(source, that.source) | |
| - && java.util.Objects.equals(locations, that.locations) | |
| - && java.util.Objects.equals(importedFrom, that.importedFrom); | |
| - } | |
| - | |
| - @Override | |
| - public int hashCode() { | |
| - int result = hashCode; | |
| - if (result == 0) { | |
| - result = java.util.Objects.hash(lineNumber, columnNumber, source, locations, importedFrom); | |
| - hashCode = result; | |
| - } | |
| - return result; | |
| - } | |
| - | |
| @Override | |
| public String toString() { | |
| return getLineNumber() + " : " + getColumnNumber() + ", " + getSource(); | |
| diff --git a/compat/maven-model/src/main/java/org/apache/maven/model/InputSource.java b/compat/maven-model/src/main/java/org/apache/maven/model/InputSource.java | |
| index 8e66eea476..1bd81e925e 100644 | |
| --- a/compat/maven-model/src/main/java/org/apache/maven/model/InputSource.java | |
| +++ b/compat/maven-model/src/main/java/org/apache/maven/model/InputSource.java | |
| @@ -58,26 +58,12 @@ public class InputSource implements java.io.Serializable, Cloneable { | |
| */ | |
| private InputLocation importedFrom; | |
| - /** | |
| - * Cached hashCode for performance. | |
| - */ | |
| - private volatile int hashCode = 0; | |
| - | |
| // ----------------/ | |
| // - Constructors -/ | |
| // ----------------/ | |
| - /** | |
| - * Default constructor for InputSource. | |
| - */ | |
| public InputSource() {} | |
| - /** | |
| - * Creates a new InputSource from an API model InputSource. | |
| - * This constructor is used for converting between the API model and the compat model. | |
| - * | |
| - * @param source the API model InputSource to convert from | |
| - */ | |
| public InputSource(org.apache.maven.api.model.InputSource source) { | |
| this.modelId = source.getModelId(); | |
| this.location = source.getLocation(); | |
| @@ -143,10 +129,9 @@ public void setModelId(String modelId) { | |
| } // -- void setModelId( String ) | |
| /** | |
| - * Get the location of the POM from which this POM was imported from. | |
| - * Can return {@code null} if this POM was not imported. | |
| + * Get the location of the POM from which this POM was | |
| * | |
| - * @return the InputLocation where this POM was imported from, or null if not imported | |
| + * @return | |
| */ | |
| public InputLocation getImportedFrom() { | |
| return importedFrom; | |
| @@ -155,48 +140,18 @@ public InputLocation getImportedFrom() { | |
| /** | |
| * Set the location of the POM from which this POM was imported from. | |
| * | |
| - * @param importedFrom the InputLocation where this POM was imported from, or null if not imported | |
| + * @param importedFrom | |
| */ | |
| public void setImportedFrom(InputLocation importedFrom) { | |
| this.importedFrom = importedFrom; | |
| } | |
| - @Override | |
| - public boolean equals(Object o) { | |
| - if (this == o) { | |
| - return true; | |
| - } | |
| - if (o == null || getClass() != o.getClass()) { | |
| - return false; | |
| - } | |
| - InputSource that = (InputSource) o; | |
| - return java.util.Objects.equals(modelId, that.modelId) | |
| - && java.util.Objects.equals(location, that.location) | |
| - && java.util.Objects.equals(importedFrom, that.importedFrom); | |
| - } | |
| - | |
| - @Override | |
| - public int hashCode() { | |
| - int result = hashCode; | |
| - if (result == 0) { | |
| - result = java.util.Objects.hash(modelId, location, importedFrom); | |
| - hashCode = result; | |
| - } | |
| - return result; | |
| - } | |
| - | |
| @Override | |
| public String toString() { | |
| return getModelId() + " " + getLocation(); | |
| } | |
| - /** | |
| - * Converts this compat model InputSource to an API model InputSource. | |
| - * This method is used for converting between the compat model and the API model. | |
| - * | |
| - * @return the equivalent API model InputSource | |
| - */ | |
| public org.apache.maven.api.model.InputSource toApiSource() { | |
| - return org.apache.maven.api.model.InputSource.of(modelId, location); | |
| + return new org.apache.maven.api.model.InputSource(modelId, location); | |
| } | |
| } | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ActivationFileTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ActivationFileTest.java | |
| index bba906b8a6..5f5dcd1876 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ActivationFileTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ActivationFileTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| ActivationFile thing = new ActivationFile(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ActivationOSTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ActivationOSTest.java | |
| index 7d5777a413..5ca7bec65e 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ActivationOSTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ActivationOSTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| ActivationOS thing = new ActivationOS(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ActivationPropertyTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ActivationPropertyTest.java | |
| index 54f0ea8f76..32b69dc046 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ActivationPropertyTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ActivationPropertyTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| ActivationProperty thing = new ActivationProperty(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ActivationTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ActivationTest.java | |
| index 13c58db2b5..545aab5a78 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ActivationTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ActivationTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Activation thing = new Activation(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/BuildTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/BuildTest.java | |
| index bb1e74f822..bd78314954 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/BuildTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/BuildTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Build thing = new Build(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/CiManagementTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/CiManagementTest.java | |
| index 4b24446627..71a402747b 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/CiManagementTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/CiManagementTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| CiManagement thing = new CiManagement(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ContributorTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ContributorTest.java | |
| index eca3b4cb0a..f6ddcc4699 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ContributorTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ContributorTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Contributor thing = new Contributor(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/DependencyManagementTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/DependencyManagementTest.java | |
| index 2cfa2a7f0d..1a32e0e8e3 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/DependencyManagementTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/DependencyManagementTest.java | |
| @@ -46,7 +46,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| DependencyManagement thing = new DependencyManagement(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/DependencyTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/DependencyTest.java | |
| index 8a82a302f6..39d7bb30d7 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/DependencyTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/DependencyTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Dependency thing = new Dependency(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/DeploymentRepositoryTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/DeploymentRepositoryTest.java | |
| index 6c9820c8bb..8b25cc6263 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/DeploymentRepositoryTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/DeploymentRepositoryTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| DeploymentRepository thing = new DeploymentRepository(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/DeveloperTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/DeveloperTest.java | |
| index 90d870623a..b6897aea37 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/DeveloperTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/DeveloperTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Developer thing = new Developer(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/DistributionManagementTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/DistributionManagementTest.java | |
| index e4c6d6ba2c..18c57a8c90 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/DistributionManagementTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/DistributionManagementTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| DistributionManagement thing = new DistributionManagement(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ExclusionTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ExclusionTest.java | |
| index 5b7cc96537..625f20ec2c 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ExclusionTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ExclusionTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Exclusion thing = new Exclusion(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ExtensionTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ExtensionTest.java | |
| index 98d49f93ed..3afa12c8ec 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ExtensionTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ExtensionTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Extension thing = new Extension(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/IssueManagementTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/IssueManagementTest.java | |
| index 634636c66f..a6905a28be 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/IssueManagementTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/IssueManagementTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| IssueManagement thing = new IssueManagement(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/LicenseTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/LicenseTest.java | |
| index 31d2f95a49..270993c20b 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/LicenseTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/LicenseTest.java | |
| @@ -46,7 +46,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| License thing = new License(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/MailingListTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/MailingListTest.java | |
| index 1ab66b6f05..c758c7e76e 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/MailingListTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/MailingListTest.java | |
| @@ -46,7 +46,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| MailingList thing = new MailingList(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/NotifierTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/NotifierTest.java | |
| index c2c25ee805..33f1c139d9 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/NotifierTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/NotifierTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Notifier thing = new Notifier(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/OrganizationTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/OrganizationTest.java | |
| index 14e499cb4e..62e51a1608 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/OrganizationTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/OrganizationTest.java | |
| @@ -46,7 +46,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Organization thing = new Organization(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ParentTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ParentTest.java | |
| index 552b29a372..79f33785ba 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ParentTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ParentTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Parent thing = new Parent(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/PluginConfigurationTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/PluginConfigurationTest.java | |
| index 304ec91e9f..996bf56bd8 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/PluginConfigurationTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/PluginConfigurationTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| PluginConfiguration thing = new PluginConfiguration(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/PluginContainerTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/PluginContainerTest.java | |
| index e7e1cbdf73..bc4c61404e 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/PluginContainerTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/PluginContainerTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| PluginContainer thing = new PluginContainer(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/PluginExecutionTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/PluginExecutionTest.java | |
| index 0a4a6c7008..110ed253d7 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/PluginExecutionTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/PluginExecutionTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| PluginExecution thing = new PluginExecution(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/PluginManagementTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/PluginManagementTest.java | |
| index 1038725ad7..c657890a95 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/PluginManagementTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/PluginManagementTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| PluginManagement thing = new PluginManagement(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/PluginTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/PluginTest.java | |
| index 8bf07fe4f5..c023199854 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/PluginTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/PluginTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Plugin thing = new Plugin(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/PrerequisitesTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/PrerequisitesTest.java | |
| index 2e4e965842..c886fd86a3 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/PrerequisitesTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/PrerequisitesTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Prerequisites thing = new Prerequisites(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ProfileTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ProfileTest.java | |
| index 13ad3b208e..aa8b0dbc95 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ProfileTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ProfileTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Profile thing = new Profile(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/RelocationTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/RelocationTest.java | |
| index 751cbbdcad..9956b12a92 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/RelocationTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/RelocationTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Relocation thing = new Relocation(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ReportPluginTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ReportPluginTest.java | |
| index 8562c67dee..37f0acf336 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ReportPluginTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ReportPluginTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| ReportPlugin thing = new ReportPlugin(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ReportSetTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ReportSetTest.java | |
| index 4403c7488b..7314675b26 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ReportSetTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ReportSetTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| ReportSet thing = new ReportSet(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ReportingTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ReportingTest.java | |
| index 0ba2195c00..8d3d7d93ac 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ReportingTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ReportingTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Reporting thing = new Reporting(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/RepositoryPolicyTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/RepositoryPolicyTest.java | |
| index 01236ee1f8..24b9e049a4 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/RepositoryPolicyTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/RepositoryPolicyTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| RepositoryPolicy thing = new RepositoryPolicy(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/RepositoryTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/RepositoryTest.java | |
| index e97699ba50..afcc13b88d 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/RepositoryTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/RepositoryTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Repository thing = new Repository(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ResourceTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ResourceTest.java | |
| index 9382da4f2f..7ed52946a6 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ResourceTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ResourceTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Resource thing = new Resource(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/ScmTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/ScmTest.java | |
| index a14f2a6077..0dde84e4a9 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/ScmTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/ScmTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Scm thing = new Scm(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/SiteTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/SiteTest.java | |
| index a01ae688e1..41565017b3 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/SiteTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/SiteTest.java | |
| @@ -45,7 +45,7 @@ void testEqualsNullSafe() { | |
| @Test | |
| void testEqualsIdentity() { | |
| Site thing = new Site(); | |
| - assertTrue(thing.equals(thing), "Expected " + thing + " to equal " + thing); | |
| + assertTrue(thing.equals(thing)); | |
| } | |
| @Test | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/merge/MavenMergerTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/merge/MavenMergerTest.java | |
| index f2d9767259..92c8c55122 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/merge/MavenMergerTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/merge/MavenMergerTest.java | |
| @@ -26,8 +26,9 @@ | |
| import org.apache.maven.model.v4.MavenMerger; | |
| import org.junit.jupiter.api.Test; | |
| -import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.contains; | |
| +import static org.hamcrest.Matchers.is; | |
| /** | |
| * MavenMerger is based on same instances, subclasses should override KeyComputer per type | |
| @@ -42,16 +43,10 @@ void mergeArtifactId() { | |
| Model source = Model.newBuilder().artifactId("SOURCE").build(); | |
| Model merged = mavenMerger.merge(target, source, true, null); | |
| - assertEquals( | |
| - "SOURCE", | |
| - merged.getArtifactId(), | |
| - "Expected merged artifactId to be SOURCE but was " + merged.getArtifactId()); | |
| + assertThat(merged.getArtifactId(), is("SOURCE")); | |
| merged = mavenMerger.merge(target, source, false, null); | |
| - assertEquals( | |
| - "TARGET", | |
| - merged.getArtifactId(), | |
| - "Expected merged artifactId to be TARGET but was " + merged.getArtifactId()); | |
| + assertThat(merged.getArtifactId(), is("TARGET")); | |
| } | |
| @Test | |
| @@ -67,10 +62,7 @@ void mergeSameContributors() { | |
| Model merged = mavenMerger.merge(target, source, true, null); | |
| - assertEquals(1, merged.getContributors().size(), "Expected exactly 1 contributor"); | |
| - assertTrue( | |
| - merged.getContributors().contains(contributor), | |
| - "Expected contributors to contain " + contributor + " but was " + merged.getContributors()); | |
| + assertThat(merged.getContributors(), contains(contributor)); | |
| } | |
| @Test | |
| @@ -89,9 +81,6 @@ void mergeSameDependencies() { | |
| Model merged = mavenMerger.merge(target, source, true, null); | |
| - assertEquals(1, merged.getDependencies().size(), "Expected exactly 1 dependency"); | |
| - assertTrue( | |
| - merged.getDependencies().contains(dependency), | |
| - "Expected dependencies to contain " + dependency + " but was " + merged.getDependencies()); | |
| + assertThat(merged.getDependencies(), contains(dependency)); | |
| } | |
| } | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/v4/ModelXmlTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/v4/ModelXmlTest.java | |
| index 048c17cfe1..b7d17e808d 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/v4/ModelXmlTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/v4/ModelXmlTest.java | |
| @@ -83,7 +83,7 @@ void testNamespaceInXmlNode() throws XMLStreamException { | |
| assertEquals("", myConfig.prefix()); | |
| assertEquals("myConfig", myConfig.name()); | |
| String config = node.toString(); | |
| - assertFalse(config.isEmpty(), "Expected collection to not be empty but was empty"); | |
| + assertFalse(config.isEmpty()); | |
| } | |
| String toXml(Model model) throws IOException, XMLStreamException { | |
| diff --git a/compat/maven-model/src/test/java/org/apache/maven/model/v4/Xpp3DomPerfTest.java b/compat/maven-model/src/test/java/org/apache/maven/model/v4/Xpp3DomPerfTest.java | |
| index 131a152ddc..090292cffa 100644 | |
| --- a/compat/maven-model/src/test/java/org/apache/maven/model/v4/Xpp3DomPerfTest.java | |
| +++ b/compat/maven-model/src/test/java/org/apache/maven/model/v4/Xpp3DomPerfTest.java | |
| @@ -73,7 +73,7 @@ public int readWithStax(AdditionState state) throws IOException, XMLStreamExcept | |
| try (InputStream is = Files.newInputStream(pom)) { | |
| MavenStaxReader reader = new MavenStaxReader(); | |
| reader.setAddLocationInformation(false); | |
| - reader.read(is, true, InputSource.of("id", pom.toString())); | |
| + reader.read(is, true, new InputSource("id", pom.toString())); | |
| i++; | |
| } catch (XMLStreamException e) { | |
| throw new RuntimeException("Error parsing: " + pom, e); | |
| diff --git a/compat/maven-plugin-api/pom.xml b/compat/maven-plugin-api/pom.xml | |
| index 6bd39596de..dffdb05609 100644 | |
| --- a/compat/maven-plugin-api/pom.xml | |
| +++ b/compat/maven-plugin-api/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-plugin-api</artifactId> | |
| diff --git a/compat/maven-plugin-api/src/test/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilderTest.java b/compat/maven-plugin-api/src/test/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilderTest.java | |
| index 5b4eeaa284..f9839369e2 100644 | |
| --- a/compat/maven-plugin-api/src/test/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilderTest.java | |
| +++ b/compat/maven-plugin-api/src/test/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilderTest.java | |
| @@ -54,8 +54,8 @@ void testBuildReader() throws Exception { | |
| assertEquals("2.3-SNAPSHOT", pd.getVersion()); | |
| assertEquals("jar", pd.getGoalPrefix()); | |
| assertEquals("plugin-description", pd.getDescription()); | |
| - assertFalse(pd.isIsolatedRealm(), "Expected " + pd + ".isIsolatedRealm() to return false"); | |
| - assertTrue(pd.isInheritedByDefault(), "Expected " + pd + ".isInheritedByDefault() to return true"); | |
| + assertFalse(pd.isIsolatedRealm()); | |
| + assertTrue(pd.isInheritedByDefault()); | |
| assertEquals(2, pd.getMojos().size()); | |
| assertEquals(1, pd.getDependencies().size()); | |
| @@ -65,12 +65,12 @@ void testBuildReader() throws Exception { | |
| assertEquals("mojo-description", md.getDescription()); | |
| assertEquals("runtime", md.getDependencyResolutionRequired()); | |
| assertEquals("test", md.getDependencyCollectionRequired()); | |
| - assertFalse(md.isAggregator(), "Expected " + md + ".isAggregator() to return false"); | |
| - assertFalse(md.isDirectInvocationOnly(), "Expected " + md + ".isDirectInvocationOnly() to return false"); | |
| - assertTrue(md.isInheritedByDefault(), "Expected " + md + ".isInheritedByDefault() to return true"); | |
| - assertFalse(md.isOnlineRequired(), "Expected " + md + ".isOnlineRequired() to return false"); | |
| - assertTrue(md.isProjectRequired(), "Expected " + md + ".isProjectRequired() to return true"); | |
| - assertFalse(md.isThreadSafe(), "Expected " + md + ".isThreadSafe() to return false"); | |
| + assertFalse(md.isAggregator()); | |
| + assertFalse(md.isDirectInvocationOnly()); | |
| + assertTrue(md.isInheritedByDefault()); | |
| + assertFalse(md.isOnlineRequired()); | |
| + assertTrue(md.isProjectRequired()); | |
| + assertFalse(md.isThreadSafe()); | |
| assertEquals("package", md.getPhase()); | |
| assertEquals("org.apache.maven.plugin.jar.JarMojo", md.getImplementation()); | |
| assertEquals("antrun", md.getComponentConfigurator()); | |
| @@ -99,8 +99,8 @@ void testBuildReader() throws Exception { | |
| assertEquals("jarName", mp.getAlias()); | |
| assertEquals("java.lang.String", mp.getType()); | |
| assertEquals("java.lang.String", mp.getImplementation()); | |
| - assertTrue(mp.isEditable(), "Expected " + mp + ".isEditable() to return true"); | |
| - assertFalse(mp.isRequired(), "Expected " + mp + ".isRequired() to return false"); | |
| + assertTrue(mp.isEditable()); | |
| + assertFalse(mp.isRequired()); | |
| assertEquals("parameter-description", mp.getDescription()); | |
| assertEquals("deprecated-parameter", mp.getDeprecated()); | |
| assertEquals("${jar.finalName}", mp.getExpression()); | |
| @@ -125,6 +125,6 @@ void testBuildReader() throws Exception { | |
| assertEquals("war", md.getGoal()); | |
| assertNull(md.getDependencyResolutionRequired()); | |
| assertNull(md.getDependencyCollectionRequired()); | |
| - assertTrue(md.isThreadSafe(), "Expected " + md + ".isThreadSafe() to return true"); | |
| + assertTrue(md.isThreadSafe()); | |
| } | |
| } | |
| diff --git a/compat/maven-repository-metadata/pom.xml b/compat/maven-repository-metadata/pom.xml | |
| index 3a6151f4b9..bb12e5216b 100644 | |
| --- a/compat/maven-repository-metadata/pom.xml | |
| +++ b/compat/maven-repository-metadata/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-repository-metadata</artifactId> | |
| diff --git a/compat/maven-resolver-provider/pom.xml b/compat/maven-resolver-provider/pom.xml | |
| index 28ba5230de..79574d50d7 100644 | |
| --- a/compat/maven-resolver-provider/pom.xml | |
| +++ b/compat/maven-resolver-provider/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-resolver-provider</artifactId> | |
| diff --git a/compat/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/RepositorySystemTest.java b/compat/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/RepositorySystemTest.java | |
| index a8547b58eb..ce33186a73 100644 | |
| --- a/compat/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/RepositorySystemTest.java | |
| +++ b/compat/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/RepositorySystemTest.java | |
| @@ -73,7 +73,7 @@ void testReadArtifactDescriptor() throws Exception { | |
| */ | |
| private void checkUtSimpleArtifactDependencies(Dependency dep1, Dependency dep2) { | |
| assertEquals("compile", dep1.getScope()); | |
| - assertFalse(dep1.isOptional(), "Expected " + dep1 + ".isOptional() to return false"); | |
| + assertFalse(dep1.isOptional()); | |
| assertEquals(0, dep1.getExclusions().size()); | |
| Artifact depArtifact = dep1.getArtifact(); | |
| assertEquals("ut.simple", depArtifact.getGroupId()); | |
| @@ -81,7 +81,7 @@ private void checkUtSimpleArtifactDependencies(Dependency dep1, Dependency dep2) | |
| assertEquals("1.0", depArtifact.getVersion()); | |
| assertEquals("1.0", depArtifact.getBaseVersion()); | |
| assertNull(depArtifact.getFile()); | |
| - assertFalse(depArtifact.isSnapshot(), "Expected " + depArtifact + ".isSnapshot() to return false"); | |
| + assertFalse(depArtifact.isSnapshot()); | |
| assertEquals("", depArtifact.getClassifier()); | |
| assertEquals("jar", depArtifact.getExtension()); | |
| assertEquals("java", depArtifact.getProperty("language", null)); | |
| @@ -91,7 +91,7 @@ private void checkUtSimpleArtifactDependencies(Dependency dep1, Dependency dep2) | |
| assertEquals(4, depArtifact.getProperties().size()); | |
| assertEquals("compile", dep2.getScope()); | |
| - assertFalse(dep2.isOptional(), "Expected " + dep2 + ".isOptional() to return false"); | |
| + assertFalse(dep2.isOptional()); | |
| assertEquals(0, dep2.getExclusions().size()); | |
| depArtifact = dep2.getArtifact(); | |
| assertEquals("ut.simple", depArtifact.getGroupId()); | |
| @@ -99,7 +99,7 @@ private void checkUtSimpleArtifactDependencies(Dependency dep1, Dependency dep2) | |
| assertEquals("1.0", depArtifact.getVersion()); | |
| assertEquals("1.0", depArtifact.getBaseVersion()); | |
| assertNull(depArtifact.getFile()); | |
| - assertFalse(depArtifact.isSnapshot(), "Expected " + depArtifact + ".isSnapshot() to return false"); | |
| + assertFalse(depArtifact.isSnapshot()); | |
| assertEquals("sources", depArtifact.getClassifier()); | |
| assertEquals("jar", depArtifact.getExtension()); | |
| assertEquals("java", depArtifact.getProperty("language", null)); | |
| @@ -152,8 +152,8 @@ void testResolveArtifact() throws Exception { | |
| } | |
| private void checkArtifactResult(ArtifactResult result, String filename) { | |
| - assertFalse(result.isMissing(), "Expected " + result + ".isMissing() to return false"); | |
| - assertTrue(result.isResolved(), "Expected " + result + ".isResolved() to return true"); | |
| + assertFalse(result.isMissing()); | |
| + assertTrue(result.isResolved()); | |
| Artifact artifact = result.getArtifact(); | |
| assertNotNull(artifact.getFile()); | |
| assertEquals(filename, artifact.getFile().getName()); | |
| diff --git a/compat/maven-settings-builder/pom.xml b/compat/maven-settings-builder/pom.xml | |
| index 24e62ee656..dc7806e20a 100644 | |
| --- a/compat/maven-settings-builder/pom.xml | |
| +++ b/compat/maven-settings-builder/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-settings-builder</artifactId> | |
| diff --git a/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java b/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java | |
| index 140393bf06..051b8f4472 100644 | |
| --- a/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java | |
| +++ b/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java | |
| @@ -105,7 +105,7 @@ public SettingsBuildingResult build(SettingsBuildingRequest request) throws Sett | |
| // for the special case of a drive-relative Windows path, make sure it's absolute to save plugins from trouble | |
| String localRepository = userSettings.getLocalRepository(); | |
| - if (localRepository != null && !localRepository.isEmpty()) { | |
| + if (localRepository != null && localRepository.length() > 0) { | |
| File file = new File(localRepository); | |
| if (!file.isAbsolute() && file.getPath().startsWith(File.separator)) { | |
| userSettings.setLocalRepository(file.getAbsolutePath()); | |
| diff --git a/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsProblem.java b/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsProblem.java | |
| index e245a63839..e4cbc82674 100644 | |
| --- a/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsProblem.java | |
| +++ b/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsProblem.java | |
| @@ -81,21 +81,21 @@ public String getLocation() { | |
| StringBuilder buffer = new StringBuilder(256); | |
| if (!getSource().isEmpty()) { | |
| - if (!buffer.isEmpty()) { | |
| + if (buffer.length() > 0) { | |
| buffer.append(", "); | |
| } | |
| buffer.append(getSource()); | |
| } | |
| if (getLineNumber() > 0) { | |
| - if (!buffer.isEmpty()) { | |
| + if (buffer.length() > 0) { | |
| buffer.append(", "); | |
| } | |
| buffer.append("line ").append(getLineNumber()); | |
| } | |
| if (getColumnNumber() > 0) { | |
| - if (!buffer.isEmpty()) { | |
| + if (buffer.length() > 0) { | |
| buffer.append(", "); | |
| } | |
| buffer.append("column ").append(getColumnNumber()); | |
| diff --git a/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java b/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java | |
| index db54b50234..f4ea4bdf4c 100644 | |
| --- a/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java | |
| +++ b/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java | |
| @@ -49,7 +49,7 @@ public Settings read(File input, Map<String, ?> options) throws IOException { | |
| Objects.requireNonNull(input, "input cannot be null"); | |
| try (InputStream in = Files.newInputStream(input.toPath())) { | |
| - InputSource source = InputSource.of(input.toString()); | |
| + InputSource source = new InputSource(input.toString()); | |
| return new Settings(new SettingsStaxReader().read(in, isStrict(options), source)); | |
| } catch (XMLStreamException e) { | |
| throw new SettingsParseException( | |
| diff --git a/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java b/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java | |
| index f1913e00de..6df108748c 100644 | |
| --- a/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java | |
| +++ b/compat/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java | |
| @@ -223,7 +223,7 @@ private static boolean validateStringNotEmpty( | |
| return false; | |
| } | |
| - if (!string.isEmpty()) { | |
| + if (string.length() > 0) { | |
| return true; | |
| } | |
| diff --git a/compat/maven-settings-builder/src/test/resources/settings/factory/simple.xml b/compat/maven-settings-builder/src/test/resources/settings/factory/simple.xml | |
| index abcda726c7..ea664bacdf 100644 | |
| --- a/compat/maven-settings-builder/src/test/resources/settings/factory/simple.xml | |
| +++ b/compat/maven-settings-builder/src/test/resources/settings/factory/simple.xml | |
| @@ -19,6 +19,6 @@ specific language governing permissions and limitations | |
| under the License. | |
| --> | |
| -<settings xmlns='http://maven.apache.org/SETTINGS/1.0.0'> | |
| +<settings> | |
| <localRepository>${user.home}/.m2/repository</localRepository> | |
| </settings> | |
| diff --git a/compat/maven-settings/pom.xml b/compat/maven-settings/pom.xml | |
| index 6aaa0e4e42..3a825e9ddc 100644 | |
| --- a/compat/maven-settings/pom.xml | |
| +++ b/compat/maven-settings/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-settings</artifactId> | |
| diff --git a/compat/maven-toolchain-builder/pom.xml b/compat/maven-toolchain-builder/pom.xml | |
| index e5e8916c90..635a58d7ea 100644 | |
| --- a/compat/maven-toolchain-builder/pom.xml | |
| +++ b/compat/maven-toolchain-builder/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-toolchain-builder</artifactId> | |
| diff --git a/compat/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsReader.java b/compat/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsReader.java | |
| index 191adcd111..3e0665b57c 100644 | |
| --- a/compat/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsReader.java | |
| +++ b/compat/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsReader.java | |
| @@ -50,7 +50,7 @@ public PersistedToolchains read(File input, Map<String, ?> options) throws IOExc | |
| Objects.requireNonNull(input, "input cannot be null"); | |
| try (InputStream in = Files.newInputStream(input.toPath())) { | |
| - InputSource source = InputSource.of(input.toString()); | |
| + InputSource source = new InputSource(input.toString()); | |
| return new PersistedToolchains(new MavenToolchainsStaxReader().read(in, isStrict(options), source)); | |
| } catch (XMLStreamException e) { | |
| throw new ToolchainsParseException( | |
| diff --git a/compat/maven-toolchain-model/pom.xml b/compat/maven-toolchain-model/pom.xml | |
| index 218bdbed07..8f309312c8 100644 | |
| --- a/compat/maven-toolchain-model/pom.xml | |
| +++ b/compat/maven-toolchain-model/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-compat-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-toolchain-model</artifactId> | |
| diff --git a/compat/pom.xml b/compat/pom.xml | |
| index bfa23c8cb1..3032d65a4d 100644 | |
| --- a/compat/pom.xml | |
| +++ b/compat/pom.xml | |
| @@ -22,7 +22,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-compat-modules</artifactId> | |
| diff --git a/doap_Maven.rdf b/doap_Maven.rdf | |
| index 859f72d2f0..525ab5fdd5 100644 | |
| --- a/doap_Maven.rdf | |
| +++ b/doap_Maven.rdf | |
| @@ -99,17 +99,6 @@ under the License. | |
| <release> | |
| <Version> | |
| <name>Latest stable release</name> | |
| - <created>2025-07-12</created> | |
| - <revision>3.9.11</revision> | |
| - <file-release>https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.zip</file-release> | |
| - <file-release>https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.tar.gz</file-release> | |
| - <file-release>https://archive.apache.org/dist/maven/maven-3/3.9.11/source/apache-maven-3.9.11-src.zip</file-release> | |
| - <file-release>https://archive.apache.org/dist/maven/maven-3/3.9.11/source/apache-maven-3.9.11-src.tar.gz</file-release> | |
| - </Version> | |
| - </release> | |
| - <release> | |
| - <Version> | |
| - <name>Apache Maven 3.9.10</name> | |
| <created>2025-06-01</created> | |
| <revision>3.9.10</revision> | |
| <file-release>https://archive.apache.org/dist/maven/maven-3/3.9.10/binaries/apache-maven-3.9.10-bin.zip</file-release> | |
| @@ -117,8 +106,6 @@ under the License. | |
| <file-release>https://archive.apache.org/dist/maven/maven-3/3.9.10/source/apache-maven-3.9.10-src.zip</file-release> | |
| <file-release>https://archive.apache.org/dist/maven/maven-3/3.9.10/source/apache-maven-3.9.10-src.tar.gz</file-release> | |
| </Version> | |
| - </release> | |
| - <release> | |
| <Version> | |
| <name>Apache Maven 3.9.9</name> | |
| <created>2024-08-17</created> | |
| diff --git a/impl/maven-cli/pom.xml b/impl/maven-cli/pom.xml | |
| index 14af725619..4046a6c543 100644 | |
| --- a/impl/maven-cli/pom.xml | |
| +++ b/impl/maven-cli/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-impl-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-cli</artifactId> | |
| @@ -235,14 +235,15 @@ under the License. | |
| <artifactId>jline-native</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| - <dependency> | |
| - <groupId>eu.maveniverse.maven.mimir</groupId> | |
| - <artifactId>testing</artifactId> | |
| - <scope>test</scope> | |
| - </dependency> | |
| </dependencies> | |
| <build> | |
| + <testResources> | |
| + <testResource> | |
| + <filtering>true</filtering> | |
| + <directory>src/test/resources-filtered</directory> | |
| + </testResource> | |
| + </testResources> | |
| <plugins> | |
| <plugin> | |
| <groupId>org.apache.maven.plugins</groupId> | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/BaseParser.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/BaseParser.java | |
| index b44377b7f3..c93150c61e 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/BaseParser.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/BaseParser.java | |
| @@ -465,6 +465,9 @@ protected Map<String, String> populateUserProperties(LocalContext context) { | |
| throw new IllegalStateException("Error loading properties from " + propertiesFile, e); | |
| } | |
| + // Warn about deprecated maven.properties files | |
| + warnAboutDeprecatedPropertiesFiles(context); | |
| + | |
| // CLI specified properties are most dominant | |
| userProperties.putAll(userSpecifiedProperties); | |
| @@ -486,21 +489,21 @@ protected List<CoreExtensions> readCoreExtensionsDescriptor(LocalContext context | |
| // project | |
| file = context.cwd.resolve(eff.get(Constants.MAVEN_PROJECT_EXTENSIONS)); | |
| - loaded = readCoreExtensionsDescriptorFromFile(file, false); | |
| + loaded = readCoreExtensionsDescriptorFromFile(file); | |
| if (!loaded.isEmpty()) { | |
| result.add(new CoreExtensions(file, loaded)); | |
| } | |
| // user | |
| file = context.userHomeDirectory.resolve(eff.get(Constants.MAVEN_USER_EXTENSIONS)); | |
| - loaded = readCoreExtensionsDescriptorFromFile(file, true); | |
| + loaded = readCoreExtensionsDescriptorFromFile(file); | |
| if (!loaded.isEmpty()) { | |
| result.add(new CoreExtensions(file, loaded)); | |
| } | |
| // installation | |
| file = context.installationDirectory.resolve(eff.get(Constants.MAVEN_INSTALLATION_EXTENSIONS)); | |
| - loaded = readCoreExtensionsDescriptorFromFile(file, true); | |
| + loaded = readCoreExtensionsDescriptorFromFile(file); | |
| if (!loaded.isEmpty()) { | |
| result.add(new CoreExtensions(file, loaded)); | |
| } | |
| @@ -508,16 +511,15 @@ protected List<CoreExtensions> readCoreExtensionsDescriptor(LocalContext context | |
| return result.isEmpty() ? null : List.copyOf(result); | |
| } | |
| - protected List<CoreExtension> readCoreExtensionsDescriptorFromFile(Path extensionsFile, boolean allowMetaVersions) { | |
| + protected List<CoreExtension> readCoreExtensionsDescriptorFromFile(Path extensionsFile) { | |
| try { | |
| if (extensionsFile != null && Files.exists(extensionsFile)) { | |
| try (InputStream is = Files.newInputStream(extensionsFile)) { | |
| return validateCoreExtensionsDescriptorFromFile( | |
| extensionsFile, | |
| List.copyOf(new CoreExtensionsStaxReader() | |
| - .read(is, true, InputSource.of(extensionsFile.toString())) | |
| - .getExtensions()), | |
| - allowMetaVersions); | |
| + .read(is, true, new InputSource(extensionsFile.toString())) | |
| + .getExtensions())); | |
| } | |
| } | |
| return List.of(); | |
| @@ -527,37 +529,23 @@ protected List<CoreExtension> readCoreExtensionsDescriptorFromFile(Path extensio | |
| } | |
| protected List<CoreExtension> validateCoreExtensionsDescriptorFromFile( | |
| - Path extensionFile, List<CoreExtension> coreExtensions, boolean allowMetaVersions) { | |
| + Path extensionFile, List<CoreExtension> coreExtensions) { | |
| Map<String, List<InputLocation>> gasLocations = new HashMap<>(); | |
| - Map<String, List<InputLocation>> metaVersionLocations = new HashMap<>(); | |
| for (CoreExtension coreExtension : coreExtensions) { | |
| String ga = coreExtension.getGroupId() + ":" + coreExtension.getArtifactId(); | |
| InputLocation location = coreExtension.getLocation(""); | |
| gasLocations.computeIfAbsent(ga, k -> new ArrayList<>()).add(location); | |
| - // TODO: metaversions could be extensible enum with these two values out of the box | |
| - if ("LATEST".equals(coreExtension.getVersion()) || "RELEASE".equals(coreExtension.getVersion())) { | |
| - metaVersionLocations.computeIfAbsent(ga, k -> new ArrayList<>()).add(location); | |
| - } | |
| } | |
| - if (gasLocations.values().stream().anyMatch(l -> l.size() > 1)) { | |
| - throw new IllegalStateException("Extension conflicts in file " + extensionFile + ": " | |
| - + gasLocations.entrySet().stream() | |
| - .map(e -> e.getKey() + " defined on lines " | |
| - + e.getValue().stream() | |
| - .map(l -> String.valueOf(l.getLineNumber())) | |
| - .collect(Collectors.joining(", "))) | |
| - .collect(Collectors.joining("; "))); | |
| - } | |
| - if (!allowMetaVersions && !metaVersionLocations.isEmpty()) { | |
| - throw new IllegalStateException("Extension with illegal version in file " + extensionFile + ": " | |
| - + metaVersionLocations.entrySet().stream() | |
| - .map(e -> e.getKey() + " defined on lines " | |
| - + e.getValue().stream() | |
| - .map(l -> String.valueOf(l.getLineNumber())) | |
| - .collect(Collectors.joining(", "))) | |
| - .collect(Collectors.joining("; "))); | |
| - } | |
| - return coreExtensions; | |
| + if (gasLocations.values().stream().noneMatch(l -> l.size() > 1)) { | |
| + return coreExtensions; | |
| + } | |
| + throw new IllegalStateException("Extension conflicts in file " + extensionFile + ": " | |
| + + gasLocations.entrySet().stream() | |
| + .map(e -> e.getKey() + " defined on lines " | |
| + + e.getValue().stream() | |
| + .map(l -> String.valueOf(l.getLineNumber())) | |
| + .collect(Collectors.joining(", "))) | |
| + .collect(Collectors.joining("; "))); | |
| } | |
| @Nullable | |
| @@ -574,4 +562,31 @@ protected CIInfo detectCI(LocalContext context) { | |
| } | |
| return detected.get(0); | |
| } | |
| + | |
| + private void warnAboutDeprecatedPropertiesFiles(LocalContext context) { | |
| + Map<String, String> systemProperties = context.systemProperties; | |
| + | |
| + // Check for deprecated ~/.m2/maven.properties | |
| + String userConfig = systemProperties.get("maven.user.conf"); | |
| + Path userMavenProperties = userConfig != null ? Path.of(userConfig).resolve("maven.properties") : null; | |
| + if (userMavenProperties != null && Files.exists(userMavenProperties)) { | |
| + context.parserRequest | |
| + .logger() | |
| + .warn("Loading deprecated properties file: " + userMavenProperties + ". " | |
| + + "Please rename to 'maven-user.properties'. " | |
| + + "Support for 'maven.properties' will be removed in Maven 4.1.0."); | |
| + } | |
| + | |
| + // Check for deprecated .mvn/maven.properties in project directory | |
| + String projectConfig = systemProperties.get("maven.project.conf"); | |
| + Path projectMavenProperties = | |
| + projectConfig != null ? Path.of(projectConfig).resolve("maven.properties") : null; | |
| + if (projectMavenProperties != null && Files.exists(projectMavenProperties)) { | |
| + context.parserRequest | |
| + .logger() | |
| + .warn("Loading deprecated properties file: " + projectMavenProperties + ". " | |
| + + "Please rename to 'maven-user.properties'. " | |
| + + "Support for 'maven.properties' will be removed in Maven 4.1.0."); | |
| + } | |
| + } | |
| } | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/CommonsCliOptions.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/CommonsCliOptions.java | |
| index c417f24f40..f78bcb0f52 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/CommonsCliOptions.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/CommonsCliOptions.java | |
| @@ -279,7 +279,7 @@ public final Options interpolate(UnaryOperator<String> callback) { | |
| for (String arg : commandLine.getArgList()) { | |
| commandLineBuilder.addArg(interpolator.interpolate(arg, callback)); | |
| } | |
| - return copy(source, cliManager, commandLineBuilder.get()); | |
| + return copy(source, cliManager, commandLineBuilder.build()); | |
| } catch (InterpolatorException e) { | |
| throw new IllegalArgumentException("Could not interpolate CommonsCliOptions", e); | |
| } | |
| @@ -348,116 +348,116 @@ protected void prepareOptions(org.apache.commons.cli.Options options) { | |
| options.addOption(Option.builder(HELP) | |
| .longOpt("help") | |
| .desc("Display help information") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(USER_PROPERTY) | |
| .numberOfArgs(2) | |
| .valueSeparator('=') | |
| .desc("Define a user property") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(SHOW_VERSION_AND_EXIT) | |
| .longOpt("version") | |
| .desc("Display version information") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(QUIET) | |
| .longOpt("quiet") | |
| .desc("Quiet output - only show errors") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(VERBOSE) | |
| .longOpt("verbose") | |
| .desc("Produce execution verbose output") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(SHOW_ERRORS) | |
| .longOpt("errors") | |
| .desc("Produce execution error messages") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(BATCH_MODE) | |
| .longOpt("batch-mode") | |
| .desc("Run in non-interactive mode. Alias for --non-interactive (kept for backwards compatability)") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder() | |
| .longOpt(NON_INTERACTIVE) | |
| .desc("Run in non-interactive mode. Alias for --batch-mode") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder() | |
| .longOpt(FORCE_INTERACTIVE) | |
| .desc( | |
| "Run in interactive mode. Overrides, if applicable, the CI environment variable and --non-interactive/--batch-mode options") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(ALTERNATE_USER_SETTINGS) | |
| .longOpt("settings") | |
| .desc("Alternate path for the user settings file") | |
| .hasArg() | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(ALTERNATE_PROJECT_SETTINGS) | |
| .longOpt("project-settings") | |
| .desc("Alternate path for the project settings file") | |
| .hasArg() | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(ALTERNATE_INSTALLATION_SETTINGS) | |
| .longOpt("install-settings") | |
| .desc("Alternate path for the installation settings file") | |
| .hasArg() | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(ALTERNATE_USER_TOOLCHAINS) | |
| .longOpt("toolchains") | |
| .desc("Alternate path for the user toolchains file") | |
| .hasArg() | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(ALTERNATE_INSTALLATION_TOOLCHAINS) | |
| .longOpt("install-toolchains") | |
| .desc("Alternate path for the installation toolchains file") | |
| .hasArg() | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(FAIL_ON_SEVERITY) | |
| .longOpt("fail-on-severity") | |
| .desc("Configure which severity of logging should cause the build to fail") | |
| .hasArg() | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(LOG_FILE) | |
| .longOpt("log-file") | |
| .hasArg() | |
| .desc("Log file where all build output will go (disables output color)") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder() | |
| .longOpt(RAW_STREAMS) | |
| .desc("Do not decorate standard output and error streams") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(SHOW_VERSION) | |
| .longOpt("show-version") | |
| .desc("Display version information WITHOUT stopping build") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder() | |
| .longOpt(COLOR) | |
| .hasArg() | |
| .optionalArg(true) | |
| .desc("Defines the color mode of the output. Supported are 'auto', 'always', 'never'.") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(OFFLINE) | |
| .longOpt("offline") | |
| .desc("Work offline") | |
| - .get()); | |
| + .build()); | |
| // Parameters handled by script | |
| options.addOption(Option.builder() | |
| .longOpt(DEBUG) | |
| .desc("Launch the JVM in debug mode (script option).") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder() | |
| .longOpt(ENC) | |
| .desc("Launch the Maven Encryption tool (script option).") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder() | |
| .longOpt(UPGRADE) | |
| .desc("Launch the Maven Upgrade tool (script option).") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder() | |
| .longOpt(SHELL) | |
| .desc("Launch the Maven Shell tool (script option).") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder() | |
| .longOpt(YJP) | |
| .desc("Launch the JVM with Yourkit profiler (script option).") | |
| - .get()); | |
| + .build()); | |
| // Deprecated | |
| options.addOption(Option.builder(ALTERNATE_GLOBAL_SETTINGS) | |
| @@ -469,7 +469,7 @@ protected void prepareOptions(org.apache.commons.cli.Options options) { | |
| .setSince("4.0.0") | |
| .setDescription("Use -is,--install-settings instead.") | |
| .get()) | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(ALTERNATE_GLOBAL_TOOLCHAINS) | |
| .longOpt("global-toolchains") | |
| .desc("<deprecated> Alternate path for the global toolchains file.") | |
| @@ -479,7 +479,7 @@ protected void prepareOptions(org.apache.commons.cli.Options options) { | |
| .setSince("4.0.0") | |
| .setDescription("Use -it,--install-toolchains instead.") | |
| .get()) | |
| - .get()); | |
| + .build()); | |
| } | |
| public CommandLine parse(String[] args) throws ParseException { | |
| @@ -487,7 +487,7 @@ public CommandLine parse(String[] args) throws ParseException { | |
| String[] cleanArgs = CleanArgument.cleanArgs(args); | |
| DefaultParser parser = DefaultParser.builder() | |
| .setDeprecatedHandler(this::addDeprecatedOption) | |
| - .get(); | |
| + .build(); | |
| CommandLine commandLine = parser.parse(options, cleanArgs); | |
| // to trigger deprecation handler, so we can report deprecation BEFORE we actually use options | |
| options.getOptions().forEach(commandLine::hasOption); | |
| @@ -535,7 +535,7 @@ public void displayHelp(String command, Consumer<String> pw) { | |
| } | |
| protected String commandLineSyntax(String command) { | |
| - return command + " [options] [<goal|phase> ...]"; | |
| + return command + " [options] [goals]"; | |
| } | |
| } | |
| } | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java | |
| index 9844cfb8d4..ec439870cf 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java | |
| @@ -284,17 +284,15 @@ protected void configureLogging(C context) throws Exception { | |
| context.loggerFactory = LoggerFactory.getILoggerFactory(); | |
| context.slf4jConfiguration = Slf4jConfigurationFactory.getConfiguration(context.loggerFactory); | |
| + context.loggerLevel = Slf4jConfiguration.Level.INFO; | |
| if (context.invokerRequest.effectiveVerbose()) { | |
| context.loggerLevel = Slf4jConfiguration.Level.DEBUG; | |
| - context.slf4jConfiguration.setRootLoggerLevel(context.loggerLevel); | |
| } else if (context.options().quiet().orElse(false)) { | |
| context.loggerLevel = Slf4jConfiguration.Level.ERROR; | |
| - context.slf4jConfiguration.setRootLoggerLevel(context.loggerLevel); | |
| - } else { | |
| - // fall back to default log level specified in conf | |
| - // see https://issues.apache.org/jira/browse/MNG-2570 and https://github.com/apache/maven/issues/11199 | |
| - context.loggerLevel = Slf4jConfiguration.Level.INFO; // default for display purposes | |
| } | |
| + context.slf4jConfiguration.setRootLoggerLevel(context.loggerLevel); | |
| + // else fall back to default log level specified in conf | |
| + // see https://issues.apache.org/jira/browse/MNG-2570 | |
| } | |
| protected BuildEventListener determineBuildEventListener(C context) { | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/PrecedenceCoreExtensionSelector.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/PrecedenceCoreExtensionSelector.java | |
| index 590529d5f1..6edfde98ee 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/PrecedenceCoreExtensionSelector.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/PrecedenceCoreExtensionSelector.java | |
| @@ -21,7 +21,6 @@ | |
| import java.util.ArrayList; | |
| import java.util.LinkedHashMap; | |
| import java.util.List; | |
| -import java.util.Objects; | |
| import java.util.Optional; | |
| import org.apache.maven.api.cli.CoreExtensions; | |
| @@ -61,7 +60,7 @@ protected List<CoreExtension> selectCoreExtensions(C context, List<CoreExtension | |
| for (CoreExtension coreExtension : coreExtensions.coreExtensions()) { | |
| String key = coreExtension.getGroupId() + ":" + coreExtension.getArtifactId(); | |
| CoreExtension conflict = selectedExtensions.putIfAbsent(key, coreExtension); | |
| - if (conflict != null && !Objects.equals(coreExtension.getVersion(), conflict.getVersion())) { | |
| + if (conflict != null) { | |
| conflicts.add(String.format( | |
| "Conflicting extension %s: %s vs %s", | |
| key, | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/CommonsCliMavenOptions.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/CommonsCliMavenOptions.java | |
| index 233e22f15e..1101965ad7 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/CommonsCliMavenOptions.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/CommonsCliMavenOptions.java | |
| @@ -260,106 +260,106 @@ protected void prepareOptions(org.apache.commons.cli.Options options) { | |
| .longOpt("file") | |
| .hasArg() | |
| .desc("Force the use of an alternate POM file (or directory with pom.xml)") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(NON_RECURSIVE) | |
| .longOpt("non-recursive") | |
| .desc( | |
| "Do not recurse into sub-projects. When used together with -pl, do not recurse into sub-projects of selected aggregators") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(UPDATE_SNAPSHOTS) | |
| .longOpt("update-snapshots") | |
| .desc("Forces a check for missing releases and updated snapshots on remote repositories") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(ACTIVATE_PROFILES) | |
| .longOpt("activate-profiles") | |
| .desc( | |
| - "Comma-delimited list of profiles to activate. Don't use spaces between commas or double quote the full list. Prefixing a profile with ! excludes it, and ? marks it as optional.") | |
| + "Comma-delimited list of profiles to activate. Prefixing a profile with ! excludes it, and ? marks it as optional") | |
| .hasArg() | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(SUPPRESS_SNAPSHOT_UPDATES) | |
| .longOpt("no-snapshot-updates") | |
| .desc("Suppress SNAPSHOT updates") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(CHECKSUM_FAILURE_POLICY) | |
| .longOpt("strict-checksums") | |
| .desc("Fail the build if checksums don't match") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(CHECKSUM_WARNING_POLICY) | |
| .longOpt("lax-checksums") | |
| .desc("Warn if checksums don't match") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(FAIL_FAST) | |
| .longOpt("fail-fast") | |
| .desc("Stop at first failure in reactorized builds") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(FAIL_AT_END) | |
| .longOpt("fail-at-end") | |
| .desc("Only fail the build afterwards; allow all non-impacted builds to continue") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(FAIL_NEVER) | |
| .longOpt("fail-never") | |
| .desc("NEVER fail the build, regardless of project result") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(RESUME) | |
| .longOpt("resume") | |
| .desc( | |
| "Resume reactor from the last failed project, using the resume.properties file in the build directory") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(RESUME_FROM) | |
| .longOpt("resume-from") | |
| .hasArg() | |
| .desc("Resume reactor from specified project") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(PROJECT_LIST) | |
| .longOpt("projects") | |
| .desc( | |
| - "Comma-delimited list of specified reactor projects to build instead of all projects. Don't use spaces between commas or double quote the full list. A project can be specified by [groupId]:artifactId or by its relative path. Prefixing a project with ! excludes it, and ? marks it as optional.") | |
| + "Comma-delimited list of specified reactor projects to build instead of all projects. A project can be specified by [groupId]:artifactId or by its relative path. Prefixing a project with ! excludes it, and ? marks it as optional") | |
| .hasArg() | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(ALSO_MAKE) | |
| .longOpt("also-make") | |
| .desc("If project list is specified, also build projects required by the list") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(ALSO_MAKE_DEPENDENTS) | |
| .longOpt("also-make-dependents") | |
| .desc("If project list is specified, also build projects that depend on projects on the list") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(THREADS) | |
| .longOpt("threads") | |
| .hasArg() | |
| .desc("Thread count, for instance 4 (int) or 2C/2.5C (int/float) where C is core multiplied") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(BUILDER) | |
| .longOpt("builder") | |
| .hasArg() | |
| .desc("The id of the build strategy to use") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(NO_TRANSFER_PROGRESS) | |
| .longOpt("no-transfer-progress") | |
| .desc("Do not display transfer progress when downloading or uploading") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(CACHE_ARTIFACT_NOT_FOUND) | |
| .longOpt("cache-artifact-not-found") | |
| .hasArg() | |
| .desc( | |
| "Defines caching behaviour for 'not found' artifacts. Supported values are 'true' (default), 'false'.") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(STRICT_ARTIFACT_DESCRIPTOR_POLICY) | |
| .longOpt("strict-artifact-descriptor-policy") | |
| .hasArg() | |
| .desc( | |
| "Defines 'strict' artifact descriptor policy. Supported values are 'true', 'false' (default).") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(IGNORE_TRANSITIVE_REPOSITORIES) | |
| .longOpt("ignore-transitive-repositories") | |
| .desc("If set, Maven will ignore remote repositories introduced by transitive dependencies.") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(AT_FILE) | |
| .longOpt("at-file") | |
| .hasArg() | |
| .desc( | |
| "If set, Maven will load command line options from the specified file and merge with CLI specified ones.") | |
| - .get()); | |
| + .build()); | |
| } | |
| } | |
| } | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/CommonsCliEncryptOptions.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/CommonsCliEncryptOptions.java | |
| index e24caa2495..495d6373de 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/CommonsCliEncryptOptions.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnenc/CommonsCliEncryptOptions.java | |
| @@ -96,11 +96,11 @@ protected void prepareOptions(org.apache.commons.cli.Options options) { | |
| options.addOption(Option.builder(FORCE) | |
| .longOpt("force") | |
| .desc("Should overwrite without asking any configuration?") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(YES) | |
| .longOpt("yes") | |
| .desc("Should imply user answered \"yes\" to all incoming questions?") | |
| - .get()); | |
| + .build()); | |
| } | |
| } | |
| } | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/CommonsCliUpgradeOptions.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/CommonsCliUpgradeOptions.java | |
| index 29025cce9a..d3f668c899 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/CommonsCliUpgradeOptions.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/CommonsCliUpgradeOptions.java | |
| @@ -126,7 +126,7 @@ public void displayHelp(ParserRequest request, Consumer<String> printStream) { | |
| printStream.accept( | |
| " -a, --all Apply all upgrades (equivalent to --model-version 4.1.0 --infer --model --plugins)"); | |
| printStream.accept(""); | |
| - printStream.accept("Default behavior: --model --plugins --infer are applied if no other options are specified"); | |
| + printStream.accept("Default behavior: --model and --plugins are applied if no other options are specified"); | |
| printStream.accept(""); | |
| } | |
| @@ -152,29 +152,29 @@ protected void prepareOptions(org.apache.commons.cli.Options options) { | |
| .hasArg() | |
| .argName("version") | |
| .desc("Target POM model version (4.0.0 or 4.1.0)") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(DIRECTORY) | |
| .longOpt("directory") | |
| .hasArg() | |
| .argName("path") | |
| .desc("Directory to use as starting point for POM discovery") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(INFER) | |
| .longOpt("infer") | |
| .desc("Use inference when upgrading (remove redundant information)") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(MODEL) | |
| .longOpt("model") | |
| .desc("Fix Maven 4 compatibility issues in POM files") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(PLUGINS) | |
| .longOpt("plugins") | |
| .desc("Upgrade plugins known to fail with Maven 4 to their minimum compatible versions") | |
| - .get()); | |
| + .build()); | |
| options.addOption(Option.builder(ALL) | |
| .longOpt("all") | |
| .desc("Apply all upgrades (equivalent to --model-version 4.1.0 --infer --model --plugins)") | |
| - .get()); | |
| + .build()); | |
| } | |
| } | |
| } | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategy.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategy.java | |
| index 11d7276f8f..426981a09a 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategy.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategy.java | |
| @@ -33,6 +33,7 @@ | |
| import org.apache.maven.api.di.Singleton; | |
| import org.apache.maven.cling.invoker.mvnup.UpgradeContext; | |
| import org.jdom2.Attribute; | |
| +import org.jdom2.Comment; | |
| import org.jdom2.Content; | |
| import org.jdom2.Document; | |
| import org.jdom2.Element; | |
| @@ -497,12 +498,25 @@ private boolean fixRepositoryExpressions(Element repositoriesElement, Namespace | |
| Element urlElement = repository.getChild("url", namespace); | |
| if (urlElement != null) { | |
| String url = urlElement.getTextTrim(); | |
| - if (url.contains("${")) { | |
| - // Allow repository URL interpolation; do not disable. | |
| - // Keep a gentle warning to help users notice unresolved placeholders at build time. | |
| + if (url.contains("${") | |
| + && !url.contains("${project.basedir}") | |
| + && !url.contains("${project.rootDirectory}")) { | |
| String repositoryId = getChildText(repository, "id", namespace); | |
| - context.info("Detected interpolated expression in " + elementType + " URL (id: " + repositoryId | |
| + context.warning("Found unsupported expression in " + elementType + " URL (id: " + repositoryId | |
| + "): " + url); | |
| + context.warning( | |
| + "Maven 4 only supports ${project.basedir} and ${project.rootDirectory} expressions in repository URLs"); | |
| + | |
| + // Comment out the problematic repository | |
| + Comment comment = | |
| + new Comment(" Repository disabled due to unsupported expression in URL: " + url + " "); | |
| + Element parent = repository.getParentElement(); | |
| + parent.addContent(parent.indexOf(repository), comment); | |
| + removeElementWithFormatting(repository); | |
| + | |
| + context.detail("Fixed: " + "Commented out " + elementType + " with unsupported URL expression (id: " | |
| + + repositoryId + ")"); | |
| + fixed = true; | |
| } | |
| } | |
| } | |
| @@ -520,8 +534,8 @@ private Path findParentPomInMap( | |
| && Objects.equals(gav.artifactId(), artifactId) | |
| && (version == null || Objects.equals(gav.version(), version)); | |
| }) | |
| - .findFirst() | |
| .map(Map.Entry::getKey) | |
| + .findFirst() | |
| .orElse(null); | |
| } | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategy.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategy.java | |
| index 6a6d18bbe0..aeff300581 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategy.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategy.java | |
| @@ -19,13 +19,11 @@ | |
| package org.apache.maven.cling.invoker.mvnup.goals; | |
| import java.nio.file.Path; | |
| -import java.util.HashMap; | |
| import java.util.HashSet; | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.Set; | |
| -import org.apache.maven.api.Lifecycle; | |
| import org.apache.maven.api.cli.mvnup.UpgradeOptions; | |
| import org.apache.maven.api.di.Named; | |
| import org.apache.maven.api.di.Priority; | |
| @@ -39,22 +37,13 @@ | |
| import static org.apache.maven.cling.invoker.mvnup.goals.ModelVersionUtils.getSchemaLocationForModelVersion; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.ModelVersions.MODEL_VERSION_4_0_0; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.ModelVersions.MODEL_VERSION_4_1_0; | |
| -import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.ModelVersions.MODEL_VERSION_4_2_0; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.Namespaces.MAVEN_4_0_0_NAMESPACE; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.Namespaces.MAVEN_4_1_0_NAMESPACE; | |
| -import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.Namespaces.MAVEN_4_2_0_NAMESPACE; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlAttributes.SCHEMA_LOCATION; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlAttributes.XSI_NAMESPACE_PREFIX; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlAttributes.XSI_NAMESPACE_URI; | |
| -import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.BUILD; | |
| -import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.EXECUTION; | |
| -import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.EXECUTIONS; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.MODULE; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.MODULES; | |
| -import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.PHASE; | |
| -import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.PLUGIN; | |
| -import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.PLUGINS; | |
| -import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.PLUGIN_MANAGEMENT; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.PROFILE; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.PROFILES; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.SUBPROJECT; | |
| @@ -152,7 +141,6 @@ private void performModelUpgrade( | |
| // Convert modules to subprojects (for 4.1.0 and higher) | |
| if (ModelVersionUtils.isVersionGreaterOrEqual(targetModelVersion, MODEL_VERSION_4_1_0)) { | |
| convertModulesToSubprojects(pomDocument, context); | |
| - upgradeDeprecatedPhases(pomDocument, context); | |
| } | |
| // Update modelVersion to target version (perhaps removed later during inference step) | |
| @@ -258,124 +246,10 @@ private String determineTargetModelVersion(UpgradeContext context) { | |
| * Gets the namespace URI for a model version. | |
| */ | |
| private String getNamespaceForModelVersion(String modelVersion) { | |
| - if (MODEL_VERSION_4_2_0.equals(modelVersion)) { | |
| - return MAVEN_4_2_0_NAMESPACE; | |
| - } else if (MODEL_VERSION_4_1_0.equals(modelVersion)) { | |
| + if (MODEL_VERSION_4_1_0.equals(modelVersion)) { | |
| return MAVEN_4_1_0_NAMESPACE; | |
| } else { | |
| return MAVEN_4_0_0_NAMESPACE; | |
| } | |
| } | |
| - | |
| - /** | |
| - * Upgrades deprecated Maven 3 phase names to Maven 4 equivalents. | |
| - * This replaces pre-/post- phases with before:/after: phases. | |
| - */ | |
| - private void upgradeDeprecatedPhases(Document pomDocument, UpgradeContext context) { | |
| - // Create mapping of deprecated phases to their Maven 4 equivalents | |
| - Map<String, String> phaseUpgrades = createPhaseUpgradeMap(); | |
| - | |
| - Element root = pomDocument.getRootElement(); | |
| - Namespace namespace = root.getNamespace(); | |
| - | |
| - int totalUpgrades = 0; | |
| - | |
| - // Upgrade phases in main build section | |
| - totalUpgrades += upgradePhaseElements(root.getChild(BUILD, namespace), namespace, phaseUpgrades, context); | |
| - | |
| - // Upgrade phases in profiles | |
| - Element profilesElement = root.getChild(PROFILES, namespace); | |
| - if (profilesElement != null) { | |
| - List<Element> profileElements = profilesElement.getChildren(PROFILE, namespace); | |
| - for (Element profileElement : profileElements) { | |
| - Element profileBuildElement = profileElement.getChild(BUILD, namespace); | |
| - totalUpgrades += upgradePhaseElements(profileBuildElement, namespace, phaseUpgrades, context); | |
| - } | |
| - } | |
| - | |
| - if (totalUpgrades > 0) { | |
| - context.detail("Upgraded " + totalUpgrades + " deprecated phase name(s) to Maven 4 equivalents"); | |
| - } | |
| - } | |
| - | |
| - /** | |
| - * Creates the mapping of deprecated phase names to their Maven 4 equivalents. | |
| - * Uses Maven API constants to ensure consistency with the lifecycle definitions. | |
| - */ | |
| - private Map<String, String> createPhaseUpgradeMap() { | |
| - Map<String, String> phaseUpgrades = new HashMap<>(); | |
| - | |
| - // Clean lifecycle aliases | |
| - phaseUpgrades.put("pre-clean", Lifecycle.BEFORE + Lifecycle.Phase.CLEAN); | |
| - phaseUpgrades.put("post-clean", Lifecycle.AFTER + Lifecycle.Phase.CLEAN); | |
| - | |
| - // Default lifecycle aliases | |
| - phaseUpgrades.put("pre-integration-test", Lifecycle.BEFORE + Lifecycle.Phase.INTEGRATION_TEST); | |
| - phaseUpgrades.put("post-integration-test", Lifecycle.AFTER + Lifecycle.Phase.INTEGRATION_TEST); | |
| - | |
| - // Site lifecycle aliases | |
| - phaseUpgrades.put("pre-site", Lifecycle.BEFORE + Lifecycle.SITE); | |
| - phaseUpgrades.put("post-site", Lifecycle.AFTER + Lifecycle.SITE); | |
| - | |
| - return phaseUpgrades; | |
| - } | |
| - | |
| - /** | |
| - * Upgrades phase elements within a build section. | |
| - */ | |
| - private int upgradePhaseElements( | |
| - Element buildElement, Namespace namespace, Map<String, String> phaseUpgrades, UpgradeContext context) { | |
| - if (buildElement == null) { | |
| - return 0; | |
| - } | |
| - | |
| - int upgrades = 0; | |
| - | |
| - // Check plugins section | |
| - Element pluginsElement = buildElement.getChild(PLUGINS, namespace); | |
| - if (pluginsElement != null) { | |
| - upgrades += upgradePhaseElementsInPlugins(pluginsElement, namespace, phaseUpgrades, context); | |
| - } | |
| - | |
| - // Check pluginManagement section | |
| - Element pluginManagementElement = buildElement.getChild(PLUGIN_MANAGEMENT, namespace); | |
| - if (pluginManagementElement != null) { | |
| - Element managedPluginsElement = pluginManagementElement.getChild(PLUGINS, namespace); | |
| - if (managedPluginsElement != null) { | |
| - upgrades += upgradePhaseElementsInPlugins(managedPluginsElement, namespace, phaseUpgrades, context); | |
| - } | |
| - } | |
| - | |
| - return upgrades; | |
| - } | |
| - | |
| - /** | |
| - * Upgrades phase elements within a plugins section. | |
| - */ | |
| - private int upgradePhaseElementsInPlugins( | |
| - Element pluginsElement, Namespace namespace, Map<String, String> phaseUpgrades, UpgradeContext context) { | |
| - int upgrades = 0; | |
| - | |
| - List<Element> pluginElements = pluginsElement.getChildren(PLUGIN, namespace); | |
| - for (Element pluginElement : pluginElements) { | |
| - Element executionsElement = pluginElement.getChild(EXECUTIONS, namespace); | |
| - if (executionsElement != null) { | |
| - List<Element> executionElements = executionsElement.getChildren(EXECUTION, namespace); | |
| - for (Element executionElement : executionElements) { | |
| - Element phaseElement = executionElement.getChild(PHASE, namespace); | |
| - if (phaseElement != null) { | |
| - String currentPhase = phaseElement.getTextTrim(); | |
| - String newPhase = phaseUpgrades.get(currentPhase); | |
| - if (newPhase != null) { | |
| - phaseElement.setText(newPhase); | |
| - context.detail("Upgraded phase: " + currentPhase + " → " + newPhase); | |
| - upgrades++; | |
| - } | |
| - } | |
| - } | |
| - } | |
| - } | |
| - | |
| - return upgrades; | |
| - } | |
| } | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelVersionUtils.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelVersionUtils.java | |
| index 1a916bd23a..8d37407789 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelVersionUtils.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelVersionUtils.java | |
| @@ -24,12 +24,9 @@ | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.ModelVersions.MODEL_VERSION_4_0_0; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.ModelVersions.MODEL_VERSION_4_1_0; | |
| -import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.ModelVersions.MODEL_VERSION_4_2_0; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.Namespaces.MAVEN_4_0_0_NAMESPACE; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.Namespaces.MAVEN_4_1_0_NAMESPACE; | |
| -import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.Namespaces.MAVEN_4_2_0_NAMESPACE; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.SchemaLocations.MAVEN_4_1_0_SCHEMA_LOCATION; | |
| -import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.SchemaLocations.MAVEN_4_2_0_SCHEMA_LOCATION; | |
| import static org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.MODEL_VERSION; | |
| /** | |
| @@ -63,9 +60,7 @@ public static String detectModelVersion(Document pomDocument) { | |
| // Fallback to namespace URI detection | |
| String namespaceUri = namespace.getURI(); | |
| - if (MAVEN_4_2_0_NAMESPACE.equals(namespaceUri)) { | |
| - return MODEL_VERSION_4_2_0; | |
| - } else if (MAVEN_4_1_0_NAMESPACE.equals(namespaceUri)) { | |
| + if (MAVEN_4_1_0_NAMESPACE.equals(namespaceUri)) { | |
| return MODEL_VERSION_4_1_0; | |
| } else if (MAVEN_4_0_0_NAMESPACE.equals(namespaceUri)) { | |
| return MODEL_VERSION_4_0_0; | |
| @@ -77,15 +72,13 @@ public static String detectModelVersion(Document pomDocument) { | |
| /** | |
| * Checks if a model version is valid for upgrade operations. | |
| - * Currently supports 4.0.0, 4.1.0, and 4.2.0. | |
| + * Currently only supports 4.0.0 and 4.1.0. | |
| * | |
| * @param modelVersion the model version to validate | |
| * @return true if the model version is valid | |
| */ | |
| public static boolean isValidModelVersion(String modelVersion) { | |
| - return MODEL_VERSION_4_0_0.equals(modelVersion) | |
| - || MODEL_VERSION_4_1_0.equals(modelVersion) | |
| - || MODEL_VERSION_4_2_0.equals(modelVersion); | |
| + return MODEL_VERSION_4_0_0.equals(modelVersion) || MODEL_VERSION_4_1_0.equals(modelVersion); | |
| } | |
| /** | |
| @@ -100,15 +93,8 @@ public static boolean canUpgrade(String fromVersion, String toVersion) { | |
| return false; | |
| } | |
| - // Support upgrades: 4.0.0 → 4.1.0, 4.0.0 → 4.2.0, 4.1.0 → 4.2.0 | |
| - if (MODEL_VERSION_4_0_0.equals(fromVersion)) { | |
| - return MODEL_VERSION_4_1_0.equals(toVersion) || MODEL_VERSION_4_2_0.equals(toVersion); | |
| - } | |
| - if (MODEL_VERSION_4_1_0.equals(fromVersion)) { | |
| - return MODEL_VERSION_4_2_0.equals(toVersion); | |
| - } | |
| - | |
| - return false; | |
| + // Currently only support 4.0.0 → 4.1.0 upgrade | |
| + return MODEL_VERSION_4_0_0.equals(fromVersion) && MODEL_VERSION_4_1_0.equals(toVersion); | |
| } | |
| /** | |
| @@ -119,9 +105,7 @@ public static boolean canUpgrade(String fromVersion, String toVersion) { | |
| * @return true if eligible for inference | |
| */ | |
| public static boolean isEligibleForInference(String modelVersion) { | |
| - return MODEL_VERSION_4_0_0.equals(modelVersion) | |
| - || MODEL_VERSION_4_1_0.equals(modelVersion) | |
| - || MODEL_VERSION_4_2_0.equals(modelVersion); | |
| + return MODEL_VERSION_4_0_0.equals(modelVersion) || MODEL_VERSION_4_1_0.equals(modelVersion); | |
| } | |
| /** | |
| @@ -236,13 +220,8 @@ public static boolean removeModelVersion(Document pomDocument) { | |
| * @return the schema location | |
| */ | |
| public static String getSchemaLocationForModelVersion(String modelVersion) { | |
| - if (MODEL_VERSION_4_2_0.equals(modelVersion)) { | |
| - return MAVEN_4_2_0_SCHEMA_LOCATION; | |
| - } else if (MODEL_VERSION_4_1_0.equals(modelVersion)) { | |
| + if (MODEL_VERSION_4_1_0.equals(modelVersion) || isNewerThan410(modelVersion)) { | |
| return MAVEN_4_1_0_SCHEMA_LOCATION; | |
| - } else if (isNewerThan410(modelVersion)) { | |
| - // For versions newer than 4.1.0 but not specifically 4.2.0, use 4.2.0 schema | |
| - return MAVEN_4_2_0_SCHEMA_LOCATION; | |
| } | |
| return UpgradeConstants.SchemaLocations.MAVEN_4_0_0_SCHEMA_LOCATION; | |
| } | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeConstants.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeConstants.java | |
| index f8fd5494bc..8d49fcc76b 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeConstants.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeConstants.java | |
| @@ -38,9 +38,6 @@ public static final class ModelVersions { | |
| /** Maven 4.1.0 model version */ | |
| public static final String MODEL_VERSION_4_1_0 = "4.1.0"; | |
| - /** Maven 4.2.0 model version */ | |
| - public static final String MODEL_VERSION_4_2_0 = "4.2.0"; | |
| - | |
| private ModelVersions() { | |
| // Utility class | |
| } | |
| @@ -77,11 +74,9 @@ public static final class XmlElements { | |
| public static final String TEST_OUTPUT_DIRECTORY = "testOutputDirectory"; | |
| public static final String EXTENSIONS = "extensions"; | |
| public static final String EXECUTIONS = "executions"; | |
| - public static final String EXECUTION = "execution"; | |
| public static final String GOALS = "goals"; | |
| public static final String INHERITED = "inherited"; | |
| public static final String CONFIGURATION = "configuration"; | |
| - public static final String PHASE = "phase"; | |
| // Module elements | |
| public static final String MODULES = "modules"; | |
| @@ -188,9 +183,6 @@ public static final class Namespaces { | |
| /** Maven 4.1.0 namespace URI */ | |
| public static final String MAVEN_4_1_0_NAMESPACE = "http://maven.apache.org/POM/4.1.0"; | |
| - /** Maven 4.2.0 namespace URI */ | |
| - public static final String MAVEN_4_2_0_NAMESPACE = "http://maven.apache.org/POM/4.2.0"; | |
| - | |
| private Namespaces() { | |
| // Utility class | |
| } | |
| @@ -208,10 +200,6 @@ public static final class SchemaLocations { | |
| public static final String MAVEN_4_1_0_SCHEMA_LOCATION = | |
| Namespaces.MAVEN_4_1_0_NAMESPACE + " https://maven.apache.org/xsd/maven-4.1.0.xsd"; | |
| - /** Schema location for 4.2.0 models */ | |
| - public static final String MAVEN_4_2_0_SCHEMA_LOCATION = | |
| - Namespaces.MAVEN_4_2_0_NAMESPACE + " https://maven.apache.org/xsd/maven-4.2.0.xsd"; | |
| - | |
| private SchemaLocations() { | |
| // Utility class | |
| } | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/logging/impl/MavenSimpleConfiguration.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/logging/impl/MavenSimpleConfiguration.java | |
| index 7bef54100b..2c407d6bee 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/logging/impl/MavenSimpleConfiguration.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/logging/impl/MavenSimpleConfiguration.java | |
| @@ -39,14 +39,14 @@ public void setRootLoggerLevel(Level level) { | |
| switch (level) { | |
| case DEBUG -> "debug"; | |
| case INFO -> "info"; | |
| - case ERROR -> "error"; | |
| + default -> "error"; | |
| }; | |
| String current = System.setProperty(Constants.MAVEN_LOGGER_DEFAULT_LOG_LEVEL, value); | |
| if (current != null && !value.equalsIgnoreCase(current)) { | |
| LOGGER.info( | |
| "System property '" + Constants.MAVEN_LOGGER_DEFAULT_LOG_LEVEL + "' is already set to '" + current | |
| - + "' - ignoring system property and get log level from -X/-e/-q options, log level will be set to " | |
| + + "' - ignoring system property and get log level from -X/-e/-q options, log level will be set to" | |
| + value); | |
| } | |
| } | |
| diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/props/MavenProperties.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/props/MavenProperties.java | |
| index 2bc3264ed4..27f4ef8052 100644 | |
| --- a/impl/maven-cli/src/main/java/org/apache/maven/cling/props/MavenProperties.java | |
| +++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/props/MavenProperties.java | |
| @@ -870,7 +870,7 @@ public String readProperty() throws IOException { | |
| line = line.substring(0, line.length() - 1); | |
| } | |
| valueLines.add(line); | |
| - while (!line.isEmpty() && contains(WHITE_SPACE, line.charAt(0))) { | |
| + while (line.length() > 0 && contains(WHITE_SPACE, line.charAt(0))) { | |
| line = line.substring(1, line.length()); | |
| } | |
| buffer.append(line); | |
| diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/BaseParserTest.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/BaseParserTest.java | |
| index 9053ec88f2..90b533fd33 100644 | |
| --- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/BaseParserTest.java | |
| +++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/BaseParserTest.java | |
| @@ -77,8 +77,7 @@ void notHappy() { | |
| .build()); | |
| Assertions.assertFalse(invokerRequest.options().isPresent()); | |
| - Assertions.assertTrue( | |
| - invokerRequest.parsingFailed(), "Expected " + invokerRequest + ".parsingFailed() to return true"); | |
| + Assertions.assertTrue(invokerRequest.parsingFailed()); | |
| } | |
| @Test | |
| diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/LookupInvokerLoggingTest.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/LookupInvokerLoggingTest.java | |
| deleted file mode 100644 | |
| index c76cd26764..0000000000 | |
| --- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/LookupInvokerLoggingTest.java | |
| +++ /dev/null | |
| @@ -1,173 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.cling.invoker; | |
| - | |
| -import java.util.Optional; | |
| - | |
| -import org.apache.maven.api.Constants; | |
| -import org.apache.maven.cling.logging.Slf4jConfiguration; | |
| -import org.junit.jupiter.api.AfterEach; | |
| -import org.junit.jupiter.api.BeforeEach; | |
| -import org.junit.jupiter.api.Test; | |
| - | |
| -import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertNull; | |
| - | |
| -/** | |
| - * Test for logging configuration behavior in LookupInvoker. | |
| - * This test verifies that the fix for GH-11199 works correctly. | |
| - */ | |
| -class LookupInvokerLoggingTest { | |
| - | |
| - private String originalSystemProperty; | |
| - | |
| - @BeforeEach | |
| - void setUp() { | |
| - // Save original system property | |
| - originalSystemProperty = System.getProperty(Constants.MAVEN_LOGGER_DEFAULT_LOG_LEVEL); | |
| - // Clear system property to test configuration file loading | |
| - System.clearProperty(Constants.MAVEN_LOGGER_DEFAULT_LOG_LEVEL); | |
| - } | |
| - | |
| - @AfterEach | |
| - void tearDown() { | |
| - // Restore original system property | |
| - if (originalSystemProperty != null) { | |
| - System.setProperty(Constants.MAVEN_LOGGER_DEFAULT_LOG_LEVEL, originalSystemProperty); | |
| - } else { | |
| - System.clearProperty(Constants.MAVEN_LOGGER_DEFAULT_LOG_LEVEL); | |
| - } | |
| - } | |
| - | |
| - @Test | |
| - void testNoCliOptionsDoesNotSetSystemProperty() { | |
| - // Simulate the scenario where no CLI options are specified | |
| - // This should NOT call setRootLoggerLevel, allowing configuration file to take effect | |
| - | |
| - MockInvokerRequest invokerRequest = new MockInvokerRequest(false); // not verbose | |
| - MockOptions options = new MockOptions(false); // not quiet | |
| - MockSlf4jConfiguration slf4jConfiguration = new MockSlf4jConfiguration(); | |
| - | |
| - // Simulate the fixed logic from LookupInvoker.prepareLogging() | |
| - Slf4jConfiguration.Level loggerLevel; | |
| - if (invokerRequest.effectiveVerbose()) { | |
| - loggerLevel = Slf4jConfiguration.Level.DEBUG; | |
| - slf4jConfiguration.setRootLoggerLevel(loggerLevel); | |
| - } else if (options.quiet().orElse(false)) { | |
| - loggerLevel = Slf4jConfiguration.Level.ERROR; | |
| - slf4jConfiguration.setRootLoggerLevel(loggerLevel); | |
| - } else { | |
| - // fall back to default log level specified in conf | |
| - loggerLevel = Slf4jConfiguration.Level.INFO; // default for display purposes | |
| - // Do NOT call setRootLoggerLevel - this is the fix! | |
| - } | |
| - | |
| - // Verify that setRootLoggerLevel was not called | |
| - assertEquals(0, slf4jConfiguration.setRootLoggerLevelCallCount); | |
| - | |
| - // Verify that system property was not set | |
| - assertNull(System.getProperty(Constants.MAVEN_LOGGER_DEFAULT_LOG_LEVEL)); | |
| - } | |
| - | |
| - @Test | |
| - void testVerboseOptionSetsSystemProperty() { | |
| - MockInvokerRequest invokerRequest = new MockInvokerRequest(true); // verbose | |
| - MockOptions options = new MockOptions(false); // not quiet | |
| - MockSlf4jConfiguration slf4jConfiguration = new MockSlf4jConfiguration(); | |
| - | |
| - // Simulate the logic from LookupInvoker.prepareLogging() | |
| - if (invokerRequest.effectiveVerbose()) { | |
| - slf4jConfiguration.setRootLoggerLevel(Slf4jConfiguration.Level.DEBUG); | |
| - } else if (options.quiet().orElse(false)) { | |
| - slf4jConfiguration.setRootLoggerLevel(Slf4jConfiguration.Level.ERROR); | |
| - } | |
| - | |
| - // Verify that setRootLoggerLevel was called | |
| - assertEquals(1, slf4jConfiguration.setRootLoggerLevelCallCount); | |
| - assertEquals(Slf4jConfiguration.Level.DEBUG, slf4jConfiguration.lastSetLevel); | |
| - } | |
| - | |
| - @Test | |
| - void testQuietOptionSetsSystemProperty() { | |
| - MockInvokerRequest invokerRequest = new MockInvokerRequest(false); // not verbose | |
| - MockOptions options = new MockOptions(true); // quiet | |
| - MockSlf4jConfiguration slf4jConfiguration = new MockSlf4jConfiguration(); | |
| - | |
| - // Simulate the logic from LookupInvoker.prepareLogging() | |
| - if (invokerRequest.effectiveVerbose()) { | |
| - slf4jConfiguration.setRootLoggerLevel(Slf4jConfiguration.Level.DEBUG); | |
| - } else if (options.quiet().orElse(false)) { | |
| - slf4jConfiguration.setRootLoggerLevel(Slf4jConfiguration.Level.ERROR); | |
| - } | |
| - | |
| - // Verify that setRootLoggerLevel was called | |
| - assertEquals(1, slf4jConfiguration.setRootLoggerLevelCallCount); | |
| - assertEquals(Slf4jConfiguration.Level.ERROR, slf4jConfiguration.lastSetLevel); | |
| - } | |
| - | |
| - // Mock classes for testing | |
| - private static class MockInvokerRequest { | |
| - private final boolean verbose; | |
| - | |
| - MockInvokerRequest(boolean verbose) { | |
| - this.verbose = verbose; | |
| - } | |
| - | |
| - boolean effectiveVerbose() { | |
| - return verbose; | |
| - } | |
| - } | |
| - | |
| - private static class MockOptions { | |
| - private final boolean quiet; | |
| - | |
| - MockOptions(boolean quiet) { | |
| - this.quiet = quiet; | |
| - } | |
| - | |
| - Optional<Boolean> quiet() { | |
| - return Optional.of(quiet); | |
| - } | |
| - } | |
| - | |
| - private static class MockSlf4jConfiguration implements Slf4jConfiguration { | |
| - int setRootLoggerLevelCallCount = 0; | |
| - Level lastSetLevel = null; | |
| - | |
| - @Override | |
| - public void setRootLoggerLevel(Level level) { | |
| - setRootLoggerLevelCallCount++; | |
| - lastSetLevel = level; | |
| - | |
| - // Simulate what MavenSimpleConfiguration does | |
| - String value = | |
| - switch (level) { | |
| - case DEBUG -> "debug"; | |
| - case INFO -> "info"; | |
| - case ERROR -> "error"; | |
| - }; | |
| - System.setProperty(Constants.MAVEN_LOGGER_DEFAULT_LOG_LEVEL, value); | |
| - } | |
| - | |
| - @Override | |
| - public void activate() { | |
| - // no-op for test | |
| - } | |
| - } | |
| -} | |
| diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvn/MavenInvokerTestSupport.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvn/MavenInvokerTestSupport.java | |
| index 9778cda9c4..a50bc24b61 100644 | |
| --- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvn/MavenInvokerTestSupport.java | |
| +++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvn/MavenInvokerTestSupport.java | |
| @@ -28,7 +28,6 @@ | |
| import java.util.List; | |
| import java.util.Map; | |
| -import eu.maveniverse.maven.mimir.testing.MimirInfuser; | |
| import org.apache.maven.api.cli.Invoker; | |
| import org.apache.maven.api.cli.Parser; | |
| import org.apache.maven.api.cli.ParserRequest; | |
| @@ -99,7 +98,7 @@ protected Map<String, String> invoke(Path cwd, Path userHome, Collection<String> | |
| Files.createDirectories(appJava.getParent()); | |
| Files.writeString(appJava, APP_JAVA_STRING); | |
| - MimirInfuser.infuseUW(userHome); | |
| + MimirInfuser.infuse(userHome); | |
| HashMap<String, String> logs = new HashMap<>(); | |
| Parser parser = createParser(); | |
| diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvn/MimirInfuser.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvn/MimirInfuser.java | |
| new file mode 100644 | |
| index 0000000000..2fa0f034c8 | |
| --- /dev/null | |
| +++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvn/MimirInfuser.java | |
| @@ -0,0 +1,57 @@ | |
| +/* | |
| + * Licensed to the Apache Software Foundation (ASF) under one | |
| + * or more contributor license agreements. See the NOTICE file | |
| + * distributed with this work for additional information | |
| + * regarding copyright ownership. The ASF licenses this file | |
| + * to you under the Apache License, Version 2.0 (the | |
| + * "License"); you may not use this file except in compliance | |
| + * with the License. You may obtain a copy of the License at | |
| + * | |
| + * http://www.apache.org/licenses/LICENSE-2.0 | |
| + * | |
| + * Unless required by applicable law or agreed to in writing, | |
| + * software distributed under the License is distributed on an | |
| + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| + * KIND, either express or implied. See the License for the | |
| + * specific language governing permissions and limitations | |
| + * under the License. | |
| + */ | |
| +package org.apache.maven.cling.invoker.mvn; | |
| + | |
| +import java.io.IOException; | |
| +import java.nio.file.Files; | |
| +import java.nio.file.Path; | |
| +import java.nio.file.StandardCopyOption; | |
| + | |
| +import static java.util.Objects.requireNonNull; | |
| + | |
| +/** | |
| + * Class that sets up Mimir for maven-cli tests IF outer build uses Mimir as well (CI setup). | |
| + */ | |
| +public final class MimirInfuser { | |
| + public static void infuse(Path userHome) throws IOException { | |
| + requireNonNull(userHome); | |
| + // GH CI copies this to place, or user may have it already | |
| + Path realUserWideExtensions = | |
| + Path.of(System.getProperty("user.home")).resolve(".m2").resolve("extensions.xml"); | |
| + if (Files.isRegularFile(realUserWideExtensions)) { | |
| + String realUserWideExtensionsString = Files.readString(realUserWideExtensions); | |
| + if (realUserWideExtensionsString.contains("<groupId>eu.maveniverse.maven.mimir</groupId>") | |
| + && realUserWideExtensionsString.contains("<artifactId>extension</artifactId>")) { | |
| + Path userWideExtensions = userHome.resolve(".m2").resolve("extensions.xml"); | |
| + // some tests do prepare project and user wide extensions; skip those for now | |
| + if (!Files.isRegularFile(userWideExtensions)) { | |
| + Files.createDirectories(userWideExtensions.getParent()); | |
| + Files.copy(realUserWideExtensions, userWideExtensions, StandardCopyOption.REPLACE_EXISTING); | |
| + | |
| + Path mimirProperties = userHome.resolve(".mimir").resolve("mimir.properties"); | |
| + Files.createDirectories(mimirProperties.getParent()); | |
| + Files.copy( | |
| + Path.of("target/test-classes/ut-mimir.properties"), | |
| + mimirProperties, | |
| + StandardCopyOption.REPLACE_EXISTING); | |
| + } | |
| + } | |
| + } | |
| + } | |
| +} | |
| diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/PluginUpgradeCliTest.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/PluginUpgradeCliTest.java | |
| index d890d984bf..32ad1473b9 100644 | |
| --- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/PluginUpgradeCliTest.java | |
| +++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/PluginUpgradeCliTest.java | |
| @@ -18,13 +18,8 @@ | |
| */ | |
| package org.apache.maven.cling.invoker.mvnup; | |
| -import java.io.ByteArrayOutputStream; | |
| -import java.nio.charset.StandardCharsets; | |
| - | |
| import org.apache.commons.cli.ParseException; | |
| import org.apache.maven.api.cli.mvnup.UpgradeOptions; | |
| -import org.apache.maven.cling.MavenUpCling; | |
| -import org.codehaus.plexus.classworlds.ClassWorld; | |
| import org.junit.jupiter.api.Test; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| @@ -195,25 +190,4 @@ void testInterpolationWithPluginsOption() throws ParseException { | |
| assertTrue(interpolated.plugins().isPresent(), "Interpolated options should preserve --plugins"); | |
| assertTrue(interpolated.plugins().get(), "Interpolated --plugins should be true"); | |
| } | |
| - | |
| - @Test | |
| - void helpMentionsInferInDefault() throws Exception { | |
| - ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
| - ByteArrayOutputStream err = new ByteArrayOutputStream(); | |
| - | |
| - int exit = MavenUpCling.main( | |
| - new String[] {"--help"}, | |
| - new ClassWorld("plexus.core", Thread.currentThread().getContextClassLoader()), | |
| - null, | |
| - out, | |
| - err); | |
| - | |
| - String help = out.toString(StandardCharsets.UTF_8); | |
| - assertEquals(0, exit, "mvnup --help should exit 0"); | |
| - assertTrue( | |
| - help.contains("Default behavior: --model --plugins --infer"), | |
| - "Help footer should advertise --infer as part of the defaults"); | |
| - assertFalse( | |
| - help.contains("Default behavior: --model and --plugins"), "Old/incorrect default text must be gone"); | |
| - } | |
| } | |
| diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/GAVUtilsTest.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/GAVUtilsTest.java | |
| index 5585616ec4..1b14223a3a 100644 | |
| --- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/GAVUtilsTest.java | |
| +++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/GAVUtilsTest.java | |
| @@ -233,7 +233,7 @@ void shouldHandleEmptyPOMMap() { | |
| Set<GAV> gavs = GAVUtils.computeAllGAVs(context, pomMap); | |
| assertNotNull(gavs); | |
| - assertTrue(gavs.isEmpty(), "Expected collection to be empty but had " + gavs.size() + " elements: " + gavs); | |
| + assertTrue(gavs.isEmpty()); | |
| } | |
| @Test | |
| diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategyTest.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategyTest.java | |
| index ab20e4c132..2a0c3c1719 100644 | |
| --- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategyTest.java | |
| +++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategyTest.java | |
| @@ -324,467 +324,6 @@ void shouldProvideMeaningfulDescription() { | |
| } | |
| } | |
| - @Nested | |
| - @DisplayName("Phase Upgrades") | |
| - class PhaseUpgradeTests { | |
| - | |
| - @Test | |
| - @DisplayName("should upgrade deprecated phases to Maven 4 equivalents in 4.1.0") | |
| - void shouldUpgradeDeprecatedPhasesIn410() throws Exception { | |
| - Document document = createDocumentWithDeprecatedPhases(); | |
| - Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document); | |
| - | |
| - // Create context with --model-version=4.1.0 option to trigger phase upgrade | |
| - UpgradeOptions options = mock(UpgradeOptions.class); | |
| - when(options.modelVersion()).thenReturn(Optional.of("4.1.0")); | |
| - when(options.all()).thenReturn(Optional.empty()); | |
| - UpgradeContext context = createMockContext(options); | |
| - | |
| - UpgradeResult result = strategy.apply(context, pomMap); | |
| - | |
| - assertTrue(result.success(), "Model upgrade should succeed"); | |
| - assertTrue(result.modifiedCount() > 0, "Should have upgraded phases"); | |
| - | |
| - // Verify phases were upgraded | |
| - verifyCleanPluginPhases(document); | |
| - verifyFailsafePluginPhases(document); | |
| - verifySitePluginPhases(document); | |
| - verifyPluginManagementPhases(document); | |
| - verifyProfilePhases(document); | |
| - } | |
| - | |
| - private Document createDocumentWithDeprecatedPhases() throws Exception { | |
| - String pomXml = | |
| - """ | |
| - <?xml version="1.0" encoding="UTF-8"?> | |
| - <project xmlns="http://maven.apache.org/POM/4.0.0"> | |
| - <modelVersion>4.0.0</modelVersion> | |
| - <groupId>com.example</groupId> | |
| - <artifactId>test-project</artifactId> | |
| - <version>1.0.0</version> | |
| - <build> | |
| - <plugins> | |
| - <plugin> | |
| - <groupId>org.apache.maven.plugins</groupId> | |
| - <artifactId>maven-clean-plugin</artifactId> | |
| - <version>3.2.0</version> | |
| - <executions> | |
| - <execution> | |
| - <id>pre-clean-test</id> | |
| - <phase>pre-clean</phase> | |
| - <goals> | |
| - <goal>clean</goal> | |
| - </goals> | |
| - </execution> | |
| - <execution> | |
| - <id>post-clean-test</id> | |
| - <phase>post-clean</phase> | |
| - <goals> | |
| - <goal>clean</goal> | |
| - </goals> | |
| - </execution> | |
| - </executions> | |
| - </plugin> | |
| - <plugin> | |
| - <groupId>org.apache.maven.plugins</groupId> | |
| - <artifactId>maven-failsafe-plugin</artifactId> | |
| - <version>3.0.0-M7</version> | |
| - <executions> | |
| - <execution> | |
| - <id>pre-integration-test-setup</id> | |
| - <phase>pre-integration-test</phase> | |
| - <goals> | |
| - <goal>integration-test</goal> | |
| - </goals> | |
| - </execution> | |
| - <execution> | |
| - <id>post-integration-test-cleanup</id> | |
| - <phase>post-integration-test</phase> | |
| - <goals> | |
| - <goal>verify</goal> | |
| - </goals> | |
| - </execution> | |
| - </executions> | |
| - </plugin> | |
| - <plugin> | |
| - <groupId>org.apache.maven.plugins</groupId> | |
| - <artifactId>maven-site-plugin</artifactId> | |
| - <version>3.12.1</version> | |
| - <executions> | |
| - <execution> | |
| - <id>pre-site-setup</id> | |
| - <phase>pre-site</phase> | |
| - <goals> | |
| - <goal>site</goal> | |
| - </goals> | |
| - </execution> | |
| - <execution> | |
| - <id>post-site-cleanup</id> | |
| - <phase>post-site</phase> | |
| - <goals> | |
| - <goal>deploy</goal> | |
| - </goals> | |
| - </execution> | |
| - </executions> | |
| - </plugin> | |
| - </plugins> | |
| - <pluginManagement> | |
| - <plugins> | |
| - <plugin> | |
| - <groupId>org.apache.maven.plugins</groupId> | |
| - <artifactId>maven-compiler-plugin</artifactId> | |
| - <version>3.11.0</version> | |
| - <executions> | |
| - <execution> | |
| - <id>pre-clean-compile</id> | |
| - <phase>pre-clean</phase> | |
| - <goals> | |
| - <goal>compile</goal> | |
| - </goals> | |
| - </execution> | |
| - </executions> | |
| - </plugin> | |
| - </plugins> | |
| - </pluginManagement> | |
| - </build> | |
| - <profiles> | |
| - <profile> | |
| - <id>test-profile</id> | |
| - <build> | |
| - <plugins> | |
| - <plugin> | |
| - <groupId>org.apache.maven.plugins</groupId> | |
| - <artifactId>maven-antrun-plugin</artifactId> | |
| - <version>3.1.0</version> | |
| - <executions> | |
| - <execution> | |
| - <id>profile-pre-integration-test</id> | |
| - <phase>pre-integration-test</phase> | |
| - <goals> | |
| - <goal>run</goal> | |
| - </goals> | |
| - </execution> | |
| - </executions> | |
| - </plugin> | |
| - </plugins> | |
| - </build> | |
| - </profile> | |
| - </profiles> | |
| - </project> | |
| - """; | |
| - | |
| - return saxBuilder.build(new StringReader(pomXml)); | |
| - } | |
| - | |
| - private void verifyCleanPluginPhases(Document document) { | |
| - Element root = document.getRootElement(); | |
| - Namespace namespace = root.getNamespace(); | |
| - Element build = root.getChild("build", namespace); | |
| - Element plugins = build.getChild("plugins", namespace); | |
| - | |
| - Element cleanPlugin = plugins.getChildren("plugin", namespace).stream() | |
| - .filter(p -> "maven-clean-plugin" | |
| - .equals(p.getChild("artifactId", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(cleanPlugin); | |
| - | |
| - Element cleanExecutions = cleanPlugin.getChild("executions", namespace); | |
| - Element preCleanExecution = cleanExecutions.getChildren("execution", namespace).stream() | |
| - .filter(e -> | |
| - "pre-clean-test".equals(e.getChild("id", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(preCleanExecution); | |
| - assertEquals( | |
| - "before:clean", | |
| - preCleanExecution.getChild("phase", namespace).getText()); | |
| - | |
| - Element postCleanExecution = cleanExecutions.getChildren("execution", namespace).stream() | |
| - .filter(e -> | |
| - "post-clean-test".equals(e.getChild("id", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(postCleanExecution); | |
| - assertEquals( | |
| - "after:clean", | |
| - postCleanExecution.getChild("phase", namespace).getText()); | |
| - } | |
| - | |
| - private void verifyFailsafePluginPhases(Document document) { | |
| - Element root = document.getRootElement(); | |
| - Namespace namespace = root.getNamespace(); | |
| - Element build = root.getChild("build", namespace); | |
| - Element plugins = build.getChild("plugins", namespace); | |
| - | |
| - Element failsafePlugin = plugins.getChildren("plugin", namespace).stream() | |
| - .filter(p -> "maven-failsafe-plugin" | |
| - .equals(p.getChild("artifactId", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(failsafePlugin); | |
| - | |
| - Element failsafeExecutions = failsafePlugin.getChild("executions", namespace); | |
| - Element preIntegrationExecution = failsafeExecutions.getChildren("execution", namespace).stream() | |
| - .filter(e -> "pre-integration-test-setup" | |
| - .equals(e.getChild("id", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(preIntegrationExecution); | |
| - assertEquals( | |
| - "before:integration-test", | |
| - preIntegrationExecution.getChild("phase", namespace).getText()); | |
| - | |
| - Element postIntegrationExecution = failsafeExecutions.getChildren("execution", namespace).stream() | |
| - .filter(e -> "post-integration-test-cleanup" | |
| - .equals(e.getChild("id", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(postIntegrationExecution); | |
| - assertEquals( | |
| - "after:integration-test", | |
| - postIntegrationExecution.getChild("phase", namespace).getText()); | |
| - } | |
| - | |
| - private void verifySitePluginPhases(Document document) { | |
| - Element root = document.getRootElement(); | |
| - Namespace namespace = root.getNamespace(); | |
| - Element build = root.getChild("build", namespace); | |
| - Element plugins = build.getChild("plugins", namespace); | |
| - | |
| - Element sitePlugin = plugins.getChildren("plugin", namespace).stream() | |
| - .filter(p -> "maven-site-plugin" | |
| - .equals(p.getChild("artifactId", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(sitePlugin); | |
| - | |
| - Element siteExecutions = sitePlugin.getChild("executions", namespace); | |
| - Element preSiteExecution = siteExecutions.getChildren("execution", namespace).stream() | |
| - .filter(e -> | |
| - "pre-site-setup".equals(e.getChild("id", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(preSiteExecution); | |
| - assertEquals( | |
| - "before:site", preSiteExecution.getChild("phase", namespace).getText()); | |
| - | |
| - Element postSiteExecution = siteExecutions.getChildren("execution", namespace).stream() | |
| - .filter(e -> "post-site-cleanup" | |
| - .equals(e.getChild("id", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(postSiteExecution); | |
| - assertEquals( | |
| - "after:site", postSiteExecution.getChild("phase", namespace).getText()); | |
| - } | |
| - | |
| - private void verifyPluginManagementPhases(Document document) { | |
| - Element root = document.getRootElement(); | |
| - Namespace namespace = root.getNamespace(); | |
| - Element build = root.getChild("build", namespace); | |
| - Element pluginManagement = build.getChild("pluginManagement", namespace); | |
| - Element managedPlugins = pluginManagement.getChild("plugins", namespace); | |
| - Element compilerPlugin = managedPlugins.getChildren("plugin", namespace).stream() | |
| - .filter(p -> "maven-compiler-plugin" | |
| - .equals(p.getChild("artifactId", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(compilerPlugin); | |
| - | |
| - Element compilerExecutions = compilerPlugin.getChild("executions", namespace); | |
| - Element preCleanCompileExecution = compilerExecutions.getChildren("execution", namespace).stream() | |
| - .filter(e -> "pre-clean-compile" | |
| - .equals(e.getChild("id", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(preCleanCompileExecution); | |
| - assertEquals( | |
| - "before:clean", | |
| - preCleanCompileExecution.getChild("phase", namespace).getText()); | |
| - } | |
| - | |
| - private void verifyProfilePhases(Document document) { | |
| - Element root = document.getRootElement(); | |
| - Namespace namespace = root.getNamespace(); | |
| - Element profiles = root.getChild("profiles", namespace); | |
| - Element profile = profiles.getChild("profile", namespace); | |
| - Element profileBuild = profile.getChild("build", namespace); | |
| - Element profilePlugins = profileBuild.getChild("plugins", namespace); | |
| - Element antrunPlugin = profilePlugins.getChildren("plugin", namespace).stream() | |
| - .filter(p -> "maven-antrun-plugin" | |
| - .equals(p.getChild("artifactId", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(antrunPlugin); | |
| - | |
| - Element antrunExecutions = antrunPlugin.getChild("executions", namespace); | |
| - Element profilePreIntegrationExecution = antrunExecutions.getChildren("execution", namespace).stream() | |
| - .filter(e -> "profile-pre-integration-test" | |
| - .equals(e.getChild("id", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(profilePreIntegrationExecution); | |
| - assertEquals( | |
| - "before:integration-test", | |
| - profilePreIntegrationExecution.getChild("phase", namespace).getText()); | |
| - } | |
| - | |
| - @Test | |
| - @DisplayName("should not upgrade phases when upgrading to 4.0.0") | |
| - void shouldNotUpgradePhasesWhenUpgradingTo400() throws Exception { | |
| - String pomXml = | |
| - """ | |
| - <?xml version="1.0" encoding="UTF-8"?> | |
| - <project xmlns="http://maven.apache.org/POM/4.0.0"> | |
| - <modelVersion>4.0.0</modelVersion> | |
| - <groupId>com.example</groupId> | |
| - <artifactId>test-project</artifactId> | |
| - <version>1.0.0</version> | |
| - <build> | |
| - <plugins> | |
| - <plugin> | |
| - <groupId>org.apache.maven.plugins</groupId> | |
| - <artifactId>maven-clean-plugin</artifactId> | |
| - <version>3.2.0</version> | |
| - <executions> | |
| - <execution> | |
| - <id>pre-clean-test</id> | |
| - <phase>pre-clean</phase> | |
| - <goals> | |
| - <goal>clean</goal> | |
| - </goals> | |
| - </execution> | |
| - </executions> | |
| - </plugin> | |
| - </plugins> | |
| - </build> | |
| - </project> | |
| - """; | |
| - | |
| - Document document = saxBuilder.build(new StringReader(pomXml)); | |
| - Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document); | |
| - | |
| - // Create context with --model-version=4.0.0 option (no phase upgrade) | |
| - UpgradeOptions options = mock(UpgradeOptions.class); | |
| - when(options.modelVersion()).thenReturn(Optional.of("4.0.0")); | |
| - when(options.all()).thenReturn(Optional.empty()); | |
| - UpgradeContext context = createMockContext(options); | |
| - | |
| - UpgradeResult result = strategy.apply(context, pomMap); | |
| - | |
| - assertTrue(result.success(), "Model upgrade should succeed"); | |
| - | |
| - // Verify phases were NOT upgraded (should remain as pre-clean) | |
| - Element root = document.getRootElement(); | |
| - Namespace namespace = root.getNamespace(); | |
| - Element build = root.getChild("build", namespace); | |
| - Element plugins = build.getChild("plugins", namespace); | |
| - Element cleanPlugin = plugins.getChild("plugin", namespace); | |
| - Element executions = cleanPlugin.getChild("executions", namespace); | |
| - Element execution = executions.getChild("execution", namespace); | |
| - Element phase = execution.getChild("phase", namespace); | |
| - | |
| - assertEquals("pre-clean", phase.getText(), "Phase should remain as pre-clean for 4.0.0"); | |
| - } | |
| - | |
| - @Test | |
| - @DisplayName("should preserve non-deprecated phases") | |
| - void shouldPreserveNonDeprecatedPhases() throws Exception { | |
| - String pomXml = | |
| - """ | |
| - <?xml version="1.0" encoding="UTF-8"?> | |
| - <project xmlns="http://maven.apache.org/POM/4.0.0"> | |
| - <modelVersion>4.0.0</modelVersion> | |
| - <groupId>com.example</groupId> | |
| - <artifactId>test-project</artifactId> | |
| - <version>1.0.0</version> | |
| - <build> | |
| - <plugins> | |
| - <plugin> | |
| - <groupId>org.apache.maven.plugins</groupId> | |
| - <artifactId>maven-compiler-plugin</artifactId> | |
| - <version>3.11.0</version> | |
| - <executions> | |
| - <execution> | |
| - <id>compile-test</id> | |
| - <phase>compile</phase> | |
| - <goals> | |
| - <goal>compile</goal> | |
| - </goals> | |
| - </execution> | |
| - <execution> | |
| - <id>test-compile-test</id> | |
| - <phase>test-compile</phase> | |
| - <goals> | |
| - <goal>testCompile</goal> | |
| - </goals> | |
| - </execution> | |
| - <execution> | |
| - <id>package-test</id> | |
| - <phase>package</phase> | |
| - <goals> | |
| - <goal>compile</goal> | |
| - </goals> | |
| - </execution> | |
| - </executions> | |
| - </plugin> | |
| - </plugins> | |
| - </build> | |
| - </project> | |
| - """; | |
| - | |
| - Document document = saxBuilder.build(new StringReader(pomXml)); | |
| - Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document); | |
| - | |
| - // Create context with --model-version=4.1.0 option | |
| - UpgradeOptions options = mock(UpgradeOptions.class); | |
| - when(options.modelVersion()).thenReturn(Optional.of("4.1.0")); | |
| - when(options.all()).thenReturn(Optional.empty()); | |
| - UpgradeContext context = createMockContext(options); | |
| - | |
| - UpgradeResult result = strategy.apply(context, pomMap); | |
| - | |
| - assertTrue(result.success(), "Model upgrade should succeed"); | |
| - | |
| - // Verify non-deprecated phases were preserved | |
| - Element root = document.getRootElement(); | |
| - Namespace namespace = root.getNamespace(); | |
| - Element build = root.getChild("build", namespace); | |
| - Element plugins = build.getChild("plugins", namespace); | |
| - Element compilerPlugin = plugins.getChild("plugin", namespace); | |
| - Element executions = compilerPlugin.getChild("executions", namespace); | |
| - | |
| - Element compileExecution = executions.getChildren("execution", namespace).stream() | |
| - .filter(e -> | |
| - "compile-test".equals(e.getChild("id", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(compileExecution); | |
| - assertEquals( | |
| - "compile", compileExecution.getChild("phase", namespace).getText()); | |
| - | |
| - Element testCompileExecution = executions.getChildren("execution", namespace).stream() | |
| - .filter(e -> "test-compile-test" | |
| - .equals(e.getChild("id", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(testCompileExecution); | |
| - assertEquals( | |
| - "test-compile", | |
| - testCompileExecution.getChild("phase", namespace).getText()); | |
| - | |
| - Element packageExecution = executions.getChildren("execution", namespace).stream() | |
| - .filter(e -> | |
| - "package-test".equals(e.getChild("id", namespace).getText())) | |
| - .findFirst() | |
| - .orElse(null); | |
| - assertNotNull(packageExecution); | |
| - assertEquals( | |
| - "package", packageExecution.getChild("phase", namespace).getText()); | |
| - } | |
| - } | |
| - | |
| @Nested | |
| @DisplayName("Downgrade Handling") | |
| class DowngradeHandlingTests { | |
| diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/ModelVersionUtilsTest.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/ModelVersionUtilsTest.java | |
| index 531c52c1ab..215e6b8e48 100644 | |
| --- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/ModelVersionUtilsTest.java | |
| +++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/ModelVersionUtilsTest.java | |
| @@ -129,14 +129,14 @@ void shouldDetectVersionFromNamespaceWhenModelVersionMissing() throws Exception | |
| class ModelVersionValidationTests { | |
| @ParameterizedTest | |
| - @ValueSource(strings = {"4.0.0", "4.1.0", "4.2.0"}) | |
| + @ValueSource(strings = {"4.0.0", "4.1.0"}) | |
| @DisplayName("should validate supported model versions") | |
| void shouldValidateSupportedModelVersions(String version) { | |
| assertTrue(ModelVersionUtils.isValidModelVersion(version)); | |
| } | |
| @ParameterizedTest | |
| - @ValueSource(strings = {"3.0.0", "5.0.0", "2.0.0", "6.0.0"}) | |
| + @ValueSource(strings = {"3.0.0", "5.0.0", "4.2.0", "2.0.0", "6.0.0"}) | |
| @DisplayName("should reject unsupported model versions") | |
| void shouldRejectUnsupportedModelVersions(String version) { | |
| assertFalse(ModelVersionUtils.isValidModelVersion(version)); | |
| @@ -366,7 +366,7 @@ class SchemaLocationOperationTests { | |
| void shouldGetSchemaLocationForModelVersion() { | |
| String schemaLocation410 = ModelVersionUtils.getSchemaLocationForModelVersion("4.1.0"); | |
| assertNotNull(schemaLocation410); | |
| - assertTrue(schemaLocation410.contains("4.1.0"), "Expected " + schemaLocation410 + " to contain " + "4.1.0"); | |
| + assertTrue(schemaLocation410.contains("4.1.0")); | |
| } | |
| @Test | |
| @@ -374,18 +374,18 @@ void shouldGetSchemaLocationForModelVersion() { | |
| void shouldGetSchemaLocationFor400() { | |
| String schemaLocation400 = ModelVersionUtils.getSchemaLocationForModelVersion("4.0.0"); | |
| assertNotNull(schemaLocation400); | |
| - assertTrue(schemaLocation400.contains("4.0.0"), "Expected " + schemaLocation400 + " to contain " + "4.0.0"); | |
| + assertTrue(schemaLocation400.contains("4.0.0")); | |
| } | |
| @Test | |
| @DisplayName("should handle unknown model version in schema location") | |
| void shouldHandleUnknownModelVersionInSchemaLocation() { | |
| String schemaLocation = ModelVersionUtils.getSchemaLocationForModelVersion("5.0.0"); | |
| - assertNotNull(schemaLocation); // Should return 4.2.0 schema for newer versions | |
| - // The method returns the 4.2.0 schema location for versions newer than 4.1.0 | |
| + assertNotNull(schemaLocation); // Should return 4.1.0 schema for newer versions | |
| + // The method returns the 4.1.0 schema location for versions newer than 4.1.0 | |
| assertTrue( | |
| - schemaLocation.contains("4.2.0"), | |
| - "Expected schema location to contain '4.2.0', but was: " + schemaLocation); | |
| + schemaLocation.contains("4.1.0"), | |
| + "Expected schema location to contain '4.1.0', but was: " + schemaLocation); | |
| } | |
| } | |
| diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/StrategyOrchestratorTest.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/StrategyOrchestratorTest.java | |
| index 452a16c7fd..88ceb5b548 100644 | |
| --- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/StrategyOrchestratorTest.java | |
| +++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/StrategyOrchestratorTest.java | |
| @@ -24,6 +24,7 @@ | |
| import java.util.Map; | |
| import java.util.Set; | |
| +import org.apache.maven.api.cli.mvnup.UpgradeOptions; | |
| import org.apache.maven.cling.invoker.mvnup.UpgradeContext; | |
| import org.jdom2.Document; | |
| import org.junit.jupiter.api.BeforeEach; | |
| @@ -60,6 +61,14 @@ private UpgradeContext createMockContext() { | |
| return TestUtils.createMockContext(); | |
| } | |
| + private UpgradeContext createMockContext(UpgradeOptions options) { | |
| + return TestUtils.createMockContext(options); | |
| + } | |
| + | |
| + private UpgradeOptions createDefaultOptions() { | |
| + return TestUtils.createDefaultOptions(); | |
| + } | |
| + | |
| @Nested | |
| @DisplayName("Strategy Execution") | |
| class StrategyExecutionTests { | |
| diff --git a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeWorkflowIntegrationTest.java b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeWorkflowIntegrationTest.java | |
| index ea75e835ba..5a652d557f 100644 | |
| --- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeWorkflowIntegrationTest.java | |
| +++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeWorkflowIntegrationTest.java | |
| @@ -165,9 +165,7 @@ void applyShouldModifyFiles() throws Exception { | |
| // Verify POM was potentially modified (depending on strategy applicability) | |
| String pomContent = Files.readString(pomFile); | |
| - assertTrue( | |
| - pomContent.contains("<groupId>com.example</groupId>"), | |
| - "Expected " + pomContent + " to contain " + "<groupId>com.example</groupId>"); | |
| + assertTrue(pomContent.contains("<groupId>com.example</groupId>")); | |
| // Note: The exact modifications depend on which strategies are applicable | |
| // This test mainly verifies that apply goal can modify files | |
| } | |
| diff --git a/impl/maven-cli/src/test/resources-filtered/ut-mimir.properties b/impl/maven-cli/src/test/resources-filtered/ut-mimir.properties | |
| new file mode 100644 | |
| index 0000000000..e502ef6482 | |
| --- /dev/null | |
| +++ b/impl/maven-cli/src/test/resources-filtered/ut-mimir.properties | |
| @@ -0,0 +1,8 @@ | |
| +# Used IF outer build uses Mimir (CI setup) | |
| + | |
| +# we change user.home in IT, so we want this interpolated | |
| +mimir.daemon.basedir=${user.home}/.mimir | |
| +# outer build already did this | |
| +mimir.daemon.autoupdate=false | |
| +# outer build already did this | |
| +mimir.daemon.autostart=false | |
| \ No newline at end of file | |
| diff --git a/impl/maven-core/pom.xml b/impl/maven-core/pom.xml | |
| index 534838b51d..08da7144ae 100644 | |
| --- a/impl/maven-core/pom.xml | |
| +++ b/impl/maven-core/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-impl-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-core</artifactId> | |
| @@ -199,7 +199,11 @@ under the License. | |
| <artifactId>junit-jupiter-params</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| - | |
| + <dependency> | |
| + <groupId>org.hamcrest</groupId> | |
| + <artifactId>hamcrest</artifactId> | |
| + <scope>test</scope> | |
| + </dependency> | |
| <dependency> | |
| <groupId>org.slf4j</groupId> | |
| <artifactId>slf4j-simple</artifactId> | |
| @@ -212,7 +216,7 @@ under the License. | |
| </dependency> | |
| <dependency> | |
| <groupId>org.xmlunit</groupId> | |
| - <artifactId>xmlunit-core</artifactId> | |
| + <artifactId>xmlunit-assertj</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| <dependency> | |
| @@ -231,20 +235,19 @@ under the License. | |
| <artifactId>mockito-core</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| - | |
| <dependency> | |
| - <groupId>org.openjdk.jmh</groupId> | |
| - <artifactId>jmh-core</artifactId> | |
| + <groupId>org.assertj</groupId> | |
| + <artifactId>assertj-core</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| <dependency> | |
| <groupId>org.openjdk.jmh</groupId> | |
| - <artifactId>jmh-generator-annprocess</artifactId> | |
| + <artifactId>jmh-core</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| <dependency> | |
| - <groupId>com.google.jimfs</groupId> | |
| - <artifactId>jimfs</artifactId> | |
| + <groupId>org.openjdk.jmh</groupId> | |
| + <artifactId>jmh-generator-annprocess</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/ReactorReader.java b/impl/maven-core/src/main/java/org/apache/maven/ReactorReader.java | |
| index fdca07ee80..db2efa7720 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/ReactorReader.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/ReactorReader.java | |
| @@ -330,18 +330,6 @@ private static boolean isTestArtifact(Artifact artifact) { | |
| } | |
| private File findInProjectLocalRepository(Artifact artifact) { | |
| - // Prefer the consumer POM when resolving POMs from the project-local repository, | |
| - // to avoid treating a build POM as a repository (consumer) POM. | |
| - if ("pom".equals(artifact.getExtension())) { | |
| - String classifier = artifact.getClassifier(); | |
| - if (classifier == null || classifier.isEmpty()) { | |
| - Path consumer = getArtifactPath( | |
| - artifact.getGroupId(), artifact.getArtifactId(), artifact.getBaseVersion(), "consumer", "pom"); | |
| - if (Files.isRegularFile(consumer)) { | |
| - return consumer.toFile(); | |
| - } | |
| - } | |
| - } | |
| Path target = getArtifactPath(artifact); | |
| return Files.isRegularFile(target) ? target.toFile() : null; | |
| } | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/RepositoryUtils.java b/impl/maven-core/src/main/java/org/apache/maven/RepositoryUtils.java | |
| index 5836b78357..ec9af20fc4 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/RepositoryUtils.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/RepositoryUtils.java | |
| @@ -259,15 +259,13 @@ public static ArtifactHandler newHandler(Artifact artifact) { | |
| } | |
| public static ArtifactType newArtifactType(String id, ArtifactHandler handler) { | |
| - return handler != null | |
| - ? new DefaultArtifactType( | |
| - id, | |
| - handler.getExtension(), | |
| - handler.getClassifier(), | |
| - handler.getLanguage(), | |
| - handler.isAddedToClasspath(), | |
| - handler.isIncludesDependencies()) | |
| - : null; | |
| + return new DefaultArtifactType( | |
| + id, | |
| + handler.getExtension(), | |
| + handler.getClassifier(), | |
| + handler.getLanguage(), | |
| + handler.isAddedToClasspath(), | |
| + handler.isIncludesDependencies()); | |
| } | |
| public static Dependency toDependency( | |
| @@ -277,8 +275,8 @@ public static Dependency toDependency( | |
| stereotype = new DefaultArtifactType(dependency.getType()); | |
| } | |
| - boolean system = dependency.getSystemPath() != null | |
| - && !dependency.getSystemPath().isEmpty(); | |
| + boolean system = | |
| + dependency.getSystemPath() != null && dependency.getSystemPath().length() > 0; | |
| Map<String, String> props = null; | |
| if (system) { | |
| @@ -309,12 +307,23 @@ private static Exclusion toExclusion(org.apache.maven.model.Exclusion exclusion) | |
| return new Exclusion(exclusion.getGroupId(), exclusion.getArtifactId(), "*", "*"); | |
| } | |
| - /** | |
| - * @deprecated Use by maven-artifact-transfer. | |
| - */ | |
| - @Deprecated | |
| public static ArtifactTypeRegistry newArtifactTypeRegistry(ArtifactHandlerManager handlerManager) { | |
| - return typeId -> newArtifactType(typeId, handlerManager.getArtifactHandler(typeId)); | |
| + return new MavenArtifactTypeRegistry(handlerManager); | |
| + } | |
| + | |
| + static class MavenArtifactTypeRegistry implements ArtifactTypeRegistry { | |
| + | |
| + private final ArtifactHandlerManager handlerManager; | |
| + | |
| + MavenArtifactTypeRegistry(ArtifactHandlerManager handlerManager) { | |
| + this.handlerManager = handlerManager; | |
| + } | |
| + | |
| + @Override | |
| + public ArtifactType get(String stereotypeId) { | |
| + ArtifactHandler handler = handlerManager.getArtifactHandler(stereotypeId); | |
| + return newArtifactType(stereotypeId, handler); | |
| + } | |
| } | |
| public static Collection<Artifact> toArtifacts(Collection<org.apache.maven.artifact.Artifact> artifactsToConvert) { | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/MultilineMessageHelper.java b/impl/maven-core/src/main/java/org/apache/maven/internal/MultilineMessageHelper.java | |
| index 723d659c93..9ff2d200e0 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/internal/MultilineMessageHelper.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/MultilineMessageHelper.java | |
| @@ -52,12 +52,12 @@ public static List<String> format(String... lines) { | |
| sb.setLength(0); | |
| String[] words = S_FILTER.split(line); | |
| for (String word : words) { | |
| - if (sb.length() >= remainder - word.length() - (!sb.isEmpty() ? 1 : 0)) { | |
| + if (sb.length() >= remainder - word.length() - (sb.length() > 0 ? 1 : 0)) { | |
| repeat(sb, ' ', remainder - sb.length()); | |
| result.add(BOX_CHAR + " " + sb + " " + BOX_CHAR); | |
| sb.setLength(0); | |
| } | |
| - if (!sb.isEmpty()) { | |
| + if (sb.length() > 0) { | |
| sb.append(' '); | |
| } | |
| sb.append(word); | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java b/impl/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java | |
| index 541c8364ed..6638b6a46f 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java | |
| @@ -63,7 +63,6 @@ | |
| import org.eclipse.aether.util.graph.version.HighestVersionFilter; | |
| import org.eclipse.aether.util.graph.version.LowestVersionFilter; | |
| import org.eclipse.aether.util.graph.version.PredicateVersionFilter; | |
| -import org.eclipse.aether.util.graph.version.SnapshotVersionFilter; | |
| import org.eclipse.aether.util.listener.ChainedRepositoryListener; | |
| import org.eclipse.aether.util.repository.AuthenticationBuilder; | |
| import org.eclipse.aether.util.repository.ChainedLocalRepositoryManager; | |
| @@ -436,8 +435,6 @@ private VersionFilter buildVersionFilter(String filterExpression) { | |
| filters.add(new LowestVersionFilter(num)); | |
| } else if ("s".equals(expression)) { | |
| filters.add(new ContextualSnapshotVersionFilter()); | |
| - } else if ("ns".equals(expression)) { | |
| - filters.add(new SnapshotVersionFilter()); | |
| } else if (expression.startsWith("e(") && expression.endsWith(")")) { | |
| Artifact artifact = new DefaultArtifact(expression.substring(2, expression.length() - 1)); | |
| VersionRange versionRange = | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/aether/TypeRegistryAdapter.java b/impl/maven-core/src/main/java/org/apache/maven/internal/aether/TypeRegistryAdapter.java | |
| index b802e8a44c..96e65dfcea 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/internal/aether/TypeRegistryAdapter.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/aether/TypeRegistryAdapter.java | |
| @@ -40,12 +40,15 @@ public ArtifactType get(String typeId) { | |
| if (type instanceof ArtifactType artifactType) { | |
| return artifactType; | |
| } | |
| - return new DefaultType( | |
| - type.id(), | |
| - type.getLanguage(), | |
| - type.getExtension(), | |
| - type.getClassifier(), | |
| - type.isIncludesDependencies(), | |
| - type.getPathTypes().toArray(new PathType[0])); | |
| + if (type != null) { | |
| + return new DefaultType( | |
| + type.id(), | |
| + type.getLanguage(), | |
| + type.getExtension(), | |
| + type.getClassifier(), | |
| + type.isIncludesDependencies(), | |
| + type.getPathTypes().toArray(new PathType[0])); | |
| + } | |
| + return null; | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java | |
| index 2b8692a86c..0f20222060 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java | |
| @@ -30,24 +30,17 @@ | |
| import org.apache.maven.api.Artifact; | |
| import org.apache.maven.api.ProducedArtifact; | |
| -import org.apache.maven.api.Service; | |
| import org.apache.maven.api.annotations.Nonnull; | |
| import org.apache.maven.api.di.SessionScoped; | |
| import org.apache.maven.api.services.ArtifactManager; | |
| import org.apache.maven.impl.DefaultArtifact; | |
| -import org.apache.maven.impl.InternalSession; | |
| import org.apache.maven.project.MavenProject; | |
| import org.eclipse.sisu.Typed; | |
| import static java.util.Objects.requireNonNull; | |
| -/** | |
| - * This implementation of {@code ArtifactManager} is explicitly bound to | |
| - * both {@code ArtifactManager} and {@code Service} interfaces so that it can be retrieved using | |
| - * {@link InternalSession#getAllServices()}. | |
| - */ | |
| @Named | |
| -@Typed({ArtifactManager.class, Service.class}) | |
| +@Typed | |
| @SessionScoped | |
| public class DefaultArtifactManager implements ArtifactManager { | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java | |
| index a0b9ff8a0a..84abf9fbb7 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java | |
| @@ -92,7 +92,7 @@ public class DefaultLifecycleRegistry implements LifecycleRegistry { | |
| + ":default-lifecycle-bindings"; | |
| public static final InputLocation DEFAULT_LIFECYCLE_INPUT_LOCATION = | |
| - InputLocation.of(InputSource.of(DEFAULT_LIFECYCLE_MODELID, null)); | |
| + new InputLocation(new InputSource(DEFAULT_LIFECYCLE_MODELID, null)); | |
| public static final String SCOPE_COMPILE = DependencyScope.COMPILE.id(); | |
| public static final String SCOPE_RUNTIME = DependencyScope.RUNTIME.id(); | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java | |
| index 62ae3b9db9..b51241642a 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java | |
| @@ -189,7 +189,8 @@ public Severity getSeverity() { | |
| public Optional<DependencyResolverResult> getDependencyResolverResult() { | |
| return Optional.ofNullable(res.getDependencyResolutionResult()) | |
| .map(r -> new DefaultDependencyResolverResult( | |
| - null, r.getCollectionErrors(), session.getNode(r.getDependencyGraph()), 0)); | |
| + // TODO: this should not be null | |
| + null, null, r.getCollectionErrors(), session.getNode(r.getDependencyGraph()), 0)); | |
| } | |
| }; | |
| } catch (ProjectBuildingException e) { | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java | |
| index 7c495a7344..c7d7505724 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java | |
| @@ -38,7 +38,6 @@ | |
| import org.apache.maven.api.Project; | |
| import org.apache.maven.api.ProjectScope; | |
| import org.apache.maven.api.RemoteRepository; | |
| -import org.apache.maven.api.Service; | |
| import org.apache.maven.api.SourceRoot; | |
| import org.apache.maven.api.annotations.Nonnull; | |
| import org.apache.maven.api.di.SessionScoped; | |
| @@ -53,13 +52,8 @@ | |
| import static java.util.Objects.requireNonNull; | |
| import static org.apache.maven.internal.impl.CoreUtils.map; | |
| -/** | |
| - * This implementation of {@code ProjectManager} is explicitly bound to | |
| - * both {@code ProjectManager} and {@code Service} interfaces so that it can be retrieved using | |
| - * {@link InternalSession#getAllServices()}. | |
| - */ | |
| @Named | |
| -@Typed({ProjectManager.class, Service.class}) | |
| +@Typed | |
| @SessionScoped | |
| public class DefaultProjectManager implements ProjectManager { | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/SisuDiBridgeModule.java b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/SisuDiBridgeModule.java | |
| index eeb6215f93..c1e020b3ed 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/SisuDiBridgeModule.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/SisuDiBridgeModule.java | |
| @@ -25,7 +25,6 @@ | |
| import java.lang.reflect.Field; | |
| import java.util.ArrayList; | |
| import java.util.HashMap; | |
| -import java.util.HashSet; | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.Set; | |
| @@ -128,7 +127,7 @@ private static <U> com.google.inject.Key<U> toGuiceKey(Key<U> key) { | |
| } else if (key.getQualifier() instanceof Annotation a) { | |
| return (com.google.inject.Key<U>) com.google.inject.Key.get(key.getType(), a); | |
| } else { | |
| - return (com.google.inject.Key<U>) com.google.inject.Key.get(key.getType(), Named.class); | |
| + return (com.google.inject.Key<U>) com.google.inject.Key.get(key.getType()); | |
| } | |
| } | |
| @@ -204,22 +203,6 @@ private <Q> Supplier<Q> getBeanSupplier(Dependency<Q> dep, Key<Q> key) { | |
| } | |
| } | |
| - @Override | |
| - public <T> Set<Binding<T>> getAllBindings(Class<T> clazz) { | |
| - Key<T> key = Key.of(clazz); | |
| - Set<Binding<T>> bindings = new HashSet<>(); | |
| - Set<Binding<T>> diBindings = super.getBindings(key); | |
| - if (diBindings != null) { | |
| - bindings.addAll(diBindings); | |
| - } | |
| - for (var bean : locator.get().locate(toGuiceKey(key))) { | |
| - if (isPlexusBean(bean)) { | |
| - bindings.add(new BindingToBeanEntry<>(Key.of(bean.getImplementationClass())).toBeanEntry(bean)); | |
| - } | |
| - } | |
| - return bindings; | |
| - } | |
| - | |
| private <Q> Supplier<Q> getListSupplier(Key<Q> key) { | |
| Key<Object> elementType = key.getTypeParameter(0); | |
| return () -> { | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/ConsumerPomArtifactTransformer.java b/impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/ConsumerPomArtifactTransformer.java | |
| index 347eef4f75..4b2722405c 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/ConsumerPomArtifactTransformer.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/ConsumerPomArtifactTransformer.java | |
| @@ -129,8 +129,7 @@ private void doDeleteFiles() { | |
| @Override | |
| public InstallRequest remapInstallArtifacts(RepositorySystemSession session, InstallRequest request) { | |
| if (consumerPomPresent(request.getArtifacts())) { | |
| - // For install, we always include build POMs as they may be needed locally | |
| - request.setArtifacts(replacePom(request.getArtifacts(), true)); | |
| + request.setArtifacts(replacePom(request.getArtifacts())); | |
| } | |
| return request; | |
| } | |
| @@ -138,8 +137,7 @@ public InstallRequest remapInstallArtifacts(RepositorySystemSession session, Ins | |
| @Override | |
| public DeployRequest remapDeployArtifacts(RepositorySystemSession session, DeployRequest request) { | |
| if (consumerPomPresent(request.getArtifacts())) { | |
| - boolean deployBuildPom = Features.deployBuildPom(session.getConfigProperties()); | |
| - request.setArtifacts(replacePom(request.getArtifacts(), deployBuildPom)); | |
| + request.setArtifacts(replacePom(request.getArtifacts())); | |
| } | |
| return request; | |
| } | |
| @@ -149,7 +147,7 @@ private boolean consumerPomPresent(Collection<Artifact> artifacts) { | |
| .anyMatch(a -> "pom".equals(a.getExtension()) && CONSUMER_POM_CLASSIFIER.equals(a.getClassifier())); | |
| } | |
| - private Collection<Artifact> replacePom(Collection<Artifact> artifacts, boolean deployBuildPom) { | |
| + private Collection<Artifact> replacePom(Collection<Artifact> artifacts) { | |
| List<Artifact> consumers = new ArrayList<>(); | |
| List<Artifact> mains = new ArrayList<>(); | |
| for (Artifact artifact : artifacts) { | |
| @@ -165,22 +163,17 @@ private Collection<Artifact> replacePom(Collection<Artifact> artifacts, boolean | |
| ArrayList<Artifact> result = new ArrayList<>(artifacts); | |
| for (Artifact main : mains) { | |
| result.remove(main); | |
| - if (deployBuildPom) { | |
| - // Add the main POM as a build POM with "build" classifier | |
| - result.add(new DefaultArtifact( | |
| - main.getGroupId(), | |
| - main.getArtifactId(), | |
| - BUILD_POM_CLASSIFIER, | |
| - main.getExtension(), | |
| - main.getVersion(), | |
| - main.getProperties(), | |
| - main.getPath())); | |
| - } | |
| - // If deployBuildPom is false, we simply don't add the build POM to the result | |
| + result.add(new DefaultArtifact( | |
| + main.getGroupId(), | |
| + main.getArtifactId(), | |
| + BUILD_POM_CLASSIFIER, | |
| + main.getExtension(), | |
| + main.getVersion(), | |
| + main.getProperties(), | |
| + main.getPath())); | |
| } | |
| for (Artifact consumer : consumers) { | |
| result.remove(consumer); | |
| - // Replace the consumer POM as the main POM (no classifier) | |
| result.add(new DefaultArtifact( | |
| consumer.getGroupId(), | |
| consumer.getArtifactId(), | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java b/impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java | |
| index 0cd11ffcd7..4056746ae9 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java | |
| @@ -29,7 +29,6 @@ | |
| import java.util.stream.Collectors; | |
| import org.apache.maven.api.ArtifactCoordinates; | |
| -import org.apache.maven.api.DependencyScope; | |
| import org.apache.maven.api.Node; | |
| import org.apache.maven.api.PathScope; | |
| import org.apache.maven.api.SessionData; | |
| @@ -115,7 +114,7 @@ private Model buildEffectiveModel(RepositorySystemSession session, Path src) thr | |
| ArtifactCoordinates artifact = iSession.createArtifactCoordinates( | |
| model.getGroupId(), model.getArtifactId(), model.getVersion(), null); | |
| Node node = iSession.collectDependencies( | |
| - iSession.createDependencyCoordinates(artifact), PathScope.MAIN_RUNTIME); | |
| + iSession.createDependencyCoordinates(artifact), PathScope.TEST_RUNTIME); | |
| Map<String, Node> nodes = node.stream() | |
| .collect(Collectors.toMap(n -> getDependencyKey(n.getDependency()), Function.identity())); | |
| @@ -160,8 +159,6 @@ private Model buildEffectiveModel(RepositorySystemSession session, Path src) thr | |
| } | |
| return dependency; | |
| }); | |
| - // Only keep transitive scopes (null/empty => COMPILE) | |
| - directDependencies.values().removeIf(DefaultConsumerPomBuilder::hasDependencyScope); | |
| managedDependencies.keySet().removeAll(directDependencies.keySet()); | |
| model = model.withDependencyManagement( | |
| @@ -169,36 +166,13 @@ private Model buildEffectiveModel(RepositorySystemSession session, Path src) thr | |
| ? null | |
| : model.getDependencyManagement().withDependencies(managedDependencies.values())) | |
| .withDependencies(directDependencies.isEmpty() ? null : directDependencies.values()); | |
| - } else { | |
| - // Even without dependencyManagement, filter direct dependencies to compile/runtime only | |
| - Map<String, Dependency> directDependencies = model.getDependencies().stream() | |
| - .filter(dependency -> !"import".equals(dependency.getScope())) | |
| - .collect(Collectors.toMap( | |
| - DefaultConsumerPomBuilder::getDependencyKey, | |
| - Function.identity(), | |
| - this::merge, | |
| - LinkedHashMap::new)); | |
| - // Only keep transitive scopes | |
| - directDependencies.values().removeIf(DefaultConsumerPomBuilder::hasDependencyScope); | |
| - model = model.withDependencies(directDependencies.isEmpty() ? null : directDependencies.values()); | |
| } | |
| return model; | |
| } | |
| - private static boolean hasDependencyScope(Dependency dependency) { | |
| - String scopeId = dependency.getScope(); | |
| - DependencyScope scope; | |
| - if (scopeId == null || scopeId.isEmpty()) { | |
| - scope = DependencyScope.COMPILE; | |
| - } else { | |
| - scope = DependencyScope.forId(scopeId); | |
| - } | |
| - return scope == null || !scope.isTransitive(); | |
| - } | |
| - | |
| private Dependency merge(Dependency dep1, Dependency dep2) { | |
| - throw new IllegalArgumentException("Duplicate dependency: " + getDependencyKey(dep1)); | |
| + throw new IllegalArgumentException("Duplicate dependency: " + dep1); | |
| } | |
| private static String getDependencyKey(org.apache.maven.api.Dependency dependency) { | |
| @@ -208,7 +182,7 @@ private static String getDependencyKey(org.apache.maven.api.Dependency dependenc | |
| private static String getDependencyKey(Dependency dependency) { | |
| return dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" | |
| - + (dependency.getType() != null ? dependency.getType() : "jar") + ":" | |
| + + (dependency.getType() != null ? dependency.getType() : "") + ":" | |
| + (dependency.getClassifier() != null ? dependency.getClassifier() : ""); | |
| } | |
| @@ -235,7 +209,6 @@ static Model transformNonPom(Model model, MavenProject project) { | |
| .preserveModelVersion(false) | |
| .root(false) | |
| .parent(null) | |
| - .mixins(null) | |
| .build(null), | |
| model) | |
| .mailingLists(null) | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ConcurrencyDependencyGraph.java b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ConcurrencyDependencyGraph.java | |
| index 9bfffcb6e3..ed0c36a3d5 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ConcurrencyDependencyGraph.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/ConcurrencyDependencyGraph.java | |
| @@ -45,12 +45,9 @@ public class ConcurrencyDependencyGraph { | |
| private final Set<MavenProject> finishedProjects = new HashSet<>(); | |
| - private final SmartProjectComparator projectComparator; | |
| - | |
| public ConcurrencyDependencyGraph(ProjectBuildList projectBuilds, ProjectDependencyGraph projectDependencyGraph) { | |
| this.projectDependencyGraph = projectDependencyGraph; | |
| this.projectBuilds = projectBuilds; | |
| - this.projectComparator = new SmartProjectComparator(projectDependencyGraph); | |
| } | |
| public int getNumberOfBuilds() { | |
| @@ -58,9 +55,9 @@ public int getNumberOfBuilds() { | |
| } | |
| /** | |
| - * Gets all the builds that have no reactor-dependencies, ordered by critical path priority | |
| + * Gets all the builds that have no reactor-dependencies | |
| * | |
| - * @return A list of all the initial builds, ordered by priority (critical path first) | |
| + * @return A set of all the initial builds | |
| */ | |
| public List<MavenProject> getRootSchedulableBuilds() { | |
| Set<MavenProject> result = new LinkedHashSet<>(); | |
| @@ -71,15 +68,11 @@ public List<MavenProject> getRootSchedulableBuilds() { | |
| result.add(projectBuild.getProject()); | |
| } | |
| } | |
| - if (result.isEmpty() && !projectBuilds.isEmpty()) { | |
| + if (result.isEmpty() && projectBuilds.size() > 0) { | |
| // Must return at least one project | |
| result.add(projectBuilds.get(0).getProject()); | |
| } | |
| - | |
| - // Sort by critical path priority (projects with longer critical paths first) | |
| - List<MavenProject> sortedResult = new ArrayList<>(result); | |
| - sortedResult.sort(projectComparator.getComparator()); | |
| - return sortedResult; | |
| + return new ArrayList<>(result); | |
| } | |
| /** | |
| @@ -103,9 +96,6 @@ private List<MavenProject> getSchedulableNewProcesses(MavenProject finishedProje | |
| result.add(dependentProject); | |
| } | |
| } | |
| - | |
| - // Sort newly schedulable projects by critical path priority | |
| - result.sort(projectComparator.getComparator()); | |
| return result; | |
| } | |
| @@ -150,13 +140,4 @@ public List<MavenProject> getActiveDependencies(MavenProject p) { | |
| activeDependencies.removeAll(finishedProjects); | |
| return activeDependencies; | |
| } | |
| - | |
| - /** | |
| - * Gets the smart project comparator used for critical path scheduling. | |
| - * | |
| - * @return the project comparator | |
| - */ | |
| - public SmartProjectComparator getProjectComparator() { | |
| - return projectComparator; | |
| - } | |
| } | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/MultiThreadedBuilder.java b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/MultiThreadedBuilder.java | |
| index c61889cda5..18157c06f2 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/MultiThreadedBuilder.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/MultiThreadedBuilder.java | |
| @@ -99,7 +99,6 @@ public void build( | |
| try { | |
| ConcurrencyDependencyGraph analyzer = | |
| new ConcurrencyDependencyGraph(segmentProjectBuilds, session.getProjectDependencyGraph()); | |
| - | |
| multiThreadedProjectTaskSegmentBuild( | |
| analyzer, reactorContext, session, service, taskSegment, projectBuildMap); | |
| if (reactorContext.getReactorBuildStatus().isHalted()) { | |
| @@ -132,7 +131,7 @@ private void multiThreadedProjectTaskSegmentBuild( | |
| .map(Map.Entry::getKey) | |
| .collect(Collectors.toSet()); | |
| - // schedule independent projects (ordered by critical path priority) | |
| + // schedule independent projects | |
| for (MavenProject mavenProject : analyzer.getRootSchedulableBuilds()) { | |
| ProjectSegment projectSegment = projectBuildList.get(mavenProject); | |
| logger.debug("Scheduling: {}", projectSegment.getProject()); | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/SmartProjectComparator.java b/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/SmartProjectComparator.java | |
| deleted file mode 100644 | |
| index 829c6e4df7..0000000000 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/SmartProjectComparator.java | |
| +++ /dev/null | |
| @@ -1,117 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.lifecycle.internal.builder.multithreaded; | |
| - | |
| -import java.util.Comparator; | |
| -import java.util.Map; | |
| -import java.util.concurrent.ConcurrentHashMap; | |
| -import java.util.function.ToLongFunction; | |
| - | |
| -import org.apache.maven.execution.ProjectDependencyGraph; | |
| -import org.apache.maven.project.MavenProject; | |
| - | |
| -/** | |
| - * Smart project comparator that orders projects based on critical path analysis. | |
| - * Projects with longer downstream dependency chains are prioritized to maximize | |
| - * parallel execution efficiency. | |
| - * | |
| - * <p>The algorithm calculates a weight for each project as: | |
| - * weight = 1 + max(downstream_project_weights) | |
| - * | |
| - * <p>Projects are then sorted by weight in descending order, ensuring that | |
| - * projects with longer dependency chains are built first. When projects have | |
| - * the same weight, they are ordered by project ID for deterministic results. | |
| - * | |
| - * <p><b>Example:</b> | |
| - * <p>Consider projects with dependencies: A → B → D, A → C → D | |
| - * <ul> | |
| - * <li>Project D: weight = 1 (no downstream dependencies)</li> | |
| - * <li>Project B: weight = 2 (1 + max(D=1))</li> | |
| - * <li>Project C: weight = 2 (1 + max(D=1))</li> | |
| - * <li>Project A: weight = 3 (1 + max(B=2, C=2))</li> | |
| - * </ul> | |
| - * <p>Build order: A (weight=3), then B and C (weight=2, ordered by project ID), then D (weight=1) | |
| - * <p>If projects have identical weights and IDs, the order is deterministic but may not preserve | |
| - * the original declaration order. | |
| - * | |
| - * @since 4.0.0 | |
| - */ | |
| -public class SmartProjectComparator { | |
| - | |
| - private final ProjectDependencyGraph dependencyGraph; | |
| - private final Map<MavenProject, Long> projectWeights; | |
| - private final Comparator<MavenProject> comparator; | |
| - | |
| - public SmartProjectComparator(ProjectDependencyGraph dependencyGraph) { | |
| - this.dependencyGraph = dependencyGraph; | |
| - this.projectWeights = new ConcurrentHashMap<>(); | |
| - this.comparator = createComparator(); | |
| - } | |
| - | |
| - /** | |
| - * Gets the comparator for ordering projects by critical path priority. | |
| - * | |
| - * @return comparator that orders projects with longer dependency chains first | |
| - */ | |
| - public Comparator<MavenProject> getComparator() { | |
| - return comparator; | |
| - } | |
| - | |
| - /** | |
| - * Gets the calculated weight for a project, representing its dependency chain length. | |
| - * | |
| - * @param project the project | |
| - * @return the project's weight (higher means longer dependency chain) | |
| - */ | |
| - public long getProjectWeight(MavenProject project) { | |
| - // First check if weight is already calculated | |
| - Long existingWeight = projectWeights.get(project); | |
| - if (existingWeight != null) { | |
| - return existingWeight; | |
| - } | |
| - | |
| - // Calculate weight without using computeIfAbsent to avoid recursive update issues | |
| - long weight = calculateWeight(project); | |
| - | |
| - // Use putIfAbsent to handle concurrent access safely | |
| - Long previousWeight = projectWeights.putIfAbsent(project, weight); | |
| - return previousWeight != null ? previousWeight : weight; | |
| - } | |
| - | |
| - private Comparator<MavenProject> createComparator() { | |
| - return Comparator.comparingLong((ToLongFunction<MavenProject>) this::getProjectWeight) | |
| - .reversed() // Higher weights first | |
| - .thenComparing(this::getProjectId); // Secondary sort for deterministic ordering | |
| - } | |
| - | |
| - private long calculateWeight(MavenProject project) { | |
| - // Calculate maximum weight of downstream dependencies | |
| - long maxDownstreamWeight = dependencyGraph.getDownstreamProjects(project, false).stream() | |
| - .mapToLong(this::getProjectWeight) | |
| - .max() | |
| - .orElse(0L); | |
| - | |
| - // Weight = 1 + max downstream weight (similar to Takari Smart Builder) | |
| - return 1L + maxDownstreamWeight; | |
| - } | |
| - | |
| - private String getProjectId(MavenProject project) { | |
| - return project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion(); | |
| - } | |
| -} | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java | |
| index e395d1ed00..6d9c76100d 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java | |
| @@ -25,11 +25,8 @@ | |
| import java.io.ByteArrayOutputStream; | |
| import java.io.PrintStream; | |
| import java.util.List; | |
| -import java.util.Map; | |
| -import java.util.function.Supplier; | |
| import org.apache.maven.api.Project; | |
| -import org.apache.maven.api.Service; | |
| import org.apache.maven.api.services.MavenException; | |
| import org.apache.maven.execution.MavenSession; | |
| import org.apache.maven.execution.MojoExecutionEvent; | |
| @@ -131,10 +128,6 @@ public void executeMojo(MavenSession session, MojoExecution mojoExecution) | |
| scope.seed(org.apache.maven.api.MojoExecution.class, new DefaultMojoExecution(sessionV4, mojoExecution)); | |
| if (mojoDescriptor.isV4Api()) { | |
| - // For Maven 4 plugins, register a service so that they can be directly injected into plugins | |
| - Map<Class<? extends Service>, Supplier<? extends Service>> services = sessionV4.getAllServices(); | |
| - services.forEach((itf, svc) -> scope.seed((Class<Service>) itf, (Supplier<Service>) svc)); | |
| - | |
| org.apache.maven.api.plugin.Mojo mojoV4 = mavenPluginManager.getConfiguredMojo( | |
| org.apache.maven.api.plugin.Mojo.class, session, mojoExecution); | |
| mojo = new MojoWrapper(mojoV4); | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterException.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterException.java | |
| index 296b5f7dbe..73a19257d0 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterException.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterException.java | |
| @@ -52,7 +52,7 @@ private static String format(List<Parameter> parameters) { | |
| StringBuilder buffer = new StringBuilder(128); | |
| if (parameters != null) { | |
| for (Parameter parameter : parameters) { | |
| - if (!buffer.isEmpty()) { | |
| + if (buffer.length() > 0) { | |
| buffer.append(", "); | |
| } | |
| buffer.append('\'').append(parameter.getName()).append('\''); | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java | |
| index 93c0d5a123..7d55730f5d 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java | |
| @@ -37,7 +37,6 @@ | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.Objects; | |
| -import java.util.function.Supplier; | |
| import java.util.jar.JarFile; | |
| import java.util.stream.Collectors; | |
| import java.util.zip.ZipEntry; | |
| @@ -48,7 +47,6 @@ | |
| import org.apache.maven.api.PathScope; | |
| import org.apache.maven.api.PathType; | |
| import org.apache.maven.api.Project; | |
| -import org.apache.maven.api.Service; | |
| import org.apache.maven.api.Session; | |
| import org.apache.maven.api.plugin.descriptor.Resolution; | |
| import org.apache.maven.api.services.DependencyResolver; | |
| @@ -567,10 +565,6 @@ private <T> T loadV4Mojo( | |
| injector.bindInstance(Project.class, project); | |
| injector.bindInstance(org.apache.maven.api.MojoExecution.class, execution); | |
| injector.bindInstance(org.apache.maven.api.plugin.Log.class, log); | |
| - | |
| - Map<Class<? extends Service>, Supplier<? extends Service>> services = sessionV4.getAllServices(); | |
| - services.forEach((itf, svc) -> injector.bindSupplier((Class<Service>) itf, (Supplier<Service>) svc)); | |
| - | |
| mojo = mojoInterface.cast(injector.getInstance( | |
| Key.of(mojoDescriptor.getImplementationClass(), mojoDescriptor.getRoleHint()))); | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java | |
| index fad79cc941..f4e667ac64 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java | |
| @@ -159,38 +159,7 @@ public DependencyResult resolveCoreExtension( | |
| List<RemoteRepository> repositories, | |
| RepositorySystemSession session) | |
| throws PluginResolutionException { | |
| - RequestTrace trace = RequestTrace.newChild(null, plugin); | |
| - | |
| - Artifact pluginArtifact = toArtifact(plugin, session); | |
| - | |
| - try { | |
| - DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession(session); | |
| - pluginSession.setArtifactDescriptorPolicy(new SimpleArtifactDescriptorPolicy(true, false)); | |
| - | |
| - ArtifactDescriptorRequest request = | |
| - new ArtifactDescriptorRequest(pluginArtifact, repositories, REPOSITORY_CONTEXT); | |
| - request.setTrace(trace); | |
| - ArtifactDescriptorResult result = repoSystem.readArtifactDescriptor(pluginSession, request); | |
| - | |
| - for (MavenPluginDependenciesValidator dependenciesValidator : dependenciesValidators) { | |
| - dependenciesValidator.validate(session, pluginArtifact, result); | |
| - } | |
| - | |
| - pluginArtifact = result.getArtifact(); | |
| - | |
| - if (logger.isWarnEnabled() && !result.getRelocations().isEmpty()) { | |
| - String message = | |
| - pluginArtifact instanceof RelocatedArtifact relocated ? ": " + relocated.getMessage() : ""; | |
| - logger.warn( | |
| - "The extension {} has been relocated to {}{}", | |
| - result.getRelocations().get(0), | |
| - pluginArtifact, | |
| - message); | |
| - } | |
| - return resolveInternal(plugin, pluginArtifact, dependencyFilter, repositories, session); | |
| - } catch (ArtifactDescriptorException e) { | |
| - throw new PluginResolutionException(plugin, e.getResult().getExceptions(), e); | |
| - } | |
| + return resolveInternal(plugin, null /* pluginArtifact */, dependencyFilter, repositories, session); | |
| } | |
| @Override | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultDependencyResolutionRequest.java b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultDependencyResolutionRequest.java | |
| index 9bc9d39cde..92c05ca420 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultDependencyResolutionRequest.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultDependencyResolutionRequest.java | |
| @@ -22,9 +22,7 @@ | |
| import org.eclipse.aether.graph.DependencyFilter; | |
| /** | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| public class DefaultDependencyResolutionRequest implements DependencyResolutionRequest { | |
| private MavenProject project; | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultDependencyResolutionResult.java b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultDependencyResolutionResult.java | |
| index d813ccb8df..9bb33ff58b 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultDependencyResolutionResult.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultDependencyResolutionResult.java | |
| @@ -28,9 +28,7 @@ | |
| import org.eclipse.aether.graph.DependencyNode; | |
| /** | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| class DefaultDependencyResolutionResult implements DependencyResolutionResult { | |
| private DependencyNode root; | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java | |
| index 1de9eeccc5..a14dfaabe1 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java | |
| @@ -44,6 +44,7 @@ | |
| import java.util.stream.Collectors; | |
| import java.util.stream.Stream; | |
| +import org.apache.maven.ProjectCycleException; | |
| import org.apache.maven.RepositoryUtils; | |
| import org.apache.maven.api.ArtifactCoordinates; | |
| import org.apache.maven.api.Language; | |
| @@ -104,10 +105,7 @@ | |
| /** | |
| * DefaultProjectBuilder | |
| - * | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| @Named | |
| @Singleton | |
| public class DefaultProjectBuilder implements ProjectBuilder { | |
| @@ -184,7 +182,7 @@ public ProjectBuildingResult build(Artifact artifact, ProjectBuildingRequest req | |
| public ProjectBuildingResult build(Artifact artifact, boolean allowStubModel, ProjectBuildingRequest request) | |
| throws ProjectBuildingException { | |
| try (BuildSession bs = new BuildSession(request)) { | |
| - return bs.build(false, artifact, allowStubModel, request.getRemoteRepositories()); | |
| + return bs.build(false, artifact, allowStubModel); | |
| } | |
| } | |
| @@ -318,18 +316,6 @@ class BuildSession implements AutoCloseable { | |
| private final ModelBuilder.ModelBuilderSession modelBuilderSession; | |
| private final Map<String, MavenProject> projectIndex = new ConcurrentHashMap<>(256); | |
| - // Store computed repositories per project to avoid leakage between projects | |
| - private final Map<String, List<ArtifactRepository>> projectRepositories = new ConcurrentHashMap<>(); | |
| - | |
| - /** | |
| - * Get the effective repositories for a project. If project-specific repositories | |
| - * have been computed and stored, use those; otherwise fall back to request repositories. | |
| - */ | |
| - private List<ArtifactRepository> getEffectiveRepositories(String projectId) { | |
| - List<ArtifactRepository> stored = projectRepositories.get(projectId); | |
| - return stored != null ? stored : request.getRemoteRepositories(); | |
| - } | |
| - | |
| BuildSession(ProjectBuildingRequest request) { | |
| this.request = request; | |
| InternalSession session = InternalSession.from(request.getRepositorySession()); | |
| @@ -441,8 +427,7 @@ ProjectBuildingResult build(boolean parent, Path pomFile, ModelSource modelSourc | |
| } | |
| } | |
| - ProjectBuildingResult build( | |
| - boolean parent, Artifact artifact, boolean allowStubModel, List<ArtifactRepository> repositories) | |
| + ProjectBuildingResult build(boolean parent, Artifact artifact, boolean allowStubModel) | |
| throws ProjectBuildingException { | |
| org.eclipse.aether.artifact.Artifact pomArtifact = RepositoryUtils.toArtifact(artifact); | |
| pomArtifact = ArtifactDescriptorUtils.toPomArtifact(pomArtifact); | |
| @@ -451,10 +436,9 @@ ProjectBuildingResult build( | |
| try { | |
| ArtifactCoordinates coordinates = session.createArtifactCoordinates(session.getArtifact(pomArtifact)); | |
| - // Use provided repositories if available, otherwise fall back to request repositories | |
| ArtifactResolverRequest req = ArtifactResolverRequest.builder() | |
| .session(session) | |
| - .repositories(repositories.stream() | |
| + .repositories(request.getRemoteRepositories().stream() | |
| .map(RepositoryUtils::toRepo) | |
| .map(session::getRemoteRepository) | |
| .toList()) | |
| @@ -505,14 +489,10 @@ List<ProjectBuildingResult> build(List<File> pomFiles, boolean recursive) throws | |
| .findAny() | |
| .orElse(null); | |
| if (cycle != null) { | |
| - final CycleDetectedException cde = (CycleDetectedException) cycle.getException(); | |
| - throw new ProjectBuildingException( | |
| - null, | |
| + throw new RuntimeException(new ProjectCycleException( | |
| "The projects in the reactor contain a cyclic reference: " + cycle.getMessage(), | |
| - null, | |
| - cde); | |
| + (CycleDetectedException) cycle.getException())); | |
| } | |
| - | |
| throw new ProjectBuildingException(results); | |
| } | |
| @@ -864,30 +844,7 @@ private void initParent(MavenProject project, ModelBuilderResult result) { | |
| // remote repositories with those found in the pom.xml, along with the existing externally | |
| // defined repositories. | |
| // | |
| - // Compute merged repositories for this project and store in session | |
| - // instead of mutating the shared request to avoid leakage between projects | |
| - List<ArtifactRepository> mergedRepositories; | |
| - switch (request.getRepositoryMerging()) { | |
| - case POM_DOMINANT -> { | |
| - LinkedHashSet<ArtifactRepository> reposes = | |
| - new LinkedHashSet<>(project.getRemoteArtifactRepositories()); | |
| - reposes.addAll(request.getRemoteRepositories()); | |
| - mergedRepositories = List.copyOf(reposes); | |
| - } | |
| - case REQUEST_DOMINANT -> { | |
| - LinkedHashSet<ArtifactRepository> reposes = | |
| - new LinkedHashSet<>(request.getRemoteRepositories()); | |
| - reposes.addAll(project.getRemoteArtifactRepositories()); | |
| - mergedRepositories = List.copyOf(reposes); | |
| - } | |
| - default -> throw new IllegalArgumentException( | |
| - "Unsupported repository merging: " + request.getRepositoryMerging()); | |
| - } | |
| - | |
| - // Store the computed repositories for this project in BuildSession storage | |
| - // to avoid mutating the shared request and causing leakage between projects | |
| - projectRepositories.put(project.getId(), mergedRepositories); | |
| - | |
| + request.getRemoteRepositories().addAll(project.getRemoteArtifactRepositories()); | |
| Path parentPomFile = parentModel.getPomFile(); | |
| if (parentPomFile != null) { | |
| project.setParentFile(parentPomFile.toFile()); | |
| @@ -907,8 +864,7 @@ private void initParent(MavenProject project, ModelBuilderResult result) { | |
| } else { | |
| Artifact parentArtifact = project.getParentArtifact(); | |
| try { | |
| - parent = build(true, parentArtifact, false, getEffectiveRepositories(project.getId())) | |
| - .getProject(); | |
| + parent = build(true, parentArtifact, false).getProject(); | |
| } catch (ProjectBuildingException e) { | |
| // MNG-4488 where let invalid parents slide on by | |
| if (logger.isDebugEnabled()) { | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingRequest.java b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingRequest.java | |
| index 343ebbc458..7f1fbddcb8 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingRequest.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingRequest.java | |
| @@ -33,10 +33,7 @@ | |
| /** | |
| * DefaultProjectBuildingRequest | |
| - * | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| public class DefaultProjectBuildingRequest implements ProjectBuildingRequest { | |
| private RepositorySystemSession repositorySession; | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingResult.java b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingResult.java | |
| index 7e6f8057b1..7c0eed6fce 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingResult.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuildingResult.java | |
| @@ -27,9 +27,7 @@ | |
| /** | |
| * Collects the output of the project builder. | |
| * | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| class DefaultProjectBuildingResult implements ProjectBuildingResult { | |
| private final String projectId; | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectDependenciesResolver.java b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectDependenciesResolver.java | |
| index 56c8339d46..20123cc954 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectDependenciesResolver.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectDependenciesResolver.java | |
| @@ -53,9 +53,7 @@ | |
| import org.slf4j.LoggerFactory; | |
| /** | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| @Named | |
| @Singleton | |
| public class DefaultProjectDependenciesResolver implements ProjectDependenciesResolver { | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/DependencyResolutionException.java b/impl/maven-core/src/main/java/org/apache/maven/project/DependencyResolutionException.java | |
| index d7392eed54..278e06ed19 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/DependencyResolutionException.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/DependencyResolutionException.java | |
| @@ -23,9 +23,7 @@ | |
| import org.eclipse.aether.graph.Dependency; | |
| /** | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| public class DependencyResolutionException extends Exception { | |
| private final transient DependencyResolutionResult result; | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/DependencyResolutionRequest.java b/impl/maven-core/src/main/java/org/apache/maven/project/DependencyResolutionRequest.java | |
| index 725c2978c9..6388adf5e0 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/DependencyResolutionRequest.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/DependencyResolutionRequest.java | |
| @@ -24,9 +24,7 @@ | |
| /** | |
| * A request to resolve the dependencies of a project. | |
| * | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| public interface DependencyResolutionRequest { | |
| /** | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/DependencyResolutionResult.java b/impl/maven-core/src/main/java/org/apache/maven/project/DependencyResolutionResult.java | |
| index 380f15388c..ce02b39616 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/DependencyResolutionResult.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/DependencyResolutionResult.java | |
| @@ -26,9 +26,7 @@ | |
| /** | |
| * The result of a project dependency resolution. | |
| * | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| public interface DependencyResolutionResult { | |
| /** | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuilder.java b/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuilder.java | |
| index 3f3f8b122a..2542269657 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuilder.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuilder.java | |
| @@ -26,10 +26,7 @@ | |
| /** | |
| * Builds in-memory descriptions of projects. | |
| - * | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| public interface ProjectBuilder { | |
| /** | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingException.java b/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingException.java | |
| index 89ca05d43a..d8b3ca5ae8 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingException.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingException.java | |
| @@ -21,12 +21,8 @@ | |
| import java.io.File; | |
| import java.util.List; | |
| -import org.apache.maven.model.building.ModelProblem; | |
| - | |
| /** | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| public class ProjectBuildingException extends Exception { | |
| private final String projectId; | |
| @@ -63,7 +59,7 @@ protected ProjectBuildingException(String projectId, String message, File pomFil | |
| } | |
| public ProjectBuildingException(List<ProjectBuildingResult> results) { | |
| - super(createMessage(results)); | |
| + super("Some problems were encountered while processing the POMs"); | |
| this.projectId = ""; | |
| this.results = results; | |
| } | |
| @@ -101,84 +97,4 @@ private static String createMessage(String message, String projectId, File pomFi | |
| } | |
| return buffer.toString(); | |
| } | |
| - | |
| - private static String createMessage(List<ProjectBuildingResult> results) { | |
| - if (results == null || results.isEmpty()) { | |
| - return "Some problems were encountered while processing the POMs"; | |
| - } | |
| - | |
| - long totalProblems = 0; | |
| - long errorProblems = 0; | |
| - | |
| - for (ProjectBuildingResult result : results) { | |
| - List<ModelProblem> problems = result.getProblems(); | |
| - totalProblems += problems.size(); | |
| - | |
| - for (ModelProblem problem : problems) { | |
| - if (problem.getSeverity() != ModelProblem.Severity.WARNING) { | |
| - errorProblems++; | |
| - } | |
| - } | |
| - } | |
| - | |
| - StringBuilder buffer = new StringBuilder(1024); | |
| - buffer.append(totalProblems); | |
| - buffer.append(totalProblems == 1 ? " problem was " : " problems were "); | |
| - buffer.append("encountered while processing the POMs"); | |
| - | |
| - if (errorProblems > 0) { | |
| - buffer.append(" (") | |
| - .append(errorProblems) | |
| - .append(" ") | |
| - .append(errorProblems > 1 ? "errors" : "error") | |
| - .append(")"); | |
| - } | |
| - | |
| - buffer.append(":\n"); | |
| - | |
| - for (ProjectBuildingResult result : results) { | |
| - if (!result.getProblems().isEmpty()) { | |
| - String projectInfo = result.getProjectId(); | |
| - if (projectInfo.trim().isEmpty()) { | |
| - projectInfo = | |
| - result.getPomFile() != null ? result.getPomFile().getName() : "unknown project"; | |
| - } | |
| - | |
| - buffer.append("\n[").append(projectInfo).append("]\n"); | |
| - | |
| - for (ModelProblem problem : result.getProblems()) { | |
| - if (errorProblems > 0 && problem.getSeverity() == ModelProblem.Severity.WARNING) { | |
| - continue; | |
| - } | |
| - | |
| - buffer.append(" [").append(problem.getSeverity()).append("] "); | |
| - buffer.append(problem.getMessage()); | |
| - | |
| - String location = ""; | |
| - if (!problem.getSource().trim().isEmpty()) { | |
| - location = problem.getSource(); | |
| - } | |
| - if (problem.getLineNumber() > 0) { | |
| - if (!location.isEmpty()) { | |
| - location += ", "; | |
| - } | |
| - location += "line " + problem.getLineNumber(); | |
| - } | |
| - if (problem.getColumnNumber() > 0) { | |
| - if (!location.isEmpty()) { | |
| - location += ", "; | |
| - } | |
| - location += "column " + problem.getColumnNumber(); | |
| - } | |
| - | |
| - if (!location.isEmpty()) { | |
| - buffer.append(" @ ").append(location); | |
| - } | |
| - buffer.append("\n"); | |
| - } | |
| - } | |
| - } | |
| - | |
| - return buffer.toString(); | |
| - } | |
| } | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingRequest.java b/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingRequest.java | |
| index cb32cd07fa..c2f8fb3bf3 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingRequest.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingRequest.java | |
| @@ -29,10 +29,7 @@ | |
| /** | |
| * ProjectBuildingRequest | |
| - * | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| public interface ProjectBuildingRequest { | |
| ProjectBuildingRequest setLocalRepository(ArtifactRepository localRepository); | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingResult.java b/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingResult.java | |
| index ea589802b0..897b0555a0 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingResult.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/ProjectBuildingResult.java | |
| @@ -26,9 +26,7 @@ | |
| /** | |
| * Collects the output of the project builder. | |
| * | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| public interface ProjectBuildingResult { | |
| /** | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/ProjectDependenciesResolver.java b/impl/maven-core/src/main/java/org/apache/maven/project/ProjectDependenciesResolver.java | |
| index 5ab53b3a26..d5794bea94 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/ProjectDependenciesResolver.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/ProjectDependenciesResolver.java | |
| @@ -21,9 +21,7 @@ | |
| /** | |
| * Resolves the transitive dependencies of a project. | |
| * | |
| - * @deprecated use {@code org.apache.maven.api.services.ProjectBuilder} instead | |
| */ | |
| -@Deprecated(since = "4.0.0") | |
| public interface ProjectDependenciesResolver { | |
| /** | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/artifact/DefaultProjectArtifactsCache.java b/impl/maven-core/src/main/java/org/apache/maven/project/artifact/DefaultProjectArtifactsCache.java | |
| index 40ed1720f5..5b0665b5e3 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/artifact/DefaultProjectArtifactsCache.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/artifact/DefaultProjectArtifactsCache.java | |
| @@ -27,12 +27,13 @@ | |
| import java.util.HashSet; | |
| import java.util.LinkedHashSet; | |
| import java.util.List; | |
| +import java.util.Map; | |
| import java.util.Objects; | |
| import java.util.Set; | |
| +import java.util.concurrent.ConcurrentHashMap; | |
| import org.apache.maven.RepositoryUtils; | |
| import org.apache.maven.artifact.Artifact; | |
| -import org.apache.maven.impl.cache.Cache; | |
| import org.apache.maven.lifecycle.LifecycleExecutionException; | |
| import org.apache.maven.lifecycle.internal.SetWithResolutionResult; | |
| import org.apache.maven.project.MavenProject; | |
| @@ -157,9 +158,8 @@ public boolean equals(Object o) { | |
| } | |
| } | |
| - protected final Cache<Key, CacheRecord> cache = | |
| - Cache.newCache(Cache.ReferenceType.SOFT, "ProjectArtifactsCache-Records"); | |
| - protected final Cache<Key, Key> keys = Cache.newCache(Cache.ReferenceType.SOFT, "ProjectArtifactsCache-Keys"); | |
| + protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<>(); | |
| + protected final Map<Key, Key> keys = new ConcurrentHashMap<>(); | |
| @Override | |
| public Key createKey( | |
| @@ -201,14 +201,18 @@ public CacheRecord put(Key key, Set<Artifact> projectArtifacts) { | |
| throw new IllegalArgumentException("projectArtifacts must implement ArtifactsSetWithResult"); | |
| } | |
| - return cache.computeIfAbsent(key, k -> new CacheRecord(artifacts)); | |
| + CacheRecord record = new CacheRecord(artifacts); | |
| + cache.put(key, record); | |
| + return record; | |
| } | |
| @Override | |
| public CacheRecord put(Key key, LifecycleExecutionException exception) { | |
| Objects.requireNonNull(exception, "exception cannot be null"); | |
| assertUniqueKey(key); | |
| - return cache.computeIfAbsent(key, k -> new CacheRecord(exception)); | |
| + CacheRecord record = new CacheRecord(exception); | |
| + cache.put(key, record); | |
| + return record; | |
| } | |
| protected void assertUniqueKey(Key key) { | |
| diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/collector/DefaultProjectsSelector.java b/impl/maven-core/src/main/java/org/apache/maven/project/collector/DefaultProjectsSelector.java | |
| index 0be344384a..828e546c1c 100644 | |
| --- a/impl/maven-core/src/main/java/org/apache/maven/project/collector/DefaultProjectsSelector.java | |
| +++ b/impl/maven-core/src/main/java/org/apache/maven/project/collector/DefaultProjectsSelector.java | |
| @@ -75,7 +75,7 @@ public List<MavenProject> selectProjects(List<File> files, MavenExecutionRequest | |
| "{} {} encountered while building the effective model for '{}' (use -e to see details)", | |
| problemsCount, | |
| (problemsCount == 1) ? "problem was" : "problems were", | |
| - result.getProjectId()); | |
| + result.getProject().getId()); | |
| if (request.isShowErrors()) { // this means -e or -X (as -X enables -e as well) | |
| for (ModelProblem problem : result.getProblems()) { | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/artifact/handler/ArtifactHandlerTest.java b/impl/maven-core/src/test/java/org/apache/maven/artifact/handler/ArtifactHandlerTest.java | |
| index 122da1e15a..a603b2429e 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/artifact/handler/ArtifactHandlerTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/artifact/handler/ArtifactHandlerTest.java | |
| @@ -99,6 +99,6 @@ private String trimApt(String content, String type) { | |
| private String trimApt(String content) { | |
| content = content.replace('<', ' ').replace('>', ' ').trim(); | |
| - return (content.isEmpty()) ? null : content; | |
| + return (content.length() == 0) ? null : content; | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/artifact/resolver/filter/ExclusionArtifactFilterTest.java b/impl/maven-core/src/test/java/org/apache/maven/artifact/resolver/filter/ExclusionArtifactFilterTest.java | |
| index eba03f5fa7..4347e1a8dc 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/artifact/resolver/filter/ExclusionArtifactFilterTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/artifact/resolver/filter/ExclusionArtifactFilterTest.java | |
| @@ -26,8 +26,8 @@ | |
| import org.junit.jupiter.api.BeforeEach; | |
| import org.junit.jupiter.api.Test; | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| +import static org.hamcrest.CoreMatchers.is; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| import static org.mockito.Mockito.mock; | |
| import static org.mockito.Mockito.when; | |
| @@ -53,7 +53,7 @@ void testExcludeExact() { | |
| exclusion.setArtifactId("maven-core"); | |
| ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Collections.singletonList(exclusion)); | |
| - assertFalse(filter.include(artifact), "Artifact should be excluded by exact match"); | |
| + assertThat(filter.include(artifact), is(false)); | |
| } | |
| @Test | |
| @@ -63,7 +63,7 @@ void testExcludeNoMatch() { | |
| exclusion.setArtifactId("maven-model"); | |
| ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Collections.singletonList(exclusion)); | |
| - assertTrue(filter.include(artifact), "Artifact should not be excluded when no match"); | |
| + assertThat(filter.include(artifact), is(true)); | |
| } | |
| @Test | |
| @@ -73,7 +73,7 @@ void testExcludeGroupIdWildcard() { | |
| exclusion.setArtifactId("maven-core"); | |
| ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Collections.singletonList(exclusion)); | |
| - assertFalse(filter.include(artifact), "Artifact should be excluded by groupId wildcard"); | |
| + assertThat(filter.include(artifact), is(false)); | |
| } | |
| @Test | |
| @@ -83,9 +83,7 @@ void testExcludeGroupIdWildcardNoMatch() { | |
| exclusion.setArtifactId("maven-compat"); | |
| ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Collections.singletonList(exclusion)); | |
| - assertTrue( | |
| - filter.include(artifact), | |
| - "Artifact should not be excluded when groupId wildcard doesn't match artifactId"); | |
| + assertThat(filter.include(artifact), is(true)); | |
| } | |
| @Test | |
| @@ -95,7 +93,7 @@ void testExcludeArtifactIdWildcard() { | |
| exclusion.setArtifactId("*"); | |
| ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Collections.singletonList(exclusion)); | |
| - assertFalse(filter.include(artifact), "Artifact should be excluded by artifactId wildcard"); | |
| + assertThat(filter.include(artifact), is(false)); | |
| } | |
| @Test | |
| @@ -105,9 +103,7 @@ void testExcludeArtifactIdWildcardNoMatch() { | |
| exclusion.setArtifactId("*"); | |
| ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Collections.singletonList(exclusion)); | |
| - assertTrue( | |
| - filter.include(artifact), | |
| - "Artifact should not be excluded when artifactId wildcard doesn't match groupId"); | |
| + assertThat(filter.include(artifact), is(true)); | |
| } | |
| @Test | |
| @@ -117,7 +113,7 @@ void testExcludeAllWildcard() { | |
| exclusion.setArtifactId("*"); | |
| ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Collections.singletonList(exclusion)); | |
| - assertFalse(filter.include(artifact), "Artifact should be excluded by all wildcard"); | |
| + assertThat(filter.include(artifact), is(false)); | |
| } | |
| @Test | |
| @@ -132,7 +128,7 @@ void testMultipleExclusionsExcludeArtifactIdWildcard() { | |
| ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Arrays.asList(exclusion1, exclusion2)); | |
| - assertFalse(filter.include(artifact), "Artifact should be excluded by multiple exclusions"); | |
| + assertThat(filter.include(artifact), is(false)); | |
| } | |
| @Test | |
| @@ -147,8 +143,7 @@ void testMultipleExclusionsExcludeGroupIdWildcard() { | |
| ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Arrays.asList(exclusion1, exclusion2)); | |
| - assertFalse( | |
| - filter.include(artifact), "Artifact should be excluded by multiple exclusions with groupId wildcard"); | |
| + assertThat(filter.include(artifact), is(false)); | |
| } | |
| @Test | |
| @@ -158,8 +153,8 @@ void testExcludeWithGlob() { | |
| exclusion.setArtifactId("maven-*"); | |
| ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Collections.singletonList(exclusion)); | |
| - assertFalse(filter.include(artifact), "Maven artifact should be excluded by glob pattern"); | |
| - assertTrue(filter.include(artifact2), "JUnit artifact should not be excluded by maven-* glob pattern"); | |
| + assertThat(filter.include(artifact), is(false)); | |
| + assertThat(filter.include(artifact2), is(true)); | |
| } | |
| @Test | |
| @@ -169,7 +164,7 @@ void testExcludeWithGlobStar() { | |
| exclusion.setArtifactId("maven-**"); | |
| ExclusionArtifactFilter filter = new ExclusionArtifactFilter(Collections.singletonList(exclusion)); | |
| - assertFalse(filter.include(artifact), "Maven artifact should be excluded by glob star pattern"); | |
| - assertTrue(filter.include(artifact2), "JUnit artifact should not be excluded by maven-** glob star pattern"); | |
| + assertThat(filter.include(artifact), is(false)); | |
| + assertThat(filter.include(artifact2), is(true)); | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/classrealm/DefaultClassRealmManagerTest.java b/impl/maven-core/src/test/java/org/apache/maven/classrealm/DefaultClassRealmManagerTest.java | |
| index 411a483b22..c90e75bece 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/classrealm/DefaultClassRealmManagerTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/classrealm/DefaultClassRealmManagerTest.java | |
| @@ -38,8 +38,9 @@ | |
| import org.slf4j.Logger; | |
| import org.slf4j.LoggerFactory; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.endsWith; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| import static org.mockito.Mockito.calls; | |
| import static org.mockito.Mockito.inOrder; | |
| import static org.mockito.Mockito.mock; | |
| @@ -118,9 +119,7 @@ void testDebugEnabled() throws PlexusContainerException { | |
| assertEquals(classRealmManager.getMavenApiRealm(), classRealm.getParentClassLoader()); | |
| assertEquals("project>modelGroup1:modelArtifact1:modelVersion1", classRealm.getId()); | |
| assertEquals(1, classRealm.getURLs().length); | |
| - assertTrue( | |
| - classRealm.getURLs()[0].getPath().endsWith("local/repository/some/path"), | |
| - "ClassRealm URL should end with local repository path"); | |
| + assertThat(classRealm.getURLs()[0].getPath(), endsWith("local/repository/some/path")); | |
| verifier.verify(logger, calls(1)).debug("Importing foreign packages into class realm {}", "maven.api"); | |
| verifier.verify(logger, calls(1)).debug(" Imported: {} < {}", "group1:artifact1", "test"); | |
| @@ -154,9 +153,7 @@ void testDebugDisabled() throws PlexusContainerException { | |
| assertEquals(classRealmManager.getMavenApiRealm(), classRealm.getParentClassLoader()); | |
| assertEquals("project>modelGroup1:modelArtifact1:modelVersion1", classRealm.getId()); | |
| assertEquals(1, classRealm.getURLs().length); | |
| - assertTrue( | |
| - classRealm.getURLs()[0].getPath().endsWith("local/repository/some/path"), | |
| - "ClassRealm URL should end with local repository path"); | |
| + assertThat(classRealm.getURLs()[0].getPath(), endsWith("local/repository/some/path")); | |
| verifier.verify(logger, calls(1)).debug("Importing foreign packages into class realm {}", "maven.api"); | |
| verifier.verify(logger, calls(1)).debug(" Imported: {} < {}", "group1:artifact1", "test"); | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/configuration/internal/EnhancedCompositeBeanHelperTest.java b/impl/maven-core/src/test/java/org/apache/maven/configuration/internal/EnhancedCompositeBeanHelperTest.java | |
| index ab954855a8..031c62b69b 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/configuration/internal/EnhancedCompositeBeanHelperTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/configuration/internal/EnhancedCompositeBeanHelperTest.java | |
| @@ -124,7 +124,7 @@ void testPerformanceWithRepeatedCalls() throws Exception { | |
| // Second call should be faster (though this is not guaranteed in all environments) | |
| // We mainly verify that both calls work correctly | |
| - assertTrue(time2 >= 0, "Expected " + time2 + " to be >= " + 0); // Just verify it completed | |
| + assertTrue(time2 >= 0); // Just verify it completed | |
| } | |
| @Test | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/execution/DefaultBuildResumptionAnalyzerTest.java b/impl/maven-core/src/test/java/org/apache/maven/execution/DefaultBuildResumptionAnalyzerTest.java | |
| index 010fef95c0..6ed0ecfb8b 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/execution/DefaultBuildResumptionAnalyzerTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/execution/DefaultBuildResumptionAnalyzerTest.java | |
| @@ -28,9 +28,8 @@ | |
| import static java.util.Arrays.asList; | |
| import static java.util.Collections.singletonList; | |
| -import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.is; | |
| class DefaultBuildResumptionAnalyzerTest { | |
| private final DefaultBuildResumptionAnalyzer analyzer = new DefaultBuildResumptionAnalyzer(); | |
| @@ -50,8 +49,8 @@ void resumeFromGetsDetermined() { | |
| Optional<BuildResumptionData> result = analyzer.determineBuildResumptionData(executionResult); | |
| - assertTrue(result.isPresent(), "Expected " + result + ".isPresent() to return true"); | |
| - assertEquals(asList("test:B"), result.get().getRemainingProjects()); | |
| + assertThat(result.isPresent(), is(true)); | |
| + assertThat(result.get().getRemainingProjects(), is(asList("test:B"))); | |
| } | |
| @Test | |
| @@ -62,7 +61,7 @@ void resumeFromIsIgnoredWhenFirstProjectFails() { | |
| Optional<BuildResumptionData> result = analyzer.determineBuildResumptionData(executionResult); | |
| - assertFalse(result.isPresent(), "Expected " + result + ".isPresent() to return false"); | |
| + assertThat(result.isPresent(), is(false)); | |
| } | |
| @Test | |
| @@ -74,8 +73,8 @@ void projectsSucceedingAfterFailedProjectsAreExcluded() { | |
| Optional<BuildResumptionData> result = analyzer.determineBuildResumptionData(executionResult); | |
| - assertTrue(result.isPresent(), "Expected " + result + ".isPresent() to return true"); | |
| - assertEquals(asList("test:B"), result.get().getRemainingProjects()); | |
| + assertThat(result.isPresent(), is(true)); | |
| + assertThat(result.get().getRemainingProjects(), is(asList("test:B"))); | |
| } | |
| @Test | |
| @@ -88,8 +87,8 @@ void projectsDependingOnFailedProjectsAreNotExcluded() { | |
| Optional<BuildResumptionData> result = analyzer.determineBuildResumptionData(executionResult); | |
| - assertTrue(result.isPresent(), "Expected " + result + ".isPresent() to return true"); | |
| - assertEquals(asList("test:B", "test:C"), result.get().getRemainingProjects()); | |
| + assertThat(result.isPresent(), is(true)); | |
| + assertThat(result.get().getRemainingProjects(), is(asList("test:B", "test:C"))); | |
| } | |
| @Test | |
| @@ -102,8 +101,8 @@ void projectsFailingAfterAnotherFailedProjectAreNotExcluded() { | |
| Optional<BuildResumptionData> result = analyzer.determineBuildResumptionData(executionResult); | |
| - assertTrue(result.isPresent(), "Expected " + result + ".isPresent() to return true"); | |
| - assertEquals(asList("test:B", "test:D"), result.get().getRemainingProjects()); | |
| + assertThat(result.isPresent(), is(true)); | |
| + assertThat(result.get().getRemainingProjects(), is(asList("test:B", "test:D"))); | |
| } | |
| private MavenProject createMavenProject(String artifactId) { | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/execution/DefaultBuildResumptionDataRepositoryTest.java b/impl/maven-core/src/test/java/org/apache/maven/execution/DefaultBuildResumptionDataRepositoryTest.java | |
| index 1dbb0e5ee3..009c7e7529 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/execution/DefaultBuildResumptionDataRepositoryTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/execution/DefaultBuildResumptionDataRepositoryTest.java | |
| @@ -27,8 +27,10 @@ | |
| import org.junit.jupiter.api.Test; | |
| import static java.util.Collections.singleton; | |
| -import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.containsInAnyOrder; | |
| +import static org.hamcrest.Matchers.empty; | |
| +import static org.hamcrest.Matchers.is; | |
| class DefaultBuildResumptionDataRepositoryTest { | |
| private final DefaultBuildResumptionDataRepository repository = new DefaultBuildResumptionDataRepository(); | |
| @@ -41,7 +43,7 @@ void resumeFromPropertyGetsApplied() { | |
| repository.applyResumptionProperties(request, properties); | |
| - assertEquals(singleton(":module-a"), request.getProjectActivation().getOptionalActiveProjectSelectors()); | |
| + assertThat(request.getProjectActivation().getOptionalActiveProjectSelectors(), is(singleton(":module-a"))); | |
| } | |
| @Test | |
| @@ -53,7 +55,7 @@ void resumeFromPropertyDoesNotOverrideExistingRequestParameters() { | |
| repository.applyResumptionProperties(request, properties); | |
| - assertEquals(":module-b", request.getResumeFrom()); | |
| + assertThat(request.getResumeFrom(), is(":module-b")); | |
| } | |
| @Test | |
| @@ -67,11 +69,9 @@ void projectsFromPropertyGetsAddedToExistingRequestParameters() { | |
| repository.applyResumptionProperties(request, properties); | |
| - var selectors = request.getProjectActivation().getOptionalActiveProjectSelectors(); | |
| - assertEquals(3, selectors.size()); | |
| - assertTrue(selectors.contains(":module-a"), "Expected selectors " + selectors + " to contain :module-a"); | |
| - assertTrue(selectors.contains(":module-b"), "Expected selectors " + selectors + " to contain :module-b"); | |
| - assertTrue(selectors.contains(":module-c"), "Expected selectors " + selectors + " to contain :module-c"); | |
| + assertThat( | |
| + request.getProjectActivation().getOptionalActiveProjectSelectors(), | |
| + containsInAnyOrder(":module-a", ":module-b", ":module-c")); | |
| } | |
| @Test | |
| @@ -82,9 +82,7 @@ void selectedProjectsAreNotAddedWhenPropertyValueIsEmpty() { | |
| repository.applyResumptionProperties(request, properties); | |
| - assertTrue(request.getProjectActivation() | |
| - .getOptionalActiveProjectSelectors() | |
| - .isEmpty()); | |
| + assertThat(request.getProjectActivation().getOptionalActiveProjectSelectors(), is(empty())); | |
| } | |
| @Test | |
| @@ -97,7 +95,8 @@ void applyResumptionDataShouldLoadData() { | |
| repository.applyResumptionData(request, rootProject); | |
| - assertEquals( | |
| - singleton("example:module-c"), request.getProjectActivation().getOptionalActiveProjectSelectors()); | |
| + assertThat( | |
| + request.getProjectActivation().getOptionalActiveProjectSelectors(), | |
| + containsInAnyOrder("example:module-c")); | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/execution/DefaultMavenExecutionTest.java b/impl/maven-core/src/test/java/org/apache/maven/execution/DefaultMavenExecutionTest.java | |
| index b486b6abc3..605137abae 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/execution/DefaultMavenExecutionTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/execution/DefaultMavenExecutionTest.java | |
| @@ -23,9 +23,11 @@ | |
| import org.apache.maven.project.MavenProject; | |
| import org.junit.jupiter.api.Test; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.empty; | |
| +import static org.hamcrest.Matchers.is; | |
| import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| import static org.junit.jupiter.api.Assertions.assertNotSame; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| /** | |
| */ | |
| @@ -44,8 +46,6 @@ void testResultWithNullTopologicallySortedProjectsIsEmptyList() { | |
| result.setTopologicallySortedProjects(null); | |
| List<MavenProject> projects = result.getTopologicallySortedProjects(); | |
| assertNotNull(projects); | |
| - assertTrue( | |
| - projects.isEmpty(), | |
| - "Expected collection to be empty but had " + projects.size() + " elements: " + projects); | |
| + assertThat(projects, is(empty())); | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/graph/DefaultGraphBuilderTest.java b/impl/maven-core/src/test/java/org/apache/maven/graph/DefaultGraphBuilderTest.java | |
| index 07bcbf90d4..cabbf41e18 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/graph/DefaultGraphBuilderTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/graph/DefaultGraphBuilderTest.java | |
| @@ -63,9 +63,8 @@ | |
| import static org.apache.maven.execution.MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM; | |
| import static org.apache.maven.execution.MavenExecutionRequest.REACTOR_MAKE_UPSTREAM; | |
| import static org.apache.maven.graph.DefaultGraphBuilderTest.ScenarioBuilder.scenario; | |
| +import static org.assertj.core.api.Assertions.assertThat; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| import static org.mockito.ArgumentMatchers.any; | |
| import static org.mockito.ArgumentMatchers.anyBoolean; | |
| import static org.mockito.ArgumentMatchers.anyList; | |
| @@ -315,22 +314,25 @@ void testGetReactorProjects( | |
| // Then | |
| if (parameterExpectedResult instanceof SelectedProjectsResult selectedProjectsResult) { | |
| - assertFalse(result.hasErrors(), "Expected result not to have errors"); | |
| + assertThat(result.hasErrors()) | |
| + .withFailMessage("Expected result not to have errors") | |
| + .isFalse(); | |
| List<String> expectedProjectNames = selectedProjectsResult.projectNames; | |
| List<MavenProject> actualReactorProjects = result.get().getSortedProjects(); | |
| List<MavenProject> expectedReactorProjects = | |
| expectedProjectNames.stream().map(artifactIdProjectMap::get).collect(toList()); | |
| assertEquals(expectedReactorProjects, actualReactorProjects, parameterDescription); | |
| } else { | |
| - assertTrue(result.hasErrors(), "Expected result to have errors"); | |
| + assertThat(result.hasErrors()) | |
| + .withFailMessage("Expected result to have errors") | |
| + .isTrue(); | |
| Class<? extends Throwable> expectedException = ((ExceptionThrown) parameterExpectedResult).expected; | |
| String partOfMessage = ((ExceptionThrown) parameterExpectedResult).partOfMessage; | |
| - assertEquals(1, ((Collection) result.getProblems()).size()); | |
| - result.getProblems().forEach(p -> { | |
| - assertTrue(expectedException.isInstance(p.getException())); | |
| - assertTrue(p.getException().getMessage().contains(partOfMessage)); | |
| - }); | |
| + assertThat(result.getProblems()).hasSize(1); | |
| + result.getProblems().forEach(p -> assertThat(p.getException()) | |
| + .isInstanceOf(expectedException) | |
| + .hasMessageContaining(partOfMessage)); | |
| } | |
| } | |
| @@ -366,7 +368,9 @@ void testProcessPackagingAttribute() throws ProjectBuildingException { | |
| Result<ProjectDependencyGraph> result = graphBuilder.build(session); | |
| - assertFalse(result.hasErrors(), "Expected result not to have errors"); | |
| + assertThat(result.hasErrors()) | |
| + .withFailMessage("Expected result not to have errors") | |
| + .isFalse(); | |
| List<MavenProject> actualReactorProjects = result.get().getSortedProjects(); | |
| assertEquals(2, actualReactorProjects.size()); | |
| assertEquals("pom", actualReactorProjects.get(1).getPackaging()); | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/graph/DefaultProjectDependencyGraphTest.java b/impl/maven-core/src/test/java/org/apache/maven/graph/DefaultProjectDependencyGraphTest.java | |
| index 9774625ccf..090702135f 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/graph/DefaultProjectDependencyGraphTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/graph/DefaultProjectDependencyGraphTest.java | |
| @@ -100,8 +100,8 @@ public void testGetDownstreamDoesNotDuplicateProjects() throws CycleDetectedExce | |
| graph = new FilteredProjectDependencyGraph(graph, Arrays.asList(aProject, dProject, eProject)); | |
| final List<MavenProject> downstreamProjects = graph.getDownstreamProjects(aProject, false); | |
| assertEquals(2, downstreamProjects.size()); | |
| - assertTrue(downstreamProjects.contains(dProject), "Expected " + downstreamProjects + " to contain " + dProject); | |
| - assertTrue(downstreamProjects.contains(eProject), "Expected " + downstreamProjects + " to contain " + eProject); | |
| + assertTrue(downstreamProjects.contains(dProject)); | |
| + assertTrue(downstreamProjects.contains(eProject)); | |
| } | |
| @Test | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/graph/ProjectSelectorTest.java b/impl/maven-core/src/test/java/org/apache/maven/graph/ProjectSelectorTest.java | |
| index 9c897f8bec..2cdeac39b8 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/graph/ProjectSelectorTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/graph/ProjectSelectorTest.java | |
| @@ -35,11 +35,13 @@ | |
| import org.junit.jupiter.params.provider.EmptySource; | |
| import org.junit.jupiter.params.provider.ValueSource; | |
| -import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| -import static org.junit.jupiter.api.Assertions.assertNull; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.contains; | |
| +import static org.hamcrest.Matchers.containsString; | |
| +import static org.hamcrest.Matchers.is; | |
| +import static org.hamcrest.Matchers.notNullValue; | |
| +import static org.hamcrest.Matchers.nullValue; | |
| import static org.junit.jupiter.api.Assertions.assertThrows; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| import static org.mockito.Mockito.mock; | |
| import static org.mockito.Mockito.when; | |
| @@ -53,7 +55,7 @@ void getBaseDirectoryFromRequestWhenDirectoryIsNullReturnNull() { | |
| final File baseDirectoryFromRequest = sut.getBaseDirectoryFromRequest(mavenExecutionRequest); | |
| - assertNull(baseDirectoryFromRequest); | |
| + assertThat(baseDirectoryFromRequest, nullValue()); | |
| } | |
| @Test | |
| @@ -62,8 +64,8 @@ void getBaseDirectoryFromRequestWhenDirectoryIsValidReturnFile() { | |
| final File baseDirectoryFromRequest = sut.getBaseDirectoryFromRequest(mavenExecutionRequest); | |
| - assertNotNull(baseDirectoryFromRequest); | |
| - assertEquals(new File("path/to/file").getPath(), baseDirectoryFromRequest.getPath()); | |
| + assertThat(baseDirectoryFromRequest, notNullValue()); | |
| + assertThat(baseDirectoryFromRequest.getPath(), is(new File("path/to/file").getPath())); | |
| } | |
| @ParameterizedTest | |
| @@ -71,14 +73,14 @@ void getBaseDirectoryFromRequestWhenDirectoryIsValidReturnFile() { | |
| @EmptySource | |
| void isMatchingProjectNoMatchOnSelectorReturnsFalse(String selector) { | |
| final boolean result = sut.isMatchingProject(createMavenProject("maven-core"), selector, null); | |
| - assertEquals(false, result); | |
| + assertThat(result, is(false)); | |
| } | |
| @ParameterizedTest | |
| @ValueSource(strings = {":maven-core", "org.apache.maven:maven-core"}) | |
| void isMatchingProjectMatchOnSelectorReturnsTrue(String selector) { | |
| final boolean result = sut.isMatchingProject(createMavenProject("maven-core"), selector, null); | |
| - assertEquals(true, result); | |
| + assertThat(result, is(true)); | |
| } | |
| @Test | |
| @@ -91,7 +93,7 @@ void isMatchingProjectMatchOnFileReturnsTrue() throws IOException { | |
| final boolean result = sut.isMatchingProject(mavenProject, selector, tempFile.getParentFile()); | |
| tempFile.delete(); | |
| - assertEquals(true, result); | |
| + assertThat(result, is(true)); | |
| } | |
| @Test | |
| @@ -105,7 +107,7 @@ void isMatchingProjectMatchOnDirectoryReturnsTrue(@TempDir File tempDir) { | |
| final boolean result = sut.isMatchingProject(mavenProject, selector, tempDir); | |
| tempProjectDir.delete(); | |
| - assertEquals(true, result); | |
| + assertThat(result, is(true)); | |
| } | |
| @Test | |
| @@ -120,8 +122,8 @@ void getOptionalProjectsBySelectorsReturnsMatches() { | |
| final Set<MavenProject> optionalProjectsBySelectors = | |
| sut.getOptionalProjectsBySelectors(mavenExecutionRequest, listOfProjects, selectors); | |
| - assertEquals(1, optionalProjectsBySelectors.size()); | |
| - assertEquals(List.of(mavenProject), List.copyOf(optionalProjectsBySelectors)); | |
| + assertThat(optionalProjectsBySelectors.size(), is(1)); | |
| + assertThat(optionalProjectsBySelectors, contains(mavenProject)); | |
| } | |
| @Test | |
| @@ -136,8 +138,8 @@ void getRequiredProjectsBySelectorsThrowsMavenExecutionException() { | |
| final MavenExecutionException exception = assertThrows( | |
| MavenExecutionException.class, | |
| () -> sut.getRequiredProjectsBySelectors(mavenExecutionRequest, listOfProjects, selectors)); | |
| - assertTrue(exception.getMessage().contains("Could not find")); | |
| - assertTrue(exception.getMessage().contains(":required")); | |
| + assertThat(exception.getMessage(), containsString("Could not find")); | |
| + assertThat(exception.getMessage(), containsString(":required")); | |
| } | |
| @Test | |
| @@ -151,8 +153,8 @@ void getRequiredProjectsBySelectorsReturnsProject() throws MavenExecutionExcepti | |
| final Set<MavenProject> requiredProjectsBySelectors = | |
| sut.getRequiredProjectsBySelectors(mavenExecutionRequest, listOfProjects, selectors); | |
| - assertEquals(1, requiredProjectsBySelectors.size()); | |
| - assertEquals(List.of(mavenProject), List.copyOf(requiredProjectsBySelectors)); | |
| + assertThat(requiredProjectsBySelectors.size(), is(1)); | |
| + assertThat(requiredProjectsBySelectors, contains(mavenProject)); | |
| } | |
| @Test | |
| @@ -170,8 +172,8 @@ void getRequiredProjectsBySelectorsReturnsProjectWithChildProjects() throws Mave | |
| final Set<MavenProject> requiredProjectsBySelectors = | |
| sut.getRequiredProjectsBySelectors(mavenExecutionRequest, listOfProjects, selectors); | |
| - assertEquals(2, requiredProjectsBySelectors.size()); | |
| - assertEquals(List.of(mavenProject, child), List.copyOf(requiredProjectsBySelectors)); | |
| + assertThat(requiredProjectsBySelectors.size(), is(2)); | |
| + assertThat(requiredProjectsBySelectors, contains(mavenProject, child)); | |
| } | |
| @Test | |
| @@ -189,8 +191,8 @@ void getOptionalProjectsBySelectorsReturnsProjectWithChildProjects() { | |
| final Set<MavenProject> optionalProjectsBySelectors = | |
| sut.getOptionalProjectsBySelectors(mavenExecutionRequest, listOfProjects, selectors); | |
| - assertEquals(2, optionalProjectsBySelectors.size()); | |
| - assertEquals(List.of(mavenProject, child), List.copyOf(optionalProjectsBySelectors)); | |
| + assertThat(optionalProjectsBySelectors.size(), is(2)); | |
| + assertThat(optionalProjectsBySelectors, contains(mavenProject, child)); | |
| } | |
| private MavenProject createMavenProject(String artifactId) { | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/internal/aether/ReverseTreeRepositoryListenerTest.java b/impl/maven-core/src/test/java/org/apache/maven/internal/aether/ReverseTreeRepositoryListenerTest.java | |
| index 55698bb093..8e7210b979 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/internal/aether/ReverseTreeRepositoryListenerTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/internal/aether/ReverseTreeRepositoryListenerTest.java | |
| @@ -27,10 +27,10 @@ | |
| import org.eclipse.aether.repository.LocalRepository; | |
| import org.junit.jupiter.api.Test; | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| -import static org.junit.jupiter.api.Assertions.assertNull; | |
| -import static org.junit.jupiter.api.Assertions.assertSame; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| +import static org.hamcrest.CoreMatchers.equalTo; | |
| +import static org.hamcrest.CoreMatchers.nullValue; | |
| +import static org.hamcrest.CoreMatchers.sameInstance; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| import static org.mockito.Mockito.mock; | |
| import static org.mockito.Mockito.when; | |
| @@ -51,9 +51,12 @@ void isLocalRepositoryArtifactTest() { | |
| Artifact nonLocalReposioryArtifact = mock(Artifact.class); | |
| when(nonLocalReposioryArtifact.getFile()).thenReturn(new File("something/completely/different")); | |
| - assertTrue(ReverseTreeRepositoryListener.isLocalRepositoryArtifactOrMissing(session, localRepositoryArtifact)); | |
| - assertFalse( | |
| - ReverseTreeRepositoryListener.isLocalRepositoryArtifactOrMissing(session, nonLocalReposioryArtifact)); | |
| + assertThat( | |
| + ReverseTreeRepositoryListener.isLocalRepositoryArtifactOrMissing(session, localRepositoryArtifact), | |
| + equalTo(true)); | |
| + assertThat( | |
| + ReverseTreeRepositoryListener.isLocalRepositoryArtifactOrMissing(session, nonLocalReposioryArtifact), | |
| + equalTo(false)); | |
| } | |
| @Test | |
| @@ -66,14 +69,16 @@ void isMissingArtifactTest() { | |
| Artifact localRepositoryArtifact = mock(Artifact.class); | |
| when(localRepositoryArtifact.getFile()).thenReturn(null); | |
| - assertTrue(ReverseTreeRepositoryListener.isLocalRepositoryArtifactOrMissing(session, localRepositoryArtifact)); | |
| + assertThat( | |
| + ReverseTreeRepositoryListener.isLocalRepositoryArtifactOrMissing(session, localRepositoryArtifact), | |
| + equalTo(true)); | |
| } | |
| @Test | |
| void lookupCollectStepDataTest() { | |
| RequestTrace doesNotHaveIt = | |
| RequestTrace.newChild(null, "foo").newChild("bar").newChild("baz"); | |
| - assertNull(ReverseTreeRepositoryListener.lookupCollectStepData(doesNotHaveIt)); | |
| + assertThat(ReverseTreeRepositoryListener.lookupCollectStepData(doesNotHaveIt), nullValue()); | |
| final CollectStepData data = mock(CollectStepData.class); | |
| @@ -81,18 +86,18 @@ void lookupCollectStepDataTest() { | |
| .newChild("foo") | |
| .newChild("bar") | |
| .newChild("baz"); | |
| - assertSame(data, ReverseTreeRepositoryListener.lookupCollectStepData(haveItFirst)); | |
| + assertThat(ReverseTreeRepositoryListener.lookupCollectStepData(haveItFirst), sameInstance(data)); | |
| RequestTrace haveItLast = RequestTrace.newChild(null, "foo") | |
| .newChild("bar") | |
| .newChild("baz") | |
| .newChild(data); | |
| - assertSame(data, ReverseTreeRepositoryListener.lookupCollectStepData(haveItLast)); | |
| + assertThat(ReverseTreeRepositoryListener.lookupCollectStepData(haveItLast), sameInstance(data)); | |
| RequestTrace haveIt = RequestTrace.newChild(null, "foo") | |
| .newChild("bar") | |
| .newChild(data) | |
| .newChild("baz"); | |
| - assertSame(data, ReverseTreeRepositoryListener.lookupCollectStepData(haveIt)); | |
| + assertThat(ReverseTreeRepositoryListener.lookupCollectStepData(haveIt), sameInstance(data)); | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/internal/impl/PropertiesAsMapTest.java b/impl/maven-core/src/test/java/org/apache/maven/internal/impl/PropertiesAsMapTest.java | |
| index b3b0ec7f2e..b0afd8632c 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/internal/impl/PropertiesAsMapTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/internal/impl/PropertiesAsMapTest.java | |
| @@ -47,13 +47,13 @@ void testPropertiesAsMap() { | |
| assertEquals(2, set.size()); | |
| Iterator<Entry<String, String>> iterator = set.iterator(); | |
| assertNotNull(iterator); | |
| - assertTrue(iterator.hasNext(), "Expected " + iterator + ".hasNext() to return true"); | |
| - assertTrue(iterator.hasNext(), "Expected " + iterator + ".hasNext() to return true"); | |
| + assertTrue(iterator.hasNext()); | |
| + assertTrue(iterator.hasNext()); | |
| Entry<String, String> entry = iterator.next(); | |
| assertNotNull(entry); | |
| entry = iterator.next(); | |
| assertNotNull(entry); | |
| assertThrows(NoSuchElementException.class, () -> iterator.next()); | |
| - assertFalse(iterator.hasNext(), "Expected " + iterator + ".hasNext() to return false"); | |
| + assertFalse(iterator.hasNext()); | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java b/impl/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java | |
| index 04802ccbee..82526ddebd 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java | |
| @@ -157,7 +157,7 @@ void testCreateAndResolveArtifact() { | |
| assertNotNull(resolved); | |
| assertNotNull(resolved.getPath()); | |
| Optional<Path> op = session.getArtifactPath(resolved); | |
| - assertTrue(op.isPresent(), "Expected " + op + ".isPresent() to return true"); | |
| + assertTrue(op.isPresent()); | |
| assertEquals(resolved.getPath(), op.get()); | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomArtifactTransformerTest.java b/impl/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomArtifactTransformerTest.java | |
| index 37c98e39b5..ec08041f24 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomArtifactTransformerTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomArtifactTransformerTest.java | |
| @@ -23,28 +23,17 @@ | |
| import java.nio.file.Files; | |
| import java.nio.file.Path; | |
| import java.nio.file.Paths; | |
| -import java.util.Collection; | |
| -import java.util.List; | |
| -import java.util.Map; | |
| -import org.apache.maven.api.Constants; | |
| import org.apache.maven.model.Model; | |
| import org.apache.maven.model.v4.MavenStaxReader; | |
| import org.apache.maven.project.MavenProject; | |
| import org.eclipse.aether.RepositorySystemSession; | |
| import org.eclipse.aether.SessionData; | |
| -import org.eclipse.aether.artifact.Artifact; | |
| -import org.eclipse.aether.artifact.DefaultArtifact; | |
| -import org.eclipse.aether.deployment.DeployRequest; | |
| -import org.eclipse.aether.installation.InstallRequest; | |
| import org.junit.jupiter.api.Test; | |
| import org.mockito.Mockito; | |
| -import org.xmlunit.builder.DiffBuilder; | |
| -import org.xmlunit.diff.Diff; | |
| +import org.xmlunit.assertj.XmlAssert; | |
| -import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| +import static org.assertj.core.api.Assertions.assertThat; | |
| import static org.mockito.Mockito.when; | |
| class ConsumerPomArtifactTransformerTest { | |
| @@ -73,12 +62,7 @@ void transform() throws Exception { | |
| t.transform(project, systemSessionMock, beforePomFile, tempFile); | |
| } | |
| - Diff diff = DiffBuilder.compare(afterPomFile.toFile()) | |
| - .withTest(tempFile.toFile()) | |
| - .ignoreComments() | |
| - .ignoreWhitespace() | |
| - .build(); | |
| - assertFalse(diff.hasDifferences(), "XML files should be identical: " + diff.toString()); | |
| + XmlAssert.assertThat(tempFile.toFile()).and(afterPomFile.toFile()).areIdentical(); | |
| } | |
| @Test | |
| @@ -105,12 +89,7 @@ void transformJarConsumerPom() throws Exception { | |
| t.transform(project, systemSessionMock, beforePomFile, tempFile); | |
| } | |
| - Diff diff = DiffBuilder.compare(afterPomFile.toFile()) | |
| - .withTest(tempFile.toFile()) | |
| - .ignoreComments() | |
| - .ignoreWhitespace() | |
| - .build(); | |
| - assertFalse(diff.hasDifferences(), "XML files should be identical: " + diff.toString()); | |
| + XmlAssert.assertThat(afterPomFile.toFile()).and(tempFile.toFile()).areIdentical(); | |
| } | |
| @Test | |
| @@ -124,158 +103,6 @@ void injectTransformedArtifactsWithoutPomShouldNotInjectAnyArtifacts() throws IO | |
| new ConsumerPomArtifactTransformer((session, project, src) -> null) | |
| .injectTransformedArtifacts(systemSessionMock, emptyProject); | |
| - assertTrue(emptyProject.getAttachedArtifacts().isEmpty()); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomEnabledByDefault() { | |
| - // Test that build POM deployment is enabled by default | |
| - ConsumerPomArtifactTransformer transformer = new ConsumerPomArtifactTransformer((s, p, f) -> null); | |
| - | |
| - RepositorySystemSession session = createMockSession(Map.of()); | |
| - DeployRequest request = createDeployRequestWithConsumerPom(); | |
| - | |
| - DeployRequest result = transformer.remapDeployArtifacts(session, request); | |
| - | |
| - // Should have both consumer POM (no classifier) and build POM (with "build" classifier) | |
| - Collection<Artifact> artifacts = result.getArtifacts(); | |
| - assertEquals(3, artifacts.size()); // original jar + consumer pom + build pom | |
| - | |
| - assertTrue(artifacts.stream().anyMatch(a -> "pom".equals(a.getExtension()) && "".equals(a.getClassifier()))); | |
| - assertTrue( | |
| - artifacts.stream().anyMatch(a -> "pom".equals(a.getExtension()) && "build".equals(a.getClassifier()))); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomDisabled() { | |
| - // Test that build POM deployment can be disabled | |
| - ConsumerPomArtifactTransformer transformer = new ConsumerPomArtifactTransformer((s, p, f) -> null); | |
| - | |
| - Map<String, Object> configProps = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "false"); | |
| - RepositorySystemSession session = createMockSession(configProps); | |
| - DeployRequest request = createDeployRequestWithConsumerPom(); | |
| - | |
| - DeployRequest result = transformer.remapDeployArtifacts(session, request); | |
| - | |
| - // Should have only consumer POM (no classifier), no build POM | |
| - Collection<Artifact> artifacts = result.getArtifacts(); | |
| - assertEquals(2, artifacts.size()); // original jar + consumer pom (no build pom) | |
| - | |
| - assertTrue(artifacts.stream().anyMatch(a -> "pom".equals(a.getExtension()) && "".equals(a.getClassifier()))); | |
| - assertTrue( | |
| - artifacts.stream().noneMatch(a -> "pom".equals(a.getExtension()) && "build".equals(a.getClassifier()))); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomExplicitlyEnabled() { | |
| - // Test that build POM deployment can be explicitly enabled | |
| - ConsumerPomArtifactTransformer transformer = new ConsumerPomArtifactTransformer((s, p, f) -> null); | |
| - | |
| - Map<String, Object> configProps = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "true"); | |
| - RepositorySystemSession session = createMockSession(configProps); | |
| - DeployRequest request = createDeployRequestWithConsumerPom(); | |
| - | |
| - DeployRequest result = transformer.remapDeployArtifacts(session, request); | |
| - | |
| - // Should have both consumer POM (no classifier) and build POM (with "build" classifier) | |
| - Collection<Artifact> artifacts = result.getArtifacts(); | |
| - assertEquals(3, artifacts.size()); // original jar + consumer pom + build pom | |
| - | |
| - assertTrue(artifacts.stream().anyMatch(a -> "pom".equals(a.getExtension()) && "".equals(a.getClassifier()))); | |
| - assertTrue( | |
| - artifacts.stream().anyMatch(a -> "pom".equals(a.getExtension()) && "build".equals(a.getClassifier()))); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployBuildPomWithBooleanValue() { | |
| - // Test that build POM deployment works with Boolean values (not just strings) | |
| - ConsumerPomArtifactTransformer transformer = new ConsumerPomArtifactTransformer((s, p, f) -> null); | |
| - | |
| - Map<String, Object> configProps = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, Boolean.FALSE); | |
| - RepositorySystemSession session = createMockSession(configProps); | |
| - DeployRequest request = createDeployRequestWithConsumerPom(); | |
| - | |
| - DeployRequest result = transformer.remapDeployArtifacts(session, request); | |
| - | |
| - // Should have only consumer POM (no classifier), no build POM | |
| - Collection<Artifact> artifacts = result.getArtifacts(); | |
| - assertEquals(2, artifacts.size()); // original jar + consumer pom (no build pom) | |
| - | |
| - assertTrue(artifacts.stream().anyMatch(a -> "pom".equals(a.getExtension()) && "".equals(a.getClassifier()))); | |
| - assertTrue( | |
| - artifacts.stream().noneMatch(a -> "pom".equals(a.getExtension()) && "build".equals(a.getClassifier()))); | |
| - } | |
| - | |
| - @Test | |
| - void testInstallAlwaysIncludesBuildPom() { | |
| - // Test that install always includes build POM regardless of the deployment setting | |
| - ConsumerPomArtifactTransformer transformer = new ConsumerPomArtifactTransformer((s, p, f) -> null); | |
| - | |
| - Map<String, Object> configProps = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "false"); | |
| - RepositorySystemSession session = createMockSession(configProps); | |
| - InstallRequest request = createInstallRequestWithConsumerPom(); | |
| - | |
| - InstallRequest result = transformer.remapInstallArtifacts(session, request); | |
| - | |
| - // Should have both consumer POM and build POM even when deployment is disabled | |
| - Collection<Artifact> artifacts = result.getArtifacts(); | |
| - assertEquals(3, artifacts.size()); // original jar + consumer pom + build pom | |
| - | |
| - assertTrue(artifacts.stream().anyMatch(a -> "pom".equals(a.getExtension()) && "".equals(a.getClassifier()))); | |
| - assertTrue( | |
| - artifacts.stream().anyMatch(a -> "pom".equals(a.getExtension()) && "build".equals(a.getClassifier()))); | |
| - } | |
| - | |
| - @Test | |
| - void testDeployWithoutConsumerPomIsUnaffected() { | |
| - // Test that requests without consumer POMs are not affected by the setting | |
| - ConsumerPomArtifactTransformer transformer = new ConsumerPomArtifactTransformer((s, p, f) -> null); | |
| - | |
| - Map<String, Object> configProps = Map.of(Constants.MAVEN_DEPLOY_BUILD_POM, "false"); | |
| - RepositorySystemSession session = createMockSession(configProps); | |
| - DeployRequest request = createDeployRequestWithoutConsumerPom(); | |
| - | |
| - DeployRequest result = transformer.remapDeployArtifacts(session, request); | |
| - | |
| - // Should be unchanged since there's no consumer POM | |
| - assertEquals(request.getArtifacts(), result.getArtifacts()); | |
| - } | |
| - | |
| - private RepositorySystemSession createMockSession(Map<String, Object> configProperties) { | |
| - RepositorySystemSession session = Mockito.mock(RepositorySystemSession.class); | |
| - when(session.getConfigProperties()).thenReturn(configProperties); | |
| - return session; | |
| - } | |
| - | |
| - private DeployRequest createDeployRequestWithConsumerPom() { | |
| - DeployRequest request = new DeployRequest(); | |
| - List<Artifact> artifacts = List.of( | |
| - new DefaultArtifact("com.example", "test", "", "jar", "1.0.0"), | |
| - new DefaultArtifact("com.example", "test", "", "pom", "1.0.0"), // main POM | |
| - new DefaultArtifact("com.example", "test", "consumer", "pom", "1.0.0") // consumer POM | |
| - ); | |
| - request.setArtifacts(artifacts); | |
| - return request; | |
| - } | |
| - | |
| - private InstallRequest createInstallRequestWithConsumerPom() { | |
| - InstallRequest request = new InstallRequest(); | |
| - List<Artifact> artifacts = List.of( | |
| - new DefaultArtifact("com.example", "test", "", "jar", "1.0.0"), | |
| - new DefaultArtifact("com.example", "test", "", "pom", "1.0.0"), // main POM | |
| - new DefaultArtifact("com.example", "test", "consumer", "pom", "1.0.0") // consumer POM | |
| - ); | |
| - request.setArtifacts(artifacts); | |
| - return request; | |
| - } | |
| - | |
| - private DeployRequest createDeployRequestWithoutConsumerPom() { | |
| - DeployRequest request = new DeployRequest(); | |
| - List<Artifact> artifacts = List.of( | |
| - new DefaultArtifact("com.example", "test", "", "jar", "1.0.0"), | |
| - new DefaultArtifact("com.example", "test", "", "pom", "1.0.0") // only main POM | |
| - ); | |
| - request.setArtifacts(artifacts); | |
| - return request; | |
| + assertThat(emptyProject.getAttachedArtifacts()).isEmpty(); | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/lifecycle/DefaultLifecyclesTest.java b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/DefaultLifecyclesTest.java | |
| index 0b36378871..0856e5ce6e 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/lifecycle/DefaultLifecyclesTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/DefaultLifecyclesTest.java | |
| @@ -34,7 +34,10 @@ | |
| import org.codehaus.plexus.testing.PlexusTest; | |
| import org.junit.jupiter.api.Test; | |
| -import static org.junit.jupiter.api.Assertions.assertEquals; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.arrayWithSize; | |
| +import static org.hamcrest.Matchers.hasSize; | |
| +import static org.hamcrest.Matchers.is; | |
| import static org.mockito.Mockito.mock; | |
| import static org.mockito.Mockito.when; | |
| @@ -48,29 +51,29 @@ class DefaultLifecyclesTest { | |
| @Test | |
| void testDefaultLifecycles() { | |
| final List<Lifecycle> lifecycles = defaultLifeCycles.getLifeCycles(); | |
| - assertEquals(3, lifecycles.size()); | |
| - assertEquals(3, DefaultLifecycles.STANDARD_LIFECYCLES.length); | |
| + assertThat(lifecycles, hasSize(3)); | |
| + assertThat(DefaultLifecycles.STANDARD_LIFECYCLES, arrayWithSize(3)); | |
| } | |
| @Test | |
| void testDefaultLifecycle() { | |
| final Lifecycle lifecycle = getLifeCycleById("default"); | |
| - assertEquals("default", lifecycle.getId()); | |
| - assertEquals(54, lifecycle.getPhases().size()); | |
| + assertThat(lifecycle.getId(), is("default")); | |
| + assertThat(lifecycle.getPhases(), hasSize(54)); | |
| } | |
| @Test | |
| void testCleanLifecycle() { | |
| final Lifecycle lifecycle = getLifeCycleById("clean"); | |
| - assertEquals("clean", lifecycle.getId()); | |
| - assertEquals(3, lifecycle.getPhases().size()); | |
| + assertThat(lifecycle.getId(), is("clean")); | |
| + assertThat(lifecycle.getPhases(), hasSize(3)); | |
| } | |
| @Test | |
| void testSiteLifecycle() { | |
| final Lifecycle lifecycle = getLifeCycleById("site"); | |
| - assertEquals("site", lifecycle.getId()); | |
| - assertEquals(6, lifecycle.getPhases().size()); | |
| + assertThat(lifecycle.getId(), is("site")); | |
| + assertThat(lifecycle.getPhases(), hasSize(6)); | |
| } | |
| @Test | |
| @@ -90,10 +93,10 @@ void testCustomLifecycle() throws ComponentLookupException { | |
| List.of(new DefaultLifecycleRegistry.LifecycleWrapperProvider(mockedPlexusContainer))), | |
| new DefaultLookup(mockedPlexusContainer)); | |
| - assertEquals("clean", dl.getLifeCycles().get(0).getId()); | |
| - assertEquals("default", dl.getLifeCycles().get(1).getId()); | |
| - assertEquals("site", dl.getLifeCycles().get(2).getId()); | |
| - assertEquals("etl", dl.getLifeCycles().get(3).getId()); | |
| + assertThat(dl.getLifeCycles().get(0).getId(), is("clean")); | |
| + assertThat(dl.getLifeCycles().get(1).getId(), is("default")); | |
| + assertThat(dl.getLifeCycles().get(2).getId(), is("site")); | |
| + assertThat(dl.getLifeCycles().get(3).getId(), is("etl")); | |
| } | |
| private Lifecycle getLifeCycleById(String id) { | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java | |
| index 09f1027e99..ca45e941b4 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java | |
| @@ -49,6 +49,8 @@ | |
| import org.apache.maven.project.MavenProject; | |
| import org.junit.jupiter.api.Test; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.hasSize; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| import static org.junit.jupiter.api.Assertions.assertNull; | |
| @@ -286,7 +288,7 @@ void testLifecycleQueryingUsingADefaultLifecyclePhase() throws Exception { | |
| void testLifecyclePluginsRetrievalForDefaultLifecycle() throws Exception { | |
| List<Plugin> plugins = new ArrayList<>(lifecycleExecutor.getPluginsBoundByDefaultToAllLifecycles("jar")); | |
| - assertEquals(8, plugins.size(), plugins.toString()); | |
| + assertThat(plugins.toString(), plugins, hasSize(8)); | |
| } | |
| @Test | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ProjectBuildListTest.java b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ProjectBuildListTest.java | |
| index 676a7b3f94..761ac82ec4 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ProjectBuildListTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/internal/ProjectBuildListTest.java | |
| @@ -22,8 +22,10 @@ | |
| import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub; | |
| import org.junit.jupiter.api.Test; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.greaterThanOrEqualTo; | |
| +import static org.hamcrest.Matchers.is; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| /** | |
| */ | |
| @@ -33,9 +35,10 @@ void testGetByTaskSegment() throws Exception { | |
| final MavenSession session = ProjectDependencyGraphStub.getMavenSession(); | |
| ProjectBuildList projectBuildList = ProjectDependencyGraphStub.getProjectBuildList(session); | |
| TaskSegment taskSegment = projectBuildList.get(0).getTaskSegment(); | |
| - assertTrue( | |
| - projectBuildList.size() >= 6, | |
| - "Expected size " + projectBuildList.size() + " to be >= 6 for collection: " + projectBuildList); | |
| + assertThat( | |
| + "This test assumes there are at least 6 elements in projectBuilds", | |
| + projectBuildList.size(), | |
| + is(greaterThanOrEqualTo(6))); | |
| final ProjectBuildList byTaskSegment = projectBuildList.getByTaskSegment(taskSegment); | |
| assertEquals(projectBuildList.size(), byTaskSegment.size()); // TODO Make multiple segments on projectBuildList | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/lifecycle/internal/builder/multithreaded/SmartProjectComparatorTest.java b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/internal/builder/multithreaded/SmartProjectComparatorTest.java | |
| deleted file mode 100644 | |
| index 50cac26e1b..0000000000 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/lifecycle/internal/builder/multithreaded/SmartProjectComparatorTest.java | |
| +++ /dev/null | |
| @@ -1,211 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.lifecycle.internal.builder.multithreaded; | |
| - | |
| -import java.util.Arrays; | |
| -import java.util.List; | |
| -import java.util.concurrent.CountDownLatch; | |
| -import java.util.concurrent.ExecutorService; | |
| -import java.util.concurrent.Executors; | |
| -import java.util.concurrent.TimeUnit; | |
| -import java.util.concurrent.atomic.AtomicReference; | |
| - | |
| -import org.apache.maven.execution.ProjectDependencyGraph; | |
| -import org.apache.maven.lifecycle.internal.stub.ProjectDependencyGraphStub; | |
| -import org.apache.maven.project.MavenProject; | |
| -import org.junit.jupiter.api.BeforeEach; | |
| -import org.junit.jupiter.api.Test; | |
| - | |
| -import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| - | |
| -/** | |
| - * Test for SmartProjectComparator to verify critical path scheduling logic. | |
| - */ | |
| -class SmartProjectComparatorTest { | |
| - | |
| - private SmartProjectComparator comparator; | |
| - private ProjectDependencyGraph dependencyGraph; | |
| - | |
| - @BeforeEach | |
| - void setUp() { | |
| - dependencyGraph = new ProjectDependencyGraphStub(); | |
| - comparator = new SmartProjectComparator(dependencyGraph); | |
| - } | |
| - | |
| - @Test | |
| - void testProjectWeightCalculation() { | |
| - // Test that projects with longer downstream chains get higher weights | |
| - // Graph: A -> B,C; B -> X,Y; C -> X,Z | |
| - MavenProject projectA = ProjectDependencyGraphStub.A; | |
| - MavenProject projectB = ProjectDependencyGraphStub.B; | |
| - MavenProject projectC = ProjectDependencyGraphStub.C; | |
| - MavenProject projectX = ProjectDependencyGraphStub.X; | |
| - | |
| - long weightA = comparator.getProjectWeight(projectA); | |
| - long weightB = comparator.getProjectWeight(projectB); | |
| - long weightC = comparator.getProjectWeight(projectC); | |
| - long weightX = comparator.getProjectWeight(projectX); | |
| - | |
| - // Project A should have the highest weight as it's at the root | |
| - assertTrue(weightA > weightB, "Project A should have weight > Project B"); | |
| - assertTrue(weightA > weightC, "Project A should have weight > Project C"); | |
| - assertTrue(weightB > weightX, "Project B should have weight > Project X"); | |
| - assertTrue(weightC > weightX, "Project C should have weight > Project X"); | |
| - } | |
| - | |
| - @Test | |
| - void testComparatorOrdering() { | |
| - List<MavenProject> projects = Arrays.asList( | |
| - ProjectDependencyGraphStub.X, | |
| - ProjectDependencyGraphStub.C, | |
| - ProjectDependencyGraphStub.A, | |
| - ProjectDependencyGraphStub.B); | |
| - | |
| - // Sort using the comparator | |
| - projects.sort(comparator.getComparator()); | |
| - | |
| - // Project A should come first (highest weight) | |
| - assertEquals( | |
| - ProjectDependencyGraphStub.A, | |
| - projects.get(0), | |
| - "Project A should be first (highest critical path weight)"); | |
| - | |
| - // B and C should come before X (they have higher weights) | |
| - assertTrue( | |
| - projects.indexOf(ProjectDependencyGraphStub.B) < projects.indexOf(ProjectDependencyGraphStub.X), | |
| - "Project B should come before X"); | |
| - assertTrue( | |
| - projects.indexOf(ProjectDependencyGraphStub.C) < projects.indexOf(ProjectDependencyGraphStub.X), | |
| - "Project C should come before X"); | |
| - } | |
| - | |
| - @Test | |
| - void testWeightConsistency() { | |
| - // Test that weights are consistent across multiple calls | |
| - MavenProject project = ProjectDependencyGraphStub.A; | |
| - | |
| - long weight1 = comparator.getProjectWeight(project); | |
| - long weight2 = comparator.getProjectWeight(project); | |
| - | |
| - assertEquals(weight1, weight2, "Project weight should be consistent"); | |
| - } | |
| - | |
| - @Test | |
| - void testDependencyChainLength() { | |
| - // Test that projects with longer dependency chains get higher weights | |
| - // In the stub: A -> B,C; B -> X,Y; C -> X,Z | |
| - long weightA = comparator.getProjectWeight(ProjectDependencyGraphStub.A); | |
| - long weightB = comparator.getProjectWeight(ProjectDependencyGraphStub.B); | |
| - long weightC = comparator.getProjectWeight(ProjectDependencyGraphStub.C); | |
| - long weightX = comparator.getProjectWeight(ProjectDependencyGraphStub.X); | |
| - long weightY = comparator.getProjectWeight(ProjectDependencyGraphStub.Y); | |
| - long weightZ = comparator.getProjectWeight(ProjectDependencyGraphStub.Z); | |
| - | |
| - // Verify the actual chain length calculation | |
| - // Leaf nodes (no downstream dependencies) | |
| - assertEquals(1L, weightX, "Project X should have weight 1 (1 + 0)"); | |
| - assertEquals(1L, weightY, "Project Y should have weight 1 (1 + 0)"); | |
| - assertEquals(1L, weightZ, "Project Z should have weight 1 (1 + 0)"); | |
| - | |
| - // Middle nodes | |
| - assertEquals(2L, weightB, "Project B should have weight 2 (1 + max(X=1, Y=1))"); | |
| - assertEquals(2L, weightC, "Project C should have weight 2 (1 + max(X=1, Z=1))"); | |
| - | |
| - // Root node | |
| - assertEquals(3L, weightA, "Project A should have weight 3 (1 + max(B=2, C=2))"); | |
| - } | |
| - | |
| - @Test | |
| - void testSameWeightOrdering() { | |
| - // Test that projects with the same weight are ordered by project ID | |
| - // Projects B and C both have weight 2, so they should be ordered by project ID | |
| - List<MavenProject> projects = Arrays.asList( | |
| - ProjectDependencyGraphStub.C, // weight=2, ID contains "C" | |
| - ProjectDependencyGraphStub.B // weight=2, ID contains "B" | |
| - ); | |
| - | |
| - projects.sort(comparator.getComparator()); | |
| - | |
| - // Both have same weight (2), so ordering should be by project ID | |
| - // Project B should come before C alphabetically by project ID | |
| - assertEquals( | |
| - ProjectDependencyGraphStub.B, | |
| - projects.get(0), | |
| - "Project B should come before C when they have the same weight (ordered by project ID)"); | |
| - assertEquals( | |
| - ProjectDependencyGraphStub.C, | |
| - projects.get(1), | |
| - "Project C should come after B when they have the same weight (ordered by project ID)"); | |
| - | |
| - // Verify they actually have the same weight | |
| - long weightB = comparator.getProjectWeight(ProjectDependencyGraphStub.B); | |
| - long weightC = comparator.getProjectWeight(ProjectDependencyGraphStub.C); | |
| - assertEquals(weightB, weightC, "Projects B and C should have the same weight"); | |
| - } | |
| - | |
| - @Test | |
| - void testConcurrentWeightCalculation() throws Exception { | |
| - // Test that concurrent weight calculation doesn't cause recursive update issues | |
| - // This test simulates the scenario that causes the IllegalStateException | |
| - | |
| - int numThreads = 10; | |
| - int numIterations = 100; | |
| - ExecutorService executor = Executors.newFixedThreadPool(numThreads); | |
| - CountDownLatch latch = new CountDownLatch(numThreads); | |
| - AtomicReference<Exception> exception = new AtomicReference<>(); | |
| - | |
| - for (int i = 0; i < numThreads; i++) { | |
| - executor.submit(() -> { | |
| - try { | |
| - for (int j = 0; j < numIterations; j++) { | |
| - // Simulate concurrent access to weight calculation | |
| - // This can trigger the recursive update issue | |
| - List<MavenProject> projects = Arrays.asList( | |
| - ProjectDependencyGraphStub.A, | |
| - ProjectDependencyGraphStub.B, | |
| - ProjectDependencyGraphStub.C, | |
| - ProjectDependencyGraphStub.X, | |
| - ProjectDependencyGraphStub.Y, | |
| - ProjectDependencyGraphStub.Z); | |
| - | |
| - // Sort projects concurrently - this triggers weight calculation | |
| - projects.sort(comparator.getComparator()); | |
| - | |
| - // Also directly access weights to increase contention | |
| - for (MavenProject project : projects) { | |
| - comparator.getProjectWeight(project); | |
| - } | |
| - } | |
| - } catch (Exception e) { | |
| - exception.set(e); | |
| - } finally { | |
| - latch.countDown(); | |
| - } | |
| - }); | |
| - } | |
| - | |
| - latch.await(30, TimeUnit.SECONDS); | |
| - executor.shutdown(); | |
| - | |
| - if (exception.get() != null) { | |
| - throw exception.get(); | |
| - } | |
| - } | |
| -} | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/ProjectDependencyGraphStubTest.java b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/ProjectDependencyGraphStubTest.java | |
| index fc85cf772c..2a12af0725 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/ProjectDependencyGraphStubTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/ProjectDependencyGraphStubTest.java | |
| @@ -43,29 +43,21 @@ void testADependencies() { | |
| void testBDependencies() { | |
| final List<MavenProject> bProjects = stub.getUpstreamProjects(ProjectDependencyGraphStub.B, false); | |
| assertEquals(1, bProjects.size()); | |
| - assertTrue( | |
| - bProjects.contains(ProjectDependencyGraphStub.A), | |
| - "Expected " + bProjects + " to contain " + ProjectDependencyGraphStub.A); | |
| + assertTrue(bProjects.contains(ProjectDependencyGraphStub.A)); | |
| } | |
| @Test | |
| void testCDependencies() { | |
| final List<MavenProject> cProjects = stub.getUpstreamProjects(ProjectDependencyGraphStub.C, false); | |
| assertEquals(1, cProjects.size()); | |
| - assertTrue( | |
| - cProjects.contains(ProjectDependencyGraphStub.A), | |
| - "Expected " + cProjects + " to contain " + ProjectDependencyGraphStub.A); | |
| + assertTrue(cProjects.contains(ProjectDependencyGraphStub.A)); | |
| } | |
| @Test | |
| void testXDependencies() { | |
| final List<MavenProject> cProjects = stub.getUpstreamProjects(ProjectDependencyGraphStub.X, false); | |
| assertEquals(2, cProjects.size()); | |
| - assertTrue( | |
| - cProjects.contains(ProjectDependencyGraphStub.C), | |
| - "Expected " + cProjects + " to contain " + ProjectDependencyGraphStub.C); | |
| - assertTrue( | |
| - cProjects.contains(ProjectDependencyGraphStub.B), | |
| - "Expected " + cProjects + " to contain " + ProjectDependencyGraphStub.B); | |
| + assertTrue(cProjects.contains(ProjectDependencyGraphStub.C)); | |
| + assertTrue(cProjects.contains(ProjectDependencyGraphStub.B)); | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/plugin/internal/MavenPluginValidatorTest.java b/impl/maven-core/src/test/java/org/apache/maven/plugin/internal/MavenPluginValidatorTest.java | |
| index 8456e54cdf..12c0bba71d 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/plugin/internal/MavenPluginValidatorTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/plugin/internal/MavenPluginValidatorTest.java | |
| @@ -59,8 +59,7 @@ void testValidate() { | |
| descriptor.setVersion("0.1"); | |
| List<String> errors = new ArrayList<>(); | |
| mavenPluginValidator.validate(plugin, descriptor, errors); | |
| - assertTrue( | |
| - errors.isEmpty(), "Expected collection to be empty but had " + errors.size() + " elements: " + errors); | |
| + assertTrue(errors.isEmpty()); | |
| } | |
| @Test | |
| @@ -79,7 +78,7 @@ void testInvalidGroupId() { | |
| descriptor.setVersion("0.1"); | |
| List<String> errors = new ArrayList<>(); | |
| mavenPluginValidator.validate(plugin, descriptor, errors); | |
| - assertFalse(errors.isEmpty(), "Expected collection to not be empty but was empty"); | |
| + assertFalse(errors.isEmpty()); | |
| } | |
| @Test | |
| @@ -98,7 +97,7 @@ void testInvalidArtifactId() { | |
| descriptor.setVersion("0.1"); | |
| List<String> errors = new ArrayList<>(); | |
| mavenPluginValidator.validate(plugin, descriptor, errors); | |
| - assertFalse(errors.isEmpty(), "Expected collection to not be empty but was empty"); | |
| + assertFalse(errors.isEmpty()); | |
| } | |
| @Test | |
| @@ -116,6 +115,6 @@ void testInvalidVersion() { | |
| descriptor.setArtifactId("maven-it-plugin"); | |
| List<String> errors = new ArrayList<>(); | |
| mavenPluginValidator.validate(plugin, descriptor, errors); | |
| - assertFalse(errors.isEmpty(), "Expected collection to not be empty but was empty"); | |
| + assertFalse(errors.isEmpty()); | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java b/impl/maven-core/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java | |
| index 3f6261f27f..3c5bcdd0ac 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java | |
| @@ -20,19 +20,13 @@ | |
| import java.io.File; | |
| import java.io.InputStream; | |
| -import java.nio.file.FileSystem; | |
| import java.nio.file.Files; | |
| import java.nio.file.Path; | |
| import java.nio.file.StandardCopyOption; | |
| import java.util.List; | |
| -import java.util.stream.Stream; | |
| -import com.google.common.jimfs.Configuration; | |
| -import com.google.common.jimfs.Jimfs; | |
| import org.apache.maven.api.model.InputLocation; | |
| import org.apache.maven.api.model.InputSource; | |
| -import org.apache.maven.api.services.ModelSource; | |
| -import org.apache.maven.api.services.Sources; | |
| import org.apache.maven.artifact.Artifact; | |
| import org.apache.maven.execution.MavenSession; | |
| import org.apache.maven.impl.InternalSession; | |
| @@ -43,12 +37,15 @@ | |
| import org.junit.jupiter.api.Disabled; | |
| import org.junit.jupiter.api.Test; | |
| import org.junit.jupiter.api.io.TempDir; | |
| -import org.junit.jupiter.params.ParameterizedTest; | |
| -import org.junit.jupiter.params.provider.Arguments; | |
| -import org.junit.jupiter.params.provider.MethodSource; | |
| import org.mockito.Mockito; | |
| +import static org.apache.maven.project.ProjectBuildingResultWithProblemMessageMatcher.projectBuildingResultWithProblemMessage; | |
| import static org.codehaus.plexus.testing.PlexusExtension.getTestFile; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.contains; | |
| +import static org.hamcrest.Matchers.containsString; | |
| +import static org.hamcrest.Matchers.greaterThan; | |
| +import static org.hamcrest.Matchers.is; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| import static org.junit.jupiter.api.Assertions.assertFalse; | |
| import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| @@ -63,16 +60,6 @@ class DefaultMavenProjectBuilderTest extends AbstractMavenProjectTestCase { | |
| @TempDir | |
| Path projectRoot; | |
| - /** | |
| - * Provides file system configurations for testing both Windows and Unix path behaviors. | |
| - * This allows us to test cross-platform path handling on any development machine. | |
| - */ | |
| - static Stream<Arguments> fileSystemConfigurations() { | |
| - return Stream.of( | |
| - Arguments.of("Unix", Configuration.unix(), "/"), | |
| - Arguments.of("Windows", Configuration.windows(), "\\")); | |
| - } | |
| - | |
| @Override | |
| @BeforeEach | |
| public void setUp() throws Exception { | |
| @@ -120,7 +107,7 @@ void testFutureModelVersion() throws Exception { | |
| ProjectBuildingException e = assertThrows( | |
| ProjectBuildingException.class, () -> getProject(f1), "Expected to fail for future versions"); | |
| - assertTrue(e.getMessage().contains("Building this project requires a newer version of Maven")); | |
| + assertThat(e.getMessage(), containsString("Building this project requires a newer version of Maven")); | |
| } | |
| @Test | |
| @@ -131,7 +118,7 @@ void testPastModelVersion() throws Exception { | |
| ProjectBuildingException e = assertThrows( | |
| ProjectBuildingException.class, () -> getProject(f1), "Expected to fail for past versions"); | |
| - assertTrue(e.getMessage().contains("Building this project requires an older version of Maven")); | |
| + assertThat(e.getMessage(), containsString("Building this project requires an older version of Maven")); | |
| } | |
| @Test | |
| @@ -140,7 +127,7 @@ void testFutureSchemaModelVersion() throws Exception { | |
| ProjectBuildingException e = assertThrows( | |
| ProjectBuildingException.class, () -> getProject(f1), "Expected to fail for future versions"); | |
| - assertTrue(e.getMessage().contains("Building this project requires a newer version of Maven")); | |
| + assertThat(e.getMessage(), containsString("Building this project requires a newer version of Maven")); | |
| } | |
| @Test | |
| @@ -159,7 +146,7 @@ void testBuildStubModelForMissingRemotePom() throws Exception { | |
| assertNull(project.getParent()); | |
| assertNull(project.getParentArtifact()); | |
| - assertFalse(project.isExecutionRoot(), "Expected " + project + ".isExecutionRoot() to return false"); | |
| + assertFalse(project.isExecutionRoot()); | |
| } | |
| @Test | |
| @@ -213,9 +200,7 @@ void testBuildParentVersionRangeLocallyWithoutChildVersion() throws Exception { | |
| ProjectBuildingException.class, | |
| () -> getProject(f1), | |
| "Expected 'ProjectBuildingException' not thrown."); | |
| - assertEquals(1, e.getResults().size()); | |
| - ProjectBuildingResultWithProblemMessageAssert.assertThat(e.getResults().get(0)) | |
| - .hasProblemMessage("Version must be a constant"); | |
| + assertThat(e.getResults(), contains(projectBuildingResultWithProblemMessage("Version must be a constant"))); | |
| } | |
| /** | |
| @@ -230,9 +215,7 @@ void testBuildParentVersionRangeLocallyWithChildProjectVersionExpression() throw | |
| ProjectBuildingException.class, | |
| () -> getProject(f1), | |
| "Expected 'ProjectBuildingException' not thrown."); | |
| - assertEquals(1, e.getResults().size()); | |
| - ProjectBuildingResultWithProblemMessageAssert.assertThat(e.getResults().get(0)) | |
| - .hasProblemMessage("Version must be a constant"); | |
| + assertThat(e.getResults(), contains(projectBuildingResultWithProblemMessage("Version must be a constant"))); | |
| } | |
| /** | |
| @@ -295,9 +278,7 @@ void testBuildParentVersionRangeExternallyWithoutChildVersion() throws Exception | |
| ProjectBuildingException.class, | |
| () -> getProjectFromRemoteRepository(f1), | |
| "Expected 'ProjectBuildingException' not thrown."); | |
| - assertEquals(1, e.getResults().size()); | |
| - ProjectBuildingResultWithProblemMessageAssert.assertThat(e.getResults().get(0)) | |
| - .hasProblemMessage("Version must be a constant"); | |
| + assertThat(e.getResults(), contains(projectBuildingResultWithProblemMessage("Version must be a constant"))); | |
| } | |
| /** | |
| @@ -312,9 +293,7 @@ void testBuildParentVersionRangeExternallyWithChildProjectVersionExpression() th | |
| ProjectBuildingException.class, | |
| () -> getProjectFromRemoteRepository(f1), | |
| "Expected 'ProjectBuildingException' not thrown."); | |
| - assertEquals(1, e.getResults().size()); | |
| - ProjectBuildingResultWithProblemMessageAssert.assertThat(e.getResults().get(0)) | |
| - .hasProblemMessage("Version must be a constant"); | |
| + assertThat(e.getResults(), contains(projectBuildingResultWithProblemMessage("Version must be a constant"))); | |
| } | |
| /** | |
| @@ -337,7 +316,7 @@ void rereadPomMng7063() throws Exception { | |
| MavenProject project = | |
| projectBuilder.build(pom.toFile(), buildingRequest).getProject(); | |
| - assertEquals("aid", project.getName()); // inherited from artifactId | |
| + assertThat(project.getName(), is("aid")); // inherited from artifactId | |
| try (InputStream pomResource = | |
| DefaultMavenProjectBuilderTest.class.getResourceAsStream("/projects/reread/pom2.xml")) { | |
| @@ -345,7 +324,7 @@ void rereadPomMng7063() throws Exception { | |
| } | |
| project = projectBuilder.build(pom.toFile(), buildingRequest).getProject(); | |
| - assertEquals("PROJECT NAME", project.getName()); | |
| + assertThat(project.getName(), is("PROJECT NAME")); | |
| } | |
| @Test | |
| @@ -366,177 +345,79 @@ void testActivatedProfileBySource() throws Exception { | |
| project.getInjectedProfileIds().get(project.getId()).stream().noneMatch("active-by-default"::equals)); | |
| } | |
| - /** | |
| - * Parameterized version of testActivatedDefaultProfileBySource that demonstrates | |
| - * cross-platform path behavior using JIMFS to simulate both Windows and Unix file systems. | |
| - * This test shows how the path separator expectations differ between platforms. | |
| - */ | |
| - @ParameterizedTest(name = "testActivatedDefaultProfileBySource[{0}]") | |
| - @MethodSource("fileSystemConfigurations") | |
| - void testActivatedDefaultProfileBySource(String fsName, Configuration fsConfig, String separator) throws Exception { | |
| + @Test | |
| + void testActivatedDefaultProfileBySource() throws Exception { | |
| File testPom = getTestFile("src/test/resources/projects/pom-with-profiles/pom.xml"); | |
| - try (FileSystem fs = Jimfs.newFileSystem(fsName, fsConfig)) { | |
| - Path path = fs.getPath("projects", "pom-with-profiles", "pom.xml"); | |
| - Files.createDirectories(path.getParent()); | |
| - Files.copy(testPom.toPath(), path); | |
| - ModelSource source = Sources.buildSource(path); | |
| - | |
| - ProjectBuildingRequest request = newBuildingRequest(); | |
| - request.setLocalRepository(getLocalRepository()); | |
| - | |
| - MavenProject project = projectBuilder.build(source, request).getProject(); | |
| - | |
| - assertTrue(project.getInjectedProfileIds().keySet().containsAll(List.of("external", project.getId()))); | |
| - assertTrue(project.getInjectedProfileIds().get("external").isEmpty()); | |
| - assertTrue(project.getInjectedProfileIds().get(project.getId()).stream() | |
| - .noneMatch("profile1"::equals)); | |
| - assertTrue(project.getInjectedProfileIds().get(project.getId()).stream() | |
| - .noneMatch("profile2"::equals)); | |
| - assertTrue(project.getInjectedProfileIds().get(project.getId()).stream() | |
| - .anyMatch("active-by-default"::equals)); | |
| - | |
| - InternalMavenSession session = Mockito.mock(InternalMavenSession.class); | |
| - List<org.apache.maven.api.model.Profile> activeProfiles = | |
| - new DefaultProject(session, project).getDeclaredActiveProfiles(); | |
| - assertEquals(1, activeProfiles.size()); | |
| - org.apache.maven.api.model.Profile profile = activeProfiles.get(0); | |
| - assertEquals("active-by-default", profile.getId()); | |
| - InputLocation location = profile.getLocation(""); | |
| - assertNotNull(location, "Profile location should not be null for profile: " + profile.getId()); | |
| - assertTrue( | |
| - location.getLineNumber() > 0, | |
| - "Profile location line number should be positive, but was: " + location.getLineNumber() | |
| - + " for profile: " + profile.getId()); | |
| - assertTrue( | |
| - location.getColumnNumber() > 0, | |
| - "Profile location column number should be positive, but was: " + location.getColumnNumber() | |
| - + " for profile: " + profile.getId()); | |
| - assertNotNull( | |
| - location.getSource(), "Profile location source should not be null for profile: " + profile.getId()); | |
| - assertTrue( | |
| - location.getSource().getLocation().contains("pom-with-profiles/pom.xml"), | |
| - "Profile location should contain 'pom-with-profiles/pom.xml', but was: " | |
| - + location.getSource().getLocation() + " for profile: " + profile.getId()); | |
| - | |
| - // This demonstrates the cross-platform path behavior: | |
| - // - On Unix systems, paths use forward slashes (/) | |
| - // - On Windows systems, paths use backslashes (\) | |
| - // - The actual file system being used determines the separator | |
| - String actualLocation = location.getSource().getLocation(); | |
| - String expectedPath = "pom-with-profiles" + separator + "pom.xml"; | |
| - | |
| - // The test will pass with File.separator but this shows the platform differences | |
| - assertTrue( | |
| - actualLocation.contains("pom-with-profiles/pom.xml"), | |
| - "Location should contain path with proper separators for " + fsName + " (actual: " + actualLocation | |
| - + ")\n" | |
| - + "=== Cross-Platform Path Test [" + fsName + "] ===\n" | |
| - + "Expected path pattern: " + expectedPath + "\n" | |
| - + "Actual location: " + actualLocation + "\n" | |
| - + "Contains expected pattern: " + actualLocation.contains(expectedPath) + "\n" | |
| - + "File.separator on this system: '" + File.separator + "'"); | |
| - } | |
| + ProjectBuildingRequest request = newBuildingRequest(); | |
| + request.setLocalRepository(getLocalRepository()); | |
| + | |
| + MavenProject project = projectBuilder.build(testPom, request).getProject(); | |
| + | |
| + assertTrue(project.getInjectedProfileIds().keySet().containsAll(List.of("external", project.getId()))); | |
| + assertTrue(project.getInjectedProfileIds().get("external").isEmpty()); | |
| + assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().noneMatch("profile1"::equals)); | |
| + assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().noneMatch("profile2"::equals)); | |
| + assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().anyMatch("active-by-default"::equals)); | |
| + | |
| + InternalMavenSession session = Mockito.mock(InternalMavenSession.class); | |
| + List<org.apache.maven.api.model.Profile> activeProfiles = | |
| + new DefaultProject(session, project).getDeclaredActiveProfiles(); | |
| + assertEquals(1, activeProfiles.size()); | |
| + org.apache.maven.api.model.Profile profile = activeProfiles.get(0); | |
| + assertEquals("active-by-default", profile.getId()); | |
| + InputLocation location = profile.getLocation(""); | |
| + assertNotNull(location); | |
| + assertThat(location.getLineNumber(), greaterThan(0)); | |
| + assertThat(location.getColumnNumber(), greaterThan(0)); | |
| + assertNotNull(location.getSource()); | |
| + assertThat(location.getSource().getLocation(), containsString("pom-with-profiles/pom.xml")); | |
| } | |
| - /** | |
| - * Parameterized version of testActivatedExternalProfileBySource that demonstrates | |
| - * cross-platform path behavior using JIMFS to simulate both Windows and Unix file systems. | |
| - * This test shows how the path separator expectations differ between platforms. | |
| - */ | |
| - @ParameterizedTest(name = "testActivatedExternalProfileBySource[{0}]") | |
| - @MethodSource("fileSystemConfigurations") | |
| - void testActivatedExternalProfileBySource(String fsName, Configuration fsConfig, String separator) | |
| - throws Exception { | |
| + @Test | |
| + void testActivatedExternalProfileBySource() throws Exception { | |
| File testPom = getTestFile("src/test/resources/projects/pom-with-profiles/pom.xml"); | |
| - try (FileSystem fs = Jimfs.newFileSystem(fsName, fsConfig)) { | |
| - Path path = fs.getPath("projects", "pom-with-profiles", "pom.xml"); | |
| - Files.createDirectories(path.getParent()); | |
| - Files.copy(testPom.toPath(), path); | |
| - ModelSource source = Sources.buildSource(path); | |
| - | |
| - ProjectBuildingRequest request = newBuildingRequest(); | |
| - request.setLocalRepository(getLocalRepository()); | |
| - | |
| - final Profile externalProfile = new Profile(); | |
| - externalProfile.setLocation( | |
| - "", | |
| - new org.apache.maven.model.InputLocation( | |
| - 1, 1, new org.apache.maven.model.InputSource(InputSource.of(null, "settings.xml", null)))); | |
| - externalProfile.setId("external-profile"); | |
| - request.addProfile(externalProfile); | |
| - request.setActiveProfileIds(List.of(externalProfile.getId())); | |
| - | |
| - MavenProject project = projectBuilder.build(source, request).getProject(); | |
| - | |
| - assertTrue(project.getInjectedProfileIds().keySet().containsAll(List.of("external", project.getId()))); | |
| - assertTrue(project.getInjectedProfileIds().get("external").stream().anyMatch("external-profile"::equals)); | |
| - assertTrue(project.getInjectedProfileIds().get(project.getId()).stream() | |
| - .noneMatch("profile1"::equals)); | |
| - assertTrue(project.getInjectedProfileIds().get(project.getId()).stream() | |
| - .noneMatch("profile2"::equals)); | |
| - assertTrue(project.getInjectedProfileIds().get(project.getId()).stream() | |
| - .anyMatch("active-by-default"::equals)); | |
| - | |
| - InternalMavenSession session = Mockito.mock(InternalMavenSession.class); | |
| - List<org.apache.maven.api.model.Profile> activeProfiles = | |
| - new DefaultProject(session, project).getDeclaredActiveProfiles(); | |
| - assertEquals(2, activeProfiles.size()); | |
| - org.apache.maven.api.model.Profile profile = activeProfiles.get(0); | |
| - assertEquals("active-by-default", profile.getId()); | |
| - InputLocation location = profile.getLocation(""); | |
| - assertNotNull(location, "Profile location should not be null for profile: " + profile.getId()); | |
| - assertTrue( | |
| - location.getLineNumber() > 0, | |
| - "Profile location line number should be positive, but was: " + location.getLineNumber() | |
| - + " for profile: " + profile.getId()); | |
| - assertTrue( | |
| - location.getColumnNumber() > 0, | |
| - "Profile location column number should be positive, but was: " + location.getColumnNumber() | |
| - + " for profile: " + profile.getId()); | |
| - assertNotNull( | |
| - location.getSource(), "Profile location source should not be null for profile: " + profile.getId()); | |
| - assertTrue( | |
| - location.getSource().getLocation().contains("pom-with-profiles/pom.xml"), | |
| - "Profile location should contain 'pom-with-profiles/pom.xml', but was: " | |
| - + location.getSource().getLocation() + " for profile: " + profile.getId()); | |
| - | |
| - // This demonstrates the cross-platform path behavior for the POM file | |
| - String actualLocation = location.getSource().getLocation(); | |
| - String expectedPath = "pom-with-profiles" + separator + "pom.xml"; | |
| - | |
| - // The test will pass with File.separator but this shows the platform differences | |
| - assertTrue( | |
| - actualLocation.contains("pom-with-profiles/pom.xml"), | |
| - "Location should contain path with proper separators for " + fsName + " (actual: " + actualLocation | |
| - + ")\n" | |
| - + "=== Cross-Platform Path Test [" + fsName + "] - External Profile ===\n" | |
| - + "Expected path pattern: " + expectedPath + "\n" | |
| - + "Actual location: " + actualLocation + "\n" | |
| - + "Contains expected pattern: " + actualLocation.contains(expectedPath) + "\n" | |
| - + "File.separator on this system: '" + File.separator + "'"); | |
| - | |
| - profile = activeProfiles.get(1); | |
| - assertEquals("external-profile", profile.getId()); | |
| - location = profile.getLocation(""); | |
| - assertNotNull(location, "External profile location should not be null for profile: " + profile.getId()); | |
| - assertTrue( | |
| - location.getLineNumber() > 0, | |
| - "External profile location line number should be positive, but was: " + location.getLineNumber() | |
| - + " for profile: " + profile.getId()); | |
| - assertTrue( | |
| - location.getColumnNumber() > 0, | |
| - "External profile location column number should be positive, but was: " + location.getColumnNumber() | |
| - + " for profile: " + profile.getId()); | |
| - assertNotNull( | |
| - location.getSource(), | |
| - "External profile location source should not be null for profile: " + profile.getId()); | |
| - assertTrue( | |
| - location.getSource().getLocation().contains("settings.xml"), | |
| - "External profile location should contain 'settings.xml', but was: " | |
| - + location.getSource().getLocation() + " for profile: " + profile.getId()); | |
| - } | |
| + ProjectBuildingRequest request = newBuildingRequest(); | |
| + request.setLocalRepository(getLocalRepository()); | |
| + | |
| + final Profile externalProfile = new Profile(); | |
| + externalProfile.setLocation( | |
| + "", | |
| + new org.apache.maven.model.InputLocation( | |
| + 1, 1, new org.apache.maven.model.InputSource(new InputSource(null, "settings.xml", null)))); | |
| + externalProfile.setId("external-profile"); | |
| + request.addProfile(externalProfile); | |
| + request.setActiveProfileIds(List.of(externalProfile.getId())); | |
| + | |
| + MavenProject project = projectBuilder.build(testPom, request).getProject(); | |
| + | |
| + assertTrue(project.getInjectedProfileIds().keySet().containsAll(List.of("external", project.getId()))); | |
| + assertTrue(project.getInjectedProfileIds().get("external").stream().anyMatch("external-profile"::equals)); | |
| + assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().noneMatch("profile1"::equals)); | |
| + assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().noneMatch("profile2"::equals)); | |
| + assertTrue(project.getInjectedProfileIds().get(project.getId()).stream().anyMatch("active-by-default"::equals)); | |
| + | |
| + InternalMavenSession session = Mockito.mock(InternalMavenSession.class); | |
| + List<org.apache.maven.api.model.Profile> activeProfiles = | |
| + new DefaultProject(session, project).getDeclaredActiveProfiles(); | |
| + assertEquals(2, activeProfiles.size()); | |
| + org.apache.maven.api.model.Profile profile = activeProfiles.get(0); | |
| + assertEquals("active-by-default", profile.getId()); | |
| + InputLocation location = profile.getLocation(""); | |
| + assertNotNull(location); | |
| + assertThat(location.getLineNumber(), greaterThan(0)); | |
| + assertThat(location.getColumnNumber(), greaterThan(0)); | |
| + assertNotNull(location.getSource()); | |
| + assertThat(location.getSource().getLocation(), containsString("pom-with-profiles/pom.xml")); | |
| + profile = activeProfiles.get(1); | |
| + assertEquals("external-profile", profile.getId()); | |
| + location = profile.getLocation(""); | |
| + assertNotNull(location); | |
| + assertThat(location.getLineNumber(), greaterThan(0)); | |
| + assertThat(location.getColumnNumber(), greaterThan(0)); | |
| + assertNotNull(location.getSource()); | |
| + assertThat(location.getSource().getLocation(), containsString("settings.xml")); | |
| } | |
| @Test | |
| @@ -664,44 +545,4 @@ public void testSubprojectDiscovery() throws Exception { | |
| MavenProject parent = p1.getArtifactId().equals("parent") ? p1 : p2; | |
| assertEquals(List.of("child"), parent.getModel().getDelegate().getSubprojects()); | |
| } | |
| - | |
| - @Test | |
| - public void testEmptySubprojectsElementPreventsDiscovery() throws Exception { | |
| - File pom = getTestFile("src/test/resources/projects/subprojects-empty/pom.xml"); | |
| - ProjectBuildingRequest configuration = newBuildingRequest(); | |
| - InternalSession internalSession = InternalSession.from(configuration.getRepositorySession()); | |
| - InternalMavenSession mavenSession = InternalMavenSession.from(internalSession); | |
| - mavenSession | |
| - .getMavenSession() | |
| - .getRequest() | |
| - .setRootDirectory(pom.toPath().getParent()); | |
| - | |
| - List<ProjectBuildingResult> results = projectBuilder.build(List.of(pom), true, configuration); | |
| - // Should only build the parent project, not discover the child | |
| - assertEquals(1, results.size()); | |
| - MavenProject parent = results.get(0).getProject(); | |
| - assertEquals("parent", parent.getArtifactId()); | |
| - // The subprojects list should be empty since we explicitly defined an empty <subprojects /> element | |
| - assertTrue(parent.getModel().getDelegate().getSubprojects().isEmpty()); | |
| - } | |
| - | |
| - @Test | |
| - public void testEmptyModulesElementPreventsDiscovery() throws Exception { | |
| - File pom = getTestFile("src/test/resources/projects/modules-empty/pom.xml"); | |
| - ProjectBuildingRequest configuration = newBuildingRequest(); | |
| - InternalSession internalSession = InternalSession.from(configuration.getRepositorySession()); | |
| - InternalMavenSession mavenSession = InternalMavenSession.from(internalSession); | |
| - mavenSession | |
| - .getMavenSession() | |
| - .getRequest() | |
| - .setRootDirectory(pom.toPath().getParent()); | |
| - | |
| - List<ProjectBuildingResult> results = projectBuilder.build(List.of(pom), true, configuration); | |
| - // Should only build the parent project, not discover the child | |
| - assertEquals(1, results.size()); | |
| - MavenProject parent = results.get(0).getProject(); | |
| - assertEquals("parent", parent.getArtifactId()); | |
| - // The modules list should be empty since we explicitly defined an empty <modules /> element | |
| - assertTrue(parent.getModel().getDelegate().getModules().isEmpty()); | |
| - } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/ExtensionDescriptorBuilderTest.java b/impl/maven-core/src/test/java/org/apache/maven/project/ExtensionDescriptorBuilderTest.java | |
| index 4232e08c23..5e73daa279 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/project/ExtensionDescriptorBuilderTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/project/ExtensionDescriptorBuilderTest.java | |
| @@ -27,9 +27,11 @@ | |
| import org.junit.jupiter.api.BeforeEach; | |
| import org.junit.jupiter.api.Test; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.empty; | |
| +import static org.hamcrest.Matchers.is; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| /** | |
| * Tests {@link ExtensionDescriptorBuilder}. | |
| @@ -61,9 +63,9 @@ void testEmptyDescriptor() throws Exception { | |
| assertNotNull(ed); | |
| assertNotNull(ed.getExportedPackages()); | |
| - assertTrue(ed.getExportedPackages().isEmpty()); | |
| + assertThat(ed.getExportedPackages(), is(empty())); | |
| assertNotNull(ed.getExportedArtifacts()); | |
| - assertTrue(ed.getExportedArtifacts().isEmpty()); | |
| + assertThat(ed.getExportedArtifacts(), is(empty())); | |
| } | |
| @Test | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/GraphTest.java b/impl/maven-core/src/test/java/org/apache/maven/project/GraphTest.java | |
| index d96551e449..ef2b83278d 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/project/GraphTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/project/GraphTest.java | |
| @@ -78,10 +78,10 @@ public void testGraph() throws CycleDetectedException { | |
| Set<String> labels = graph.getVertices().stream().map(Vertex::getLabel).collect(Collectors.toSet()); | |
| assertEquals(4, labels.size()); | |
| - assertTrue(labels.contains("a"), "Expected " + labels + " to contain " + "a"); | |
| - assertTrue(labels.contains("b"), "Expected " + labels + " to contain " + "b"); | |
| - assertTrue(labels.contains("c"), "Expected " + labels + " to contain " + "c"); | |
| - assertTrue(labels.contains("d"), "Expected " + labels + " to contain " + "d"); | |
| + assertTrue(labels.contains("a")); | |
| + assertTrue(labels.contains("b")); | |
| + assertTrue(labels.contains("c")); | |
| + assertTrue(labels.contains("d")); | |
| addEdge(graph, "a", "d"); | |
| assertEquals(2, a.getChildren().size()); | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/MavenProjectTest.java b/impl/maven-core/src/test/java/org/apache/maven/project/MavenProjectTest.java | |
| index 67af48b502..402fd3014f 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/project/MavenProjectTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/project/MavenProjectTest.java | |
| @@ -213,6 +213,6 @@ void testAddDotFile() { | |
| } | |
| private void assertNoNulls(List<String> elements) { | |
| - assertFalse(elements.contains(null), "Expected " + elements + " to not contain " + null); | |
| + assertFalse(elements.contains(null)); | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/PomConstructionTest.java b/impl/maven-core/src/test/java/org/apache/maven/project/PomConstructionTest.java | |
| index a6513e4091..d53b81cc4e 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/project/PomConstructionTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/project/PomConstructionTest.java | |
| @@ -51,6 +51,10 @@ | |
| import org.junit.jupiter.api.Test; | |
| import static org.codehaus.plexus.testing.PlexusExtension.getBasedir; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.endsWith; | |
| +import static org.hamcrest.Matchers.lessThan; | |
| +import static org.hamcrest.Matchers.startsWith; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| import static org.junit.jupiter.api.Assertions.assertFalse; | |
| import static org.junit.jupiter.api.Assertions.assertNotEquals; | |
| @@ -1029,17 +1033,13 @@ void testMergedFilterOrder() throws Exception { | |
| PomTestWrapper pom = buildPom("merged-filter-order/sub"); | |
| assertEquals(7, ((List<?>) pom.getValue("build/filters")).size()); | |
| - assertTrue( | |
| - pom.getValue("build/filters[1]").toString().endsWith("child-a.properties"), | |
| - "Expected " + pom.getValue("build/filters[1]") + " to end with child-a.properties"); | |
| - assertTrue( | |
| - pom.getValue("build/filters[2]").toString().endsWith("child-c.properties"), | |
| - "Expected " + pom.getValue("build/filters[2]") + " to end with child-c.properties"); | |
| - assertTrue(pom.getValue("build/filters[3]").toString().endsWith("child-b.properties")); | |
| - assertTrue(pom.getValue("build/filters[4]").toString().endsWith("child-d.properties")); | |
| - assertTrue(pom.getValue("build/filters[5]").toString().endsWith("parent-c.properties")); | |
| - assertTrue(pom.getValue("build/filters[6]").toString().endsWith("parent-b.properties")); | |
| - assertTrue(pom.getValue("build/filters[7]").toString().endsWith("parent-d.properties")); | |
| + assertThat(pom.getValue("build/filters[1]").toString(), endsWith("child-a.properties")); | |
| + assertThat(pom.getValue("build/filters[2]").toString(), endsWith("child-c.properties")); | |
| + assertThat(pom.getValue("build/filters[3]").toString(), endsWith("child-b.properties")); | |
| + assertThat(pom.getValue("build/filters[4]").toString(), endsWith("child-d.properties")); | |
| + assertThat(pom.getValue("build/filters[5]").toString(), endsWith("parent-c.properties")); | |
| + assertThat(pom.getValue("build/filters[6]").toString(), endsWith("parent-b.properties")); | |
| + assertThat(pom.getValue("build/filters[7]").toString(), endsWith("parent-d.properties")); | |
| } | |
| /** MNG-4027*/ | |
| @@ -1180,7 +1180,7 @@ void testInterpolationOfRfc3986BaseUri() throws Exception { | |
| PomTestWrapper pom = buildPom("baseuri-interpolation/pom.xml"); | |
| String prop1 = pom.getValue("properties/prop1").toString(); | |
| assertEquals(pom.getBasedir().toPath().toUri().toASCIIString(), prop1); | |
| - assertTrue(prop1.startsWith("file:///"), "Expected " + prop1 + " to start with " + "file:///"); | |
| + assertThat(prop1, startsWith("file:///")); | |
| } | |
| /* MNG-3811*/ | |
| @@ -1771,10 +1771,10 @@ void testPluginDeclarationsRetainPomOrderAfterInjectionOfDefaultPlugins() throws | |
| for (int i = 0; i < plugins.size(); i++) { | |
| Plugin plugin = plugins.get(i); | |
| if ("maven-resources-plugin".equals(plugin.getArtifactId())) { | |
| - assertTrue(resourcesPlugin < 0, "Expected " + resourcesPlugin + " to be < " + 0); | |
| + assertThat(resourcesPlugin, lessThan(0)); | |
| resourcesPlugin = i; | |
| } else if ("maven-it-plugin-log-file".equals(plugin.getArtifactId())) { | |
| - assertTrue(customPlugin < 0, "Expected " + customPlugin + " to be < " + 0); | |
| + assertThat(customPlugin, lessThan(0)); | |
| customPlugin = i; | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuilderTest.java b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuilderTest.java | |
| index 69b1aef227..541ac8063c 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuilderTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuilderTest.java | |
| @@ -39,6 +39,15 @@ | |
| import org.junit.jupiter.api.Test; | |
| import org.junit.jupiter.api.io.TempDir; | |
| +import static org.apache.maven.project.ProjectBuildingResultWithLocationMatcher.projectBuildingResultWithLocation; | |
| +import static org.apache.maven.project.ProjectBuildingResultWithProblemMessageMatcher.projectBuildingResultWithProblemMessage; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.contains; | |
| +import static org.hamcrest.Matchers.containsString; | |
| +import static org.hamcrest.Matchers.empty; | |
| +import static org.hamcrest.Matchers.greaterThan; | |
| +import static org.hamcrest.Matchers.hasKey; | |
| +import static org.hamcrest.Matchers.is; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| import static org.junit.jupiter.api.Assertions.assertThrows; | |
| @@ -89,12 +98,12 @@ void testVersionlessManagedDependency() throws Exception { | |
| ProjectBuildingException e = assertThrows(ProjectBuildingException.class, () -> getContainer() | |
| .lookup(org.apache.maven.project.ProjectBuilder.class) | |
| .build(pomFile, configuration)); | |
| - assertEquals(1, e.getResults().size()); | |
| - ProjectBuildingResultWithProblemMessageAssert.assertThat(e.getResults().get(0)) | |
| - .hasProblemMessage( | |
| - "'dependencies.dependency.version' for groupId='org.apache.maven.its', artifactId='a', type='jar' is missing"); | |
| - ProjectBuildingResultWithLocationAssert.assertThat(e.getResults().get(0)) | |
| - .hasLocation(5, 9); | |
| + assertThat( | |
| + e.getResults(), | |
| + contains( | |
| + projectBuildingResultWithProblemMessage( | |
| + "'dependencies.dependency.version' for groupId='org.apache.maven.its', artifactId='a', type='jar' is missing"))); | |
| + assertThat(e.getResults(), contains(projectBuildingResultWithLocation(5, 9))); | |
| } | |
| @Test | |
| @@ -178,7 +187,7 @@ void testReadModifiedPoms(@TempDir Path tempDir) throws Exception { | |
| Files.write(parent.toPath(), parentContent.getBytes(StandardCharsets.UTF_8)); | |
| // re-build pom with modified parent | |
| ProjectBuildingResult result = projectBuilder.build(child, configuration); | |
| - assertTrue(result.getProject().getProperties().containsKey("addedProperty")); | |
| + assertThat(result.getProject().getProperties(), hasKey((Object) "addedProperty")); | |
| } | |
| @Test | |
| @@ -226,7 +235,7 @@ void testReadInvalidPom() throws Exception { | |
| // single project build entry point | |
| Exception ex = assertThrows(Exception.class, () -> projectBuilder.build(pomFile, configuration)); | |
| - assertTrue(ex.getMessage().contains("Received non-all-whitespace CHARACTERS or CDATA event")); | |
| + assertThat(ex.getMessage(), containsString("Received non-all-whitespace CHARACTERS or CDATA event")); | |
| // multi projects build entry point | |
| ProjectBuildingException pex = assertThrows( | |
| @@ -234,10 +243,11 @@ void testReadInvalidPom() throws Exception { | |
| () -> projectBuilder.build(Collections.singletonList(pomFile), false, configuration)); | |
| assertEquals(1, pex.getResults().size()); | |
| assertNotNull(pex.getResults().get(0).getPomFile()); | |
| - assertTrue(pex.getResults().get(0).getProblems().size() > 0); | |
| - ProjectBuildingResultWithProblemMessageAssert.assertThat( | |
| - pex.getResults().get(0)) | |
| - .hasProblemMessage("Received non-all-whitespace CHARACTERS or CDATA event in nextTag()"); | |
| + assertThat(pex.getResults().get(0).getProblems().size(), greaterThan(0)); | |
| + assertThat( | |
| + pex.getResults(), | |
| + contains(projectBuildingResultWithProblemMessage( | |
| + "Received non-all-whitespace CHARACTERS or CDATA event in nextTag()"))); | |
| } | |
| @Test | |
| @@ -288,7 +298,7 @@ private MavenProject findChildProject(List<ProjectBuildingResult> results) { | |
| private void assertResultShowNoError(List<ProjectBuildingResult> results) { | |
| for (ProjectBuildingResult result : results) { | |
| - assertTrue(result.getProblems().isEmpty()); | |
| + assertThat(result.getProblems(), is(empty())); | |
| assertNotNull(result.getProject()); | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingExceptionTest.java b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingExceptionTest.java | |
| deleted file mode 100644 | |
| index fae4355e0e..0000000000 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingExceptionTest.java | |
| +++ /dev/null | |
| @@ -1,163 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.project; | |
| - | |
| -import java.io.File; | |
| -import java.util.ArrayList; | |
| -import java.util.Collections; | |
| -import java.util.List; | |
| - | |
| -import org.apache.maven.model.building.DefaultModelProblem; | |
| -import org.apache.maven.model.building.ModelProblem; | |
| -import org.junit.jupiter.api.Test; | |
| - | |
| -import static org.junit.jupiter.api.Assertions.assertEquals; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| - | |
| -/** | |
| - * Test for {@link ProjectBuildingException} message generation. | |
| - */ | |
| -@SuppressWarnings("deprecation") | |
| -class ProjectBuildingExceptionTest { | |
| - | |
| - @Test | |
| - void testDetailedExceptionMessageWithMultipleProblems() { | |
| - List<ProjectBuildingResult> results = new ArrayList<>(); | |
| - | |
| - List<ModelProblem> problems1 = new ArrayList<>(); | |
| - Collections.addAll( | |
| - problems1, | |
| - new DefaultModelProblem( | |
| - "Missing required dependency", | |
| - ModelProblem.Severity.ERROR, | |
| - null, | |
| - "pom.xml", | |
| - 25, | |
| - 10, | |
| - null, | |
| - null), | |
| - new DefaultModelProblem( | |
| - "Invalid version format", ModelProblem.Severity.ERROR, null, "pom.xml", 30, 5, null, null)); | |
| - DefaultProjectBuildingResult result1 = | |
| - new DefaultProjectBuildingResult("com.example:project1:1.0", new File("project1/pom.xml"), problems1); | |
| - results.add(result1); | |
| - | |
| - List<ModelProblem> problems2 = new ArrayList<>(); | |
| - Collections.addAll( | |
| - problems2, | |
| - new DefaultModelProblem( | |
| - "Deprecated plugin usage", ModelProblem.Severity.WARNING, null, "pom.xml", 15, 3, null, null)); | |
| - DefaultProjectBuildingResult result2 = | |
| - new DefaultProjectBuildingResult("com.example:project2:1.0", new File("project2/pom.xml"), problems2); | |
| - results.add(result2); | |
| - | |
| - ProjectBuildingException exception = new ProjectBuildingException(results); | |
| - String message = exception.getMessage(); | |
| - | |
| - assertTrue( | |
| - message.contains("3 problems were encountered while processing the POMs (2 errors)"), | |
| - "Message should contain problem count and error count"); | |
| - | |
| - assertTrue(message.contains("[com.example:project1:1.0]"), "Message should contain project1 identifier"); | |
| - | |
| - assertTrue(message.contains("[com.example:project2:1.0]"), "Message should contain project2 identifier"); | |
| - | |
| - assertTrue( | |
| - message.contains("[ERROR] Missing required dependency @ pom.xml, line 25, column 10"), | |
| - "Message should contain error details with location"); | |
| - | |
| - assertTrue( | |
| - message.contains("[ERROR] Invalid version format @ pom.xml, line 30, column 5"), | |
| - "Message should contain second error details"); | |
| - | |
| - assertTrue( | |
| - !message.contains("[WARNING]") || message.contains("[WARNING] Deprecated plugin usage"), | |
| - "Warnings should be filtered when errors are present or shown if explicitly included"); | |
| - } | |
| - | |
| - @Test | |
| - void testExceptionMessageWithOnlyWarnings() { | |
| - List<ProjectBuildingResult> results = new ArrayList<>(); | |
| - | |
| - List<ModelProblem> problems = new ArrayList<>(); | |
| - Collections.addAll( | |
| - problems, | |
| - new DefaultModelProblem( | |
| - "Deprecated feature used", ModelProblem.Severity.WARNING, null, "pom.xml", 10, 1, null, null)); | |
| - DefaultProjectBuildingResult result = | |
| - new DefaultProjectBuildingResult("com.example:project:1.0", new File("project/pom.xml"), problems); | |
| - results.add(result); | |
| - | |
| - ProjectBuildingException exception = new ProjectBuildingException(results); | |
| - String message = exception.getMessage(); | |
| - | |
| - assertTrue( | |
| - message.contains("1 problem was encountered while processing the POMs"), | |
| - "Message should use singular form for single problem"); | |
| - | |
| - assertTrue( | |
| - message.contains("[WARNING] Deprecated feature used"), | |
| - "Message should contain warning when no errors are present"); | |
| - | |
| - assertTrue( | |
| - !message.contains("(") || !message.contains("error"), | |
| - "Message should not contain error count when there are no errors"); | |
| - } | |
| - | |
| - @Test | |
| - void testExceptionMessageWithEmptyResults() { | |
| - List<ProjectBuildingResult> results = Collections.emptyList(); | |
| - | |
| - ProjectBuildingException exception = new ProjectBuildingException(results); | |
| - String message = exception.getMessage(); | |
| - | |
| - assertEquals( | |
| - "Some problems were encountered while processing the POMs", | |
| - message, | |
| - "Empty results should fall back to generic message"); | |
| - } | |
| - | |
| - @Test | |
| - void testExceptionMessageWithNullResults() { | |
| - ProjectBuildingException exception = new ProjectBuildingException((List<ProjectBuildingResult>) null); | |
| - String message = exception.getMessage(); | |
| - | |
| - assertEquals( | |
| - "Some problems were encountered while processing the POMs", | |
| - message, | |
| - "Null results should fall back to generic message"); | |
| - } | |
| - | |
| - @Test | |
| - void testExceptionMessageWithUnknownProject() { | |
| - List<ProjectBuildingResult> results = new ArrayList<>(); | |
| - | |
| - List<ModelProblem> problems = new ArrayList<>(); | |
| - Collections.addAll( | |
| - problems, | |
| - new DefaultModelProblem("Some error", ModelProblem.Severity.ERROR, null, "unknown", 1, 1, null, null)); | |
| - DefaultProjectBuildingResult result = new DefaultProjectBuildingResult(null, null, problems); | |
| - results.add(result); | |
| - | |
| - ProjectBuildingException exception = new ProjectBuildingException(results); | |
| - String message = exception.getMessage(); | |
| - | |
| - assertTrue(message.contains("[unknown project]"), "Message should handle unknown project gracefully"); | |
| - } | |
| -} | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingResultWithLocationAssert.java b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingResultWithLocationAssert.java | |
| deleted file mode 100644 | |
| index 3e15ce14ad..0000000000 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingResultWithLocationAssert.java | |
| +++ /dev/null | |
| @@ -1,66 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.project; | |
| - | |
| -import static java.util.stream.Collectors.joining; | |
| -import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| - | |
| -/** | |
| - * JUnit custom assertion to help create fluent assertions about {@link ProjectBuildingResult} instances. | |
| - */ | |
| -class ProjectBuildingResultWithLocationAssert { | |
| - private final ProjectBuildingResult actual; | |
| - | |
| - ProjectBuildingResultWithLocationAssert(ProjectBuildingResult actual) { | |
| - this.actual = actual; | |
| - } | |
| - | |
| - public static ProjectBuildingResultWithLocationAssert assertThat(ProjectBuildingResult actual) { | |
| - return new ProjectBuildingResultWithLocationAssert(actual); | |
| - } | |
| - | |
| - public ProjectBuildingResultWithLocationAssert hasLocation(int columnNumber, int lineNumber) { | |
| - assertNotNull(actual); | |
| - | |
| - boolean hasLocation = actual.getProblems().stream() | |
| - .anyMatch(p -> p.getLineNumber() == lineNumber && p.getColumnNumber() == columnNumber); | |
| - | |
| - if (!hasLocation) { | |
| - String actualLocations = actual.getProblems().stream() | |
| - .map(p -> formatLocation(p.getColumnNumber(), p.getLineNumber())) | |
| - .collect(joining(", ")); | |
| - String message = String.format( | |
| - "Expected ProjectBuildingResult to have location <%s> but had locations <%s>", | |
| - formatLocation(columnNumber, lineNumber), actualLocations); | |
| - assertTrue(false, message); | |
| - } | |
| - | |
| - return this; | |
| - } | |
| - | |
| - private String formatLocation(int columnNumber, int lineNumber) { | |
| - return String.format("line %d, column %d", lineNumber, columnNumber); | |
| - } | |
| - | |
| - // Helper method for backward compatibility | |
| - static ProjectBuildingResultWithLocationAssert projectBuildingResultWithLocation(int columnNumber, int lineNumber) { | |
| - return new ProjectBuildingResultWithLocationAssert(null).hasLocation(columnNumber, lineNumber); | |
| - } | |
| -} | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingResultWithLocationMatcher.java b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingResultWithLocationMatcher.java | |
| new file mode 100644 | |
| index 0000000000..ac46ca37e5 | |
| --- /dev/null | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingResultWithLocationMatcher.java | |
| @@ -0,0 +1,76 @@ | |
| +/* | |
| + * Licensed to the Apache Software Foundation (ASF) under one | |
| + * or more contributor license agreements. See the NOTICE file | |
| + * distributed with this work for additional information | |
| + * regarding copyright ownership. The ASF licenses this file | |
| + * to you under the Apache License, Version 2.0 (the | |
| + * "License"); you may not use this file except in compliance | |
| + * with the License. You may obtain a copy of the License at | |
| + * | |
| + * http://www.apache.org/licenses/LICENSE-2.0 | |
| + * | |
| + * Unless required by applicable law or agreed to in writing, | |
| + * software distributed under the License is distributed on an | |
| + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| + * KIND, either express or implied. See the License for the | |
| + * specific language governing permissions and limitations | |
| + * under the License. | |
| + */ | |
| +package org.apache.maven.project; | |
| + | |
| +import org.hamcrest.BaseMatcher; | |
| +import org.hamcrest.Description; | |
| +import org.hamcrest.Matcher; | |
| + | |
| +import static java.util.stream.Collectors.joining; | |
| + | |
| +/** | |
| + * Hamcrest matcher to help create fluent assertions about {@link ProjectBuildingResult} instances. | |
| + */ | |
| +class ProjectBuildingResultWithLocationMatcher extends BaseMatcher<ProjectBuildingResult> { | |
| + private final int columnNumber; | |
| + private final int lineNumber; | |
| + | |
| + ProjectBuildingResultWithLocationMatcher(int columnNumber, int lineNumber) { | |
| + this.columnNumber = columnNumber; | |
| + this.lineNumber = lineNumber; | |
| + } | |
| + | |
| + @Override | |
| + public boolean matches(Object o) { | |
| + if (o instanceof ProjectBuildingResult r) { | |
| + return r.getProblems().stream() | |
| + .anyMatch(p -> p.getLineNumber() == lineNumber && p.getColumnNumber() == columnNumber); | |
| + } else { | |
| + return false; | |
| + } | |
| + } | |
| + | |
| + @Override | |
| + public void describeTo(Description description) { | |
| + description | |
| + .appendText("a ProjectBuildingResult with location ") | |
| + .appendText(formatLocation(columnNumber, lineNumber)); | |
| + } | |
| + | |
| + private String formatLocation(int columnNumber, int lineNumber) { | |
| + return String.format("line %d, column %d", lineNumber, columnNumber); | |
| + } | |
| + | |
| + @Override | |
| + public void describeMismatch(final Object o, final Description description) { | |
| + if (o instanceof ProjectBuildingResult r) { | |
| + description.appendText("was a ProjectBuildingResult with locations "); | |
| + String messages = r.getProblems().stream() | |
| + .map(p -> formatLocation(p.getColumnNumber(), p.getLineNumber())) | |
| + .collect(joining(", ")); | |
| + description.appendText(messages); | |
| + } else { | |
| + super.describeMismatch(o, description); | |
| + } | |
| + } | |
| + | |
| + static Matcher<ProjectBuildingResult> projectBuildingResultWithLocation(int columnNumber, int lineNumber) { | |
| + return new ProjectBuildingResultWithLocationMatcher(columnNumber, lineNumber); | |
| + } | |
| +} | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingResultWithProblemMessageAssert.java b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingResultWithProblemMessageAssert.java | |
| deleted file mode 100644 | |
| index ed7a4c9558..0000000000 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingResultWithProblemMessageAssert.java | |
| +++ /dev/null | |
| @@ -1,65 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.project; | |
| - | |
| -import org.apache.maven.model.building.ModelProblem; | |
| - | |
| -import static java.util.stream.Collectors.joining; | |
| -import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| - | |
| -/** | |
| - * JUnit custom assertion to help create fluent assertions about {@link ProjectBuildingResult} instances. | |
| - */ | |
| -class ProjectBuildingResultWithProblemMessageAssert { | |
| - private final ProjectBuildingResult actual; | |
| - | |
| - ProjectBuildingResultWithProblemMessageAssert(ProjectBuildingResult actual) { | |
| - this.actual = actual; | |
| - } | |
| - | |
| - public static ProjectBuildingResultWithProblemMessageAssert assertThat(ProjectBuildingResult actual) { | |
| - return new ProjectBuildingResultWithProblemMessageAssert(actual); | |
| - } | |
| - | |
| - public ProjectBuildingResultWithProblemMessageAssert hasProblemMessage(String problemMessage) { | |
| - assertNotNull(actual); | |
| - | |
| - boolean hasMessage = | |
| - actual.getProblems().stream().anyMatch(p -> p.getMessage().contains(problemMessage)); | |
| - | |
| - if (!hasMessage) { | |
| - String actualMessages = actual.getProblems().stream() | |
| - .map(ModelProblem::getMessage) | |
| - .map(m -> "\"" + m + "\"") | |
| - .collect(joining(", ")); | |
| - String message = String.format( | |
| - "Expected ProjectBuildingResult to have problem message containing <%s> but had messages <%s>", | |
| - problemMessage, actualMessages); | |
| - assertTrue(false, message); | |
| - } | |
| - | |
| - return this; | |
| - } | |
| - | |
| - // Helper method for backward compatibility | |
| - static ProjectBuildingResultWithProblemMessageAssert projectBuildingResultWithProblemMessage(String message) { | |
| - return new ProjectBuildingResultWithProblemMessageAssert(null).hasProblemMessage(message); | |
| - } | |
| -} | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingResultWithProblemMessageMatcher.java b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingResultWithProblemMessageMatcher.java | |
| new file mode 100644 | |
| index 0000000000..a180175c2a | |
| --- /dev/null | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingResultWithProblemMessageMatcher.java | |
| @@ -0,0 +1,69 @@ | |
| +/* | |
| + * Licensed to the Apache Software Foundation (ASF) under one | |
| + * or more contributor license agreements. See the NOTICE file | |
| + * distributed with this work for additional information | |
| + * regarding copyright ownership. The ASF licenses this file | |
| + * to you under the Apache License, Version 2.0 (the | |
| + * "License"); you may not use this file except in compliance | |
| + * with the License. You may obtain a copy of the License at | |
| + * | |
| + * http://www.apache.org/licenses/LICENSE-2.0 | |
| + * | |
| + * Unless required by applicable law or agreed to in writing, | |
| + * software distributed under the License is distributed on an | |
| + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| + * KIND, either express or implied. See the License for the | |
| + * specific language governing permissions and limitations | |
| + * under the License. | |
| + */ | |
| +package org.apache.maven.project; | |
| + | |
| +import org.apache.maven.model.building.ModelProblem; | |
| +import org.hamcrest.BaseMatcher; | |
| +import org.hamcrest.Description; | |
| +import org.hamcrest.Matcher; | |
| + | |
| +import static java.util.stream.Collectors.joining; | |
| + | |
| +/** | |
| + * Hamcrest matcher to help create fluent assertions about {@link ProjectBuildingResult} instances. | |
| + */ | |
| +class ProjectBuildingResultWithProblemMessageMatcher extends BaseMatcher<ProjectBuildingResult> { | |
| + private final String problemMessage; | |
| + | |
| + ProjectBuildingResultWithProblemMessageMatcher(String problemMessage) { | |
| + this.problemMessage = problemMessage; | |
| + } | |
| + | |
| + @Override | |
| + public boolean matches(Object o) { | |
| + if (o instanceof ProjectBuildingResult r) { | |
| + return r.getProblems().stream().anyMatch(p -> p.getMessage().contains(problemMessage)); | |
| + } else { | |
| + return false; | |
| + } | |
| + } | |
| + | |
| + @Override | |
| + public void describeTo(Description description) { | |
| + description.appendText("a ProjectBuildingResult with message ").appendValue(problemMessage); | |
| + } | |
| + | |
| + @Override | |
| + public void describeMismatch(final Object o, final Description description) { | |
| + if (o instanceof ProjectBuildingResult r) { | |
| + description.appendText("was a ProjectBuildingResult with messages "); | |
| + String messages = r.getProblems().stream() | |
| + .map(ModelProblem::getMessage) | |
| + .map(m -> "\"" + m + "\"" + System.lineSeparator()) | |
| + .collect(joining(", ")); | |
| + description.appendText(messages); | |
| + } else { | |
| + super.describeMismatch(o, description); | |
| + } | |
| + } | |
| + | |
| + static Matcher<ProjectBuildingResult> projectBuildingResultWithProblemMessage(String message) { | |
| + return new ProjectBuildingResultWithProblemMessageMatcher(message); | |
| + } | |
| +} | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java | |
| index 684ac70ef8..522fc58e03 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java | |
| @@ -35,10 +35,11 @@ | |
| import org.junit.jupiter.api.Test; | |
| import static org.codehaus.plexus.testing.PlexusExtension.getBasedir; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.containsString; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| import static org.junit.jupiter.api.Assertions.assertThrows; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| /** | |
| * Test cases for the project {@code ModelResolver} implementation. | |
| @@ -66,7 +67,7 @@ void testResolveParentThrowsUnresolvableModelExceptionWhenNotFound() throws Exce | |
| () -> newModelResolver().resolveModel(parent), | |
| "Expected 'UnresolvableModelException' not thrown."); | |
| assertNotNull(e.getMessage()); | |
| - assertTrue(e.getMessage().contains("Could not find artifact org.apache:apache:pom:0 in central")); | |
| + assertThat(e.getMessage(), containsString("Could not find artifact org.apache:apache:pom:0 in central")); | |
| } | |
| @Test | |
| @@ -131,7 +132,7 @@ void testResolveDependencyThrowsUnresolvableModelExceptionWhenNotFound() throws | |
| () -> newModelResolver().resolveModel(dependency), | |
| "Expected 'UnresolvableModelException' not thrown."); | |
| assertNotNull(e.getMessage()); | |
| - assertTrue(e.getMessage().contains("Could not find artifact org.apache:apache:pom:0 in central")); | |
| + assertThat(e.getMessage(), containsString("Could not find artifact org.apache:apache:pom:0 in central")); | |
| } | |
| @Test | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectSorterTest.java b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectSorterTest.java | |
| index 209f3e44f9..ada0b514b4 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/project/ProjectSorterTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/project/ProjectSorterTest.java | |
| @@ -31,9 +31,10 @@ | |
| import org.apache.maven.model.PluginManagement; | |
| import org.junit.jupiter.api.Test; | |
| +import static org.hamcrest.MatcherAssert.assertThat; | |
| +import static org.hamcrest.Matchers.hasItem; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| import static org.junit.jupiter.api.Assertions.assertThrows; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| /** | |
| * Test sorting projects by dependencies. | |
| @@ -238,10 +239,8 @@ void testPluginDependenciesInfluenceSorting() throws Exception { | |
| assertEquals(parentProject, projects.get(0)); | |
| // the order of these two is non-deterministic, based on when they're added to the reactor. | |
| - assertTrue(projects.contains(pluginProject), "Expected " + projects + " to contain " + pluginProject); | |
| - assertTrue( | |
| - projects.contains(pluginLevelDepProject), | |
| - "Expected " + projects + " to contain " + pluginLevelDepProject); | |
| + assertThat(projects, hasItem(pluginProject)); | |
| + assertThat(projects, hasItem(pluginLevelDepProject)); | |
| // the declaring project MUST be listed after the plugin and its plugin-level dep, though. | |
| assertEquals(declaringProject, projects.get(3)); | |
| @@ -277,10 +276,8 @@ void testPluginDependenciesInfluenceSortingDeclarationInParent() throws Exceptio | |
| assertEquals(parentProject, projects.get(0)); | |
| // the order of these two is non-deterministic, based on when they're added to the reactor. | |
| - assertTrue(projects.contains(pluginProject), "Expected " + projects + " to contain " + pluginProject); | |
| - assertTrue( | |
| - projects.contains(pluginLevelDepProject), | |
| - "Expected " + projects + " to contain " + pluginLevelDepProject); | |
| + assertThat(projects, hasItem(pluginProject)); | |
| + assertThat(projects, hasItem(pluginLevelDepProject)); | |
| } | |
| @Test | |
| @@ -297,8 +294,8 @@ void testPluginVersionsAreConsidered() throws Exception { | |
| projects = new ProjectSorter(projects).getSortedProjects(); | |
| - assertTrue(projects.contains(pluginProjectA), "Expected " + projects + " to contain " + pluginProjectA); | |
| - assertTrue(projects.contains(pluginProjectB), "Expected " + projects + " to contain " + pluginProjectB); | |
| + assertThat(projects, hasItem(pluginProjectA)); | |
| + assertThat(projects, hasItem(pluginProjectB)); | |
| } | |
| @Test | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/project/RepositoryLeakageTest.java b/impl/maven-core/src/test/java/org/apache/maven/project/RepositoryLeakageTest.java | |
| deleted file mode 100644 | |
| index b5ff18f872..0000000000 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/project/RepositoryLeakageTest.java | |
| +++ /dev/null | |
| @@ -1,214 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.project; | |
| - | |
| -import java.io.File; | |
| -import java.nio.file.Files; | |
| -import java.nio.file.Path; | |
| -import java.util.List; | |
| - | |
| -import org.apache.maven.artifact.repository.ArtifactRepository; | |
| -import org.codehaus.plexus.testing.PlexusTest; | |
| -import org.junit.jupiter.api.Test; | |
| - | |
| -import static org.junit.jupiter.api.Assertions.assertFalse; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| -import static org.junit.jupiter.api.Assertions.fail; | |
| - | |
| -/** | |
| - * Test to verify that repositories from one project don't leak to sibling projects. | |
| - */ | |
| -@PlexusTest | |
| -public class RepositoryLeakageTest extends AbstractMavenProjectTestCase { | |
| - | |
| - @Test | |
| - @SuppressWarnings("checkstyle:MethodLength") | |
| - public void testRepositoryLeakageBetweenSiblings() throws Exception { | |
| - // Create a temporary directory structure for our test | |
| - Path tempDir = Files.createTempDirectory("maven-repo-leakage-test"); | |
| - | |
| - try { | |
| - // Create parent POM | |
| - Path parentPom = tempDir.resolve("pom.xml"); | |
| - Files.writeString( | |
| - parentPom, | |
| - """ | |
| - <?xml version="1.0" encoding="UTF-8"?> | |
| - <project xmlns="http://maven.apache.org/POM/4.0.0" | |
| - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 | |
| - http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
| - <modelVersion>4.0.0</modelVersion> | |
| - <groupId>test</groupId> | |
| - <artifactId>parent</artifactId> | |
| - <version>1.0</version> | |
| - <packaging>pom</packaging> | |
| - | |
| - <modules> | |
| - <module>child1</module> | |
| - <module>child2</module> | |
| - </modules> | |
| - </project> | |
| - """); | |
| - | |
| - // Create child1 with specific repository | |
| - Path child1Dir = tempDir.resolve("child1"); | |
| - Files.createDirectories(child1Dir); | |
| - Path child1Pom = child1Dir.resolve("pom.xml"); | |
| - Files.writeString( | |
| - child1Pom, | |
| - """ | |
| - <?xml version="1.0" encoding="UTF-8"?> | |
| - <project xmlns="http://maven.apache.org/POM/4.0.0" | |
| - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 | |
| - http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
| - <modelVersion>4.0.0</modelVersion> | |
| - <parent> | |
| - <groupId>test</groupId> | |
| - <artifactId>parent</artifactId> | |
| - <version>1.0</version> | |
| - </parent> | |
| - <artifactId>child1</artifactId> | |
| - | |
| - <repositories> | |
| - <repository> | |
| - <id>child1-repo</id> | |
| - <url>https://child1.example.com/repo</url> | |
| - </repository> | |
| - </repositories> | |
| - </project> | |
| - """); | |
| - | |
| - // Create child2 with different repository | |
| - Path child2Dir = tempDir.resolve("child2"); | |
| - Files.createDirectories(child2Dir); | |
| - Path child2Pom = child2Dir.resolve("pom.xml"); | |
| - Files.writeString( | |
| - child2Pom, | |
| - """ | |
| - <?xml version="1.0" encoding="UTF-8"?> | |
| - <project xmlns="http://maven.apache.org/POM/4.0.0" | |
| - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 | |
| - http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
| - <modelVersion>4.0.0</modelVersion> | |
| - <parent> | |
| - <groupId>test</groupId> | |
| - <artifactId>parent</artifactId> | |
| - <version>1.0</version> | |
| - </parent> | |
| - <artifactId>child2</artifactId> | |
| - | |
| - <repositories> | |
| - <repository> | |
| - <id>child2-repo</id> | |
| - <url>https://child2.example.com/repo</url> | |
| - </repository> | |
| - </repositories> | |
| - </project> | |
| - """); | |
| - | |
| - // Create a shared ProjectBuildingRequest | |
| - ProjectBuildingRequest sharedRequest = newBuildingRequest(); | |
| - | |
| - // Build child1 first | |
| - ProjectBuildingResult result1 = projectBuilder.build(child1Pom.toFile(), sharedRequest); | |
| - MavenProject child1Project = result1.getProject(); | |
| - | |
| - // Capture repositories after building child1 | |
| - | |
| - // Build child2 using the same shared request | |
| - ProjectBuildingResult result2 = projectBuilder.build(child2Pom.toFile(), sharedRequest); | |
| - MavenProject child2Project = result2.getProject(); | |
| - | |
| - // Capture repositories after building child2 | |
| - List<ArtifactRepository> repositoriesAfterChild2 = List.copyOf(sharedRequest.getRemoteRepositories()); | |
| - | |
| - // Verify that child1 has its own repository | |
| - boolean child1HasOwnRepo = child1Project.getRemoteArtifactRepositories().stream() | |
| - .anyMatch(repo -> "child1-repo".equals(repo.getId())); | |
| - assertTrue(child1HasOwnRepo, "Child1 should have its own repository"); | |
| - | |
| - // Verify that child2 has its own repository | |
| - boolean child2HasOwnRepo = child2Project.getRemoteArtifactRepositories().stream() | |
| - .anyMatch(repo -> "child2-repo".equals(repo.getId())); | |
| - assertTrue(child2HasOwnRepo, "Child2 should have its own repository"); | |
| - | |
| - // Print debug information | |
| - System.out.println("=== REPOSITORY LEAKAGE TEST RESULTS ==="); | |
| - System.out.println( | |
| - "Repositories in shared request after building child2: " + repositoriesAfterChild2.size()); | |
| - repositoriesAfterChild2.forEach( | |
| - repo -> System.out.println(" - " + repo.getId() + " (" + repo.getUrl() + ")")); | |
| - | |
| - System.out.println("Child1 project repositories:"); | |
| - child1Project | |
| - .getRemoteArtifactRepositories() | |
| - .forEach(repo -> System.out.println(" - " + repo.getId() + " (" + repo.getUrl() + ")")); | |
| - | |
| - System.out.println("Child2 project repositories:"); | |
| - child2Project | |
| - .getRemoteArtifactRepositories() | |
| - .forEach(repo -> System.out.println(" - " + repo.getId() + " (" + repo.getUrl() + ")")); | |
| - System.out.println("======================================="); | |
| - | |
| - // Check for leakage: child2 should NOT have child1's repository | |
| - boolean child2HasChild1Repo = child2Project.getRemoteArtifactRepositories().stream() | |
| - .anyMatch(repo -> "child1-repo".equals(repo.getId())); | |
| - assertFalse(child2HasChild1Repo, "Child2 should NOT have child1's repository (leakage detected!)"); | |
| - | |
| - // Check for leakage in the shared request | |
| - boolean sharedRequestHasChild1Repo = | |
| - repositoriesAfterChild2.stream().anyMatch(repo -> "child1-repo".equals(repo.getId())); | |
| - boolean sharedRequestHasChild2Repo = | |
| - repositoriesAfterChild2.stream().anyMatch(repo -> "child2-repo".equals(repo.getId())); | |
| - | |
| - // Print debug information | |
| - /* | |
| - System.out.println("Repositories after child1: " + repositoriesAfterChild1.size()); | |
| - repositoriesAfterChild1.forEach(repo -> System.out.println(" - " + repo.getId() + ": " + repo.getUrl())); | |
| - | |
| - System.out.println("Repositories after child2: " + repositoriesAfterChild2.size()); | |
| - repositoriesAfterChild2.forEach(repo -> System.out.println(" - " + repo.getId() + ": " + repo.getUrl())); | |
| - */ | |
| - | |
| - // The shared request should not accumulate repositories from both children | |
| - if (sharedRequestHasChild1Repo && sharedRequestHasChild2Repo) { | |
| - fail("REPOSITORY LEAKAGE DETECTED: Shared request contains repositories from both children!"); | |
| - } | |
| - | |
| - } finally { | |
| - // Clean up | |
| - deleteRecursively(tempDir.toFile()); | |
| - } | |
| - } | |
| - | |
| - private void deleteRecursively(File file) { | |
| - if (file.isDirectory()) { | |
| - File[] children = file.listFiles(); | |
| - if (children != null) { | |
| - for (File child : children) { | |
| - deleteRecursively(child); | |
| - } | |
| - } | |
| - } | |
| - file.delete(); | |
| - } | |
| -} | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/rtinfo/internal/DefaultRuntimeInformationTest.java b/impl/maven-core/src/test/java/org/apache/maven/rtinfo/internal/DefaultRuntimeInformationTest.java | |
| index 1c474c69ed..e04b13aca0 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/rtinfo/internal/DefaultRuntimeInformationTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/rtinfo/internal/DefaultRuntimeInformationTest.java | |
| @@ -38,7 +38,7 @@ class DefaultRuntimeInformationTest { | |
| void testGetMavenVersion() { | |
| String mavenVersion = rtInfo.getMavenVersion(); | |
| assertNotNull(mavenVersion); | |
| - assertTrue(!mavenVersion.isEmpty(), "Expected Maven version to not be empty but was: " + mavenVersion); | |
| + assertTrue(!mavenVersion.isEmpty()); | |
| } | |
| @Test | |
| diff --git a/impl/maven-core/src/test/java/org/apache/maven/settings/PomConstructionWithSettingsTest.java b/impl/maven-core/src/test/java/org/apache/maven/settings/PomConstructionWithSettingsTest.java | |
| index c7dc9998a9..ae1ee942cf 100644 | |
| --- a/impl/maven-core/src/test/java/org/apache/maven/settings/PomConstructionWithSettingsTest.java | |
| +++ b/impl/maven-core/src/test/java/org/apache/maven/settings/PomConstructionWithSettingsTest.java | |
| @@ -131,7 +131,7 @@ private PomTestWrapper buildPom(String pomPath) throws Exception { | |
| private static Settings readSettingsFile(File settingsFile) throws IOException, XMLStreamException { | |
| try (InputStream is = Files.newInputStream(settingsFile.toPath())) { | |
| SettingsStaxReader reader = new SettingsStaxReader(); | |
| - InputSource source = InputSource.of(settingsFile.toString()); | |
| + InputSource source = new InputSource(settingsFile.toString()); | |
| return new Settings(reader.read(is, true, source)); | |
| } | |
| } | |
| diff --git a/impl/maven-core/src/test/projects/plugin-manager/project-with-plugin-classpath-ordering/sub/settings-template.xml b/impl/maven-core/src/test/projects/plugin-manager/project-with-plugin-classpath-ordering/sub/settings-template.xml | |
| index ddfed199ae..cde4215860 100644 | |
| --- a/impl/maven-core/src/test/projects/plugin-manager/project-with-plugin-classpath-ordering/sub/settings-template.xml | |
| +++ b/impl/maven-core/src/test/projects/plugin-manager/project-with-plugin-classpath-ordering/sub/settings-template.xml | |
| @@ -19,7 +19,7 @@ specific language governing permissions and limitations | |
| under the License. | |
| --> | |
| -<settings xmlns='http://maven.apache.org/SETTINGS/1.0.0'> | |
| +<settings> | |
| <profiles> | |
| <profile> | |
| <id>maven-core-it-repo</id> | |
| diff --git a/impl/maven-core/src/test/resources-settings/repositories/settings.xml b/impl/maven-core/src/test/resources-settings/repositories/settings.xml | |
| index a8eff40516..6f96f0b6f8 100644 | |
| --- a/impl/maven-core/src/test/resources-settings/repositories/settings.xml | |
| +++ b/impl/maven-core/src/test/resources-settings/repositories/settings.xml | |
| @@ -19,7 +19,7 @@ specific language governing permissions and limitations | |
| under the License. | |
| --> | |
| -<settings xmlns='http://maven.apache.org/SETTINGS/1.0.0'> | |
| +<settings> | |
| <profiles> | |
| <profile> | |
| <id>maven-core-it-repo</id> | |
| diff --git a/impl/maven-core/src/test/resources-settings/test-pom-and-settings-interpolation/settings.xml b/impl/maven-core/src/test/resources-settings/test-pom-and-settings-interpolation/settings.xml | |
| index 536c6be0bb..2d42d495c5 100644 | |
| --- a/impl/maven-core/src/test/resources-settings/test-pom-and-settings-interpolation/settings.xml | |
| +++ b/impl/maven-core/src/test/resources-settings/test-pom-and-settings-interpolation/settings.xml | |
| @@ -19,7 +19,7 @@ specific language governing permissions and limitations | |
| under the License. | |
| --> | |
| -<settings xmlns='http://maven.apache.org/SETTINGS/1.0.0'> | |
| +<settings> | |
| <profiles> | |
| <profile> | |
| <id>settings</id> | |
| diff --git a/impl/maven-core/src/test/resources/projects/modules-empty/child/pom.xml b/impl/maven-core/src/test/resources/projects/modules-empty/child/pom.xml | |
| deleted file mode 100644 | |
| index 022d865352..0000000000 | |
| --- a/impl/maven-core/src/test/resources/projects/modules-empty/child/pom.xml | |
| +++ /dev/null | |
| @@ -1,8 +0,0 @@ | |
| -<project xmlns="http://maven.apache.org/POM/4.1.0"> | |
| - <parent> | |
| - <groupId>modules-empty</groupId> | |
| - <artifactId>parent</artifactId> | |
| - </parent> | |
| - <artifactId>child</artifactId> | |
| - <packaging>jar</packaging> | |
| -</project> | |
| diff --git a/impl/maven-core/src/test/resources/projects/modules-empty/pom.xml b/impl/maven-core/src/test/resources/projects/modules-empty/pom.xml | |
| deleted file mode 100644 | |
| index b36128e6a5..0000000000 | |
| --- a/impl/maven-core/src/test/resources/projects/modules-empty/pom.xml | |
| +++ /dev/null | |
| @@ -1,7 +0,0 @@ | |
| -<project xmlns="http://maven.apache.org/POM/4.1.0"> | |
| - <groupId>modules-empty</groupId> | |
| - <artifactId>parent</artifactId> | |
| - <version>1</version> | |
| - <packaging>pom</packaging> | |
| - <modules /> | |
| -</project> | |
| diff --git a/impl/maven-core/src/test/resources/projects/subprojects-empty/child/pom.xml b/impl/maven-core/src/test/resources/projects/subprojects-empty/child/pom.xml | |
| deleted file mode 100644 | |
| index 1c4f2b7709..0000000000 | |
| --- a/impl/maven-core/src/test/resources/projects/subprojects-empty/child/pom.xml | |
| +++ /dev/null | |
| @@ -1,8 +0,0 @@ | |
| -<project xmlns="http://maven.apache.org/POM/4.1.0"> | |
| - <parent> | |
| - <groupId>subprojects-empty</groupId> | |
| - <artifactId>parent</artifactId> | |
| - </parent> | |
| - <artifactId>child</artifactId> | |
| - <packaging>jar</packaging> | |
| -</project> | |
| diff --git a/impl/maven-core/src/test/resources/projects/subprojects-empty/pom.xml b/impl/maven-core/src/test/resources/projects/subprojects-empty/pom.xml | |
| deleted file mode 100644 | |
| index 840c572d1d..0000000000 | |
| --- a/impl/maven-core/src/test/resources/projects/subprojects-empty/pom.xml | |
| +++ /dev/null | |
| @@ -1,7 +0,0 @@ | |
| -<project xmlns="http://maven.apache.org/POM/4.1.0"> | |
| - <groupId>subprojects-empty</groupId> | |
| - <artifactId>parent</artifactId> | |
| - <version>1</version> | |
| - <packaging>pom</packaging> | |
| - <subprojects /> | |
| -</project> | |
| diff --git a/impl/maven-di/pom.xml b/impl/maven-di/pom.xml | |
| index 4068da194b..5a6d5c3773 100644 | |
| --- a/impl/maven-di/pom.xml | |
| +++ b/impl/maven-di/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-impl-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-di</artifactId> | |
| @@ -45,6 +45,11 @@ under the License. | |
| <artifactId>junit-jupiter-api</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| + <dependency> | |
| + <groupId>org.assertj</groupId> | |
| + <artifactId>assertj-core</artifactId> | |
| + <scope>test</scope> | |
| + </dependency> | |
| </dependencies> | |
| </project> | |
| diff --git a/impl/maven-di/src/main/java/org/apache/maven/di/Injector.java b/impl/maven-di/src/main/java/org/apache/maven/di/Injector.java | |
| index 270ea6947c..8a95f0fd6f 100644 | |
| --- a/impl/maven-di/src/main/java/org/apache/maven/di/Injector.java | |
| +++ b/impl/maven-di/src/main/java/org/apache/maven/di/Injector.java | |
| @@ -123,21 +123,6 @@ static Injector create() { | |
| @Nonnull | |
| <T> Injector bindInstance(@Nonnull Class<T> cls, @Nonnull T instance); | |
| - /** | |
| - * Binds a specific instance supplier to a class type. | |
| - * <p> | |
| - * This method allows pre-created instances to be used for injection instead of | |
| - * having the injector create new instances. | |
| - * | |
| - * @param <T> the type of the instance | |
| - * @param cls the class to bind to | |
| - * @param supplier the supplier to use for injection | |
| - * @return this injector instance for method chaining | |
| - * @throws NullPointerException if either parameter is null | |
| - */ | |
| - @Nonnull | |
| - <T> Injector bindSupplier(@Nonnull Class<T> cls, @Nonnull Supplier<T> supplier); | |
| - | |
| /** | |
| * Performs field and method injection on an existing instance. | |
| * <p> | |
| @@ -176,16 +161,4 @@ static Injector create() { | |
| */ | |
| @Nonnull | |
| <T> T getInstance(@Nonnull Key<T> key); | |
| - | |
| - /** | |
| - * Disposes this Injector, clearing all internal state (bindings, caches, scopes, etc.). | |
| - * After calling this, the Injector should not be used again. | |
| - * @since 4.1 | |
| - */ | |
| - default void dispose() { | |
| - // delegate to the implementation | |
| - if (this instanceof InjectorImpl) { | |
| - ((InjectorImpl) this).dispose(); | |
| - } | |
| - } | |
| } | |
| diff --git a/impl/maven-di/src/main/java/org/apache/maven/di/impl/Binding.java b/impl/maven-di/src/main/java/org/apache/maven/di/impl/Binding.java | |
| index 4caa7311b8..a5da997d75 100644 | |
| --- a/impl/maven-di/src/main/java/org/apache/maven/di/impl/Binding.java | |
| +++ b/impl/maven-di/src/main/java/org/apache/maven/di/impl/Binding.java | |
| @@ -53,10 +53,6 @@ public static <T> Binding<T> toInstance(T instance) { | |
| return new BindingToInstance<>(instance); | |
| } | |
| - public static <T> Binding<T> toSupplier(Supplier<T> supplier) { | |
| - return new BindingToSupplier<>(supplier); | |
| - } | |
| - | |
| public static <R> Binding<R> to(Key<R> originalKey, TupleConstructorN<R> constructor, Class<?>[] types) { | |
| return Binding.to( | |
| originalKey, | |
| @@ -172,25 +168,6 @@ public String toString() { | |
| } | |
| } | |
| - public static class BindingToSupplier<T> extends Binding<T> { | |
| - final Supplier<T> supplier; | |
| - | |
| - public BindingToSupplier(Supplier<T> supplier) { | |
| - super(null, Collections.emptySet()); | |
| - this.supplier = supplier; | |
| - } | |
| - | |
| - @Override | |
| - public Supplier<T> compile(Function<Dependency<?>, Supplier<?>> compiler) { | |
| - return supplier; | |
| - } | |
| - | |
| - @Override | |
| - public String toString() { | |
| - return "BindingToSupplier[" + supplier + "]" + getDependencies(); | |
| - } | |
| - } | |
| - | |
| public static class BindingToConstructor<T> extends Binding<T> { | |
| final TupleConstructorN<T> constructor; | |
| final Dependency<?>[] args; | |
| diff --git a/impl/maven-di/src/main/java/org/apache/maven/di/impl/InjectorImpl.java b/impl/maven-di/src/main/java/org/apache/maven/di/impl/InjectorImpl.java | |
| index b0672ff56f..c3a069bca5 100644 | |
| --- a/impl/maven-di/src/main/java/org/apache/maven/di/impl/InjectorImpl.java | |
| +++ b/impl/maven-di/src/main/java/org/apache/maven/di/impl/InjectorImpl.java | |
| @@ -137,13 +137,6 @@ public <U> Injector bindInstance(@Nonnull Class<U> clazz, @Nonnull U instance) { | |
| return doBind(key, binding); | |
| } | |
| - @Override | |
| - public <U> Injector bindSupplier(@Nonnull Class<U> clazz, @Nonnull Supplier<U> supplier) { | |
| - Key<?> key = Key.of(clazz, ReflectionUtils.qualifierOf(clazz)); | |
| - Binding<U> binding = Binding.toSupplier(supplier); | |
| - return doBind(key, binding); | |
| - } | |
| - | |
| @Nonnull | |
| @Override | |
| public Injector bindImplicit(@Nonnull Class<?> clazz) { | |
| @@ -202,10 +195,6 @@ public Map<Key<?>, Set<Binding<?>>> getBindings() { | |
| return bindings; | |
| } | |
| - public <T> Set<Binding<T>> getAllBindings(Class<T> clazz) { | |
| - return getBindings(Key.of(clazz)); | |
| - } | |
| - | |
| public <Q> Supplier<Q> getCompiledBinding(Dependency<Q> dep) { | |
| Key<Q> key = dep.key(); | |
| Supplier<Q> originalSupplier = doGetCompiledBinding(dep); | |
| @@ -279,8 +268,8 @@ protected <Q> Supplier<Q> compile(Binding<Q> binding) { | |
| if (binding.getScope() != null) { | |
| Scope scope = scopes.entrySet().stream() | |
| .filter(e -> e.getKey().isInstance(binding.getScope())) | |
| - .findFirst() | |
| .map(Map.Entry::getValue) | |
| + .findFirst() | |
| .orElseThrow(() -> new DIException("Scope not bound for annotation " | |
| + binding.getScope().annotationType())) | |
| .get(); | |
| @@ -467,24 +456,4 @@ public T get() { | |
| }); | |
| } | |
| } | |
| - | |
| - /** | |
| - * Release all internal state so this Injector can be GC’d | |
| - * (and so that subsequent tests start from a clean slate). | |
| - * @since 4.1 | |
| - */ | |
| - public void dispose() { | |
| - // First, clear any singleton‐scope caches | |
| - scopes.values().stream() | |
| - .map(Supplier::get) | |
| - .filter(scope -> scope instanceof SingletonScope) | |
| - .map(scope -> (SingletonScope) scope) | |
| - .forEach(singleton -> singleton.cache.clear()); | |
| - | |
| - // Now clear everything else | |
| - bindings.clear(); | |
| - scopes.clear(); | |
| - loadedUrls.clear(); | |
| - resolutionStack.remove(); | |
| - } | |
| } | |
| diff --git a/impl/maven-di/src/test/java/org/apache/maven/di/impl/InjectorImplTest.java b/impl/maven-di/src/test/java/org/apache/maven/di/impl/InjectorImplTest.java | |
| index 46ea1b3318..f02eb011d9 100644 | |
| --- a/impl/maven-di/src/test/java/org/apache/maven/di/impl/InjectorImplTest.java | |
| +++ b/impl/maven-di/src/test/java/org/apache/maven/di/impl/InjectorImplTest.java | |
| @@ -38,6 +38,7 @@ | |
| import org.junit.jupiter.api.Test; | |
| import static java.lang.annotation.RetentionPolicy.RUNTIME; | |
| +import static org.assertj.core.api.Assertions.assertThat; | |
| import static org.junit.jupiter.api.Assertions.assertEquals; | |
| import static org.junit.jupiter.api.Assertions.assertInstanceOf; | |
| import static org.junit.jupiter.api.Assertions.assertNotEquals; | |
| @@ -45,7 +46,6 @@ | |
| import static org.junit.jupiter.api.Assertions.assertNotSame; | |
| import static org.junit.jupiter.api.Assertions.assertNull; | |
| import static org.junit.jupiter.api.Assertions.assertThrows; | |
| -import static org.junit.jupiter.api.Assertions.assertTrue; | |
| @SuppressWarnings("unused") | |
| public class InjectorImplTest { | |
| @@ -416,20 +416,11 @@ void testCircularPriorityDependency() { | |
| DIException exception = assertThrows(DIException.class, () -> { | |
| injector.getInstance(CircularPriorityTest.MyService.class); | |
| }); | |
| - assertInstanceOf(DIException.class, exception, "Expected exception to be DIException"); | |
| - assertTrue( | |
| - exception.getMessage().contains("HighPriorityServiceImpl"), | |
| - "Expected exception message to contain 'HighPriorityServiceImpl' but was: " + exception.getMessage()); | |
| - | |
| - assertInstanceOf(DIException.class, exception.getCause(), "Expected cause to be DIException"); | |
| - assertTrue( | |
| - exception.getCause().getMessage().contains("Cyclic dependency detected"), | |
| - "Expected cause message to contain 'Cyclic dependency detected' but was: " | |
| - + exception.getCause().getMessage()); | |
| - assertTrue( | |
| - exception.getCause().getMessage().contains("MyService"), | |
| - "Expected cause message to contain 'MyService' but was: " | |
| - + exception.getCause().getMessage()); | |
| + assertThat(exception).isInstanceOf(DIException.class).hasMessageContaining("HighPriorityServiceImpl"); | |
| + assertThat(exception.getCause()) | |
| + .isInstanceOf(DIException.class) | |
| + .hasMessageContaining("Cyclic dependency detected") | |
| + .hasMessageContaining("MyService"); | |
| } | |
| @Test | |
| @@ -484,34 +475,4 @@ static class MediumPriorityServiceImpl implements MyService {} | |
| @Named | |
| static class DefaultPriorityServiceImpl implements MyService {} | |
| } | |
| - | |
| - @Test | |
| - void testDisposeClearsBindingsAndCache() { | |
| - final Injector injector = Injector.create() | |
| - // bind two simple beans | |
| - .bindImplicit(DisposeTest.Foo.class) | |
| - .bindImplicit(DisposeTest.Bar.class); | |
| - | |
| - // make sure they really get created | |
| - assertNotNull(injector.getInstance(DisposeTest.Foo.class)); | |
| - assertNotNull(injector.getInstance(DisposeTest.Bar.class)); | |
| - | |
| - // now dispose | |
| - injector.dispose(); | |
| - | |
| - // after dispose, bindings should be gone => DIException on lookup | |
| - assertThrows(DIException.class, () -> injector.getInstance(DisposeTest.Foo.class)); | |
| - assertThrows(DIException.class, () -> injector.getInstance(DisposeTest.Bar.class)); | |
| - } | |
| - | |
| - /** | |
| - * Simple test classes for dispose(). | |
| - */ | |
| - static class DisposeTest { | |
| - @Named | |
| - static class Foo {} | |
| - | |
| - @Named | |
| - static class Bar {} | |
| - } | |
| } | |
| diff --git a/impl/maven-executor/pom.xml b/impl/maven-executor/pom.xml | |
| index 093adffc95..650271b74c 100644 | |
| --- a/impl/maven-executor/pom.xml | |
| +++ b/impl/maven-executor/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-impl-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-executor</artifactId> | |
| @@ -53,11 +53,6 @@ under the License. | |
| <artifactId>junit-jupiter-params</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| - <dependency> | |
| - <groupId>eu.maveniverse.maven.mimir</groupId> | |
| - <artifactId>testing</artifactId> | |
| - <scope>test</scope> | |
| - </dependency> | |
| <dependency> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>apache-maven</artifactId> | |
| @@ -75,6 +70,12 @@ under the License. | |
| </dependencies> | |
| <build> | |
| + <testResources> | |
| + <testResource> | |
| + <filtering>true</filtering> | |
| + <directory>src/test/resources-filtered</directory> | |
| + </testResource> | |
| + </testResources> | |
| <plugins> | |
| <plugin> | |
| <groupId>org.apache.maven.plugins</groupId> | |
| diff --git a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MavenExecutorTestSupport.java b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MavenExecutorTestSupport.java | |
| index afa33b904a..79bace4a9f 100644 | |
| --- a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MavenExecutorTestSupport.java | |
| +++ b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MavenExecutorTestSupport.java | |
| @@ -26,7 +26,6 @@ | |
| import java.util.Collection; | |
| import java.util.List; | |
| -import eu.maveniverse.maven.mimir.testing.MimirInfuser; | |
| import org.apache.maven.api.annotations.Nullable; | |
| import org.apache.maven.api.cli.Executor; | |
| import org.apache.maven.api.cli.ExecutorRequest; | |
| @@ -317,7 +316,7 @@ public static void main(String... args) { | |
| protected void execute(@Nullable Path logFile, Collection<ExecutorRequest> requests) throws Exception { | |
| Executor invoker = createAndMemoizeExecutor(); | |
| for (ExecutorRequest request : requests) { | |
| - MimirInfuser.infuseUW(request.userHomeDirectory()); | |
| + MimirInfuser.infuse(request.userHomeDirectory()); | |
| int exitCode = invoker.execute(request); | |
| if (exitCode != 0) { | |
| throw new FailedExecution(request, exitCode, logFile == null ? "" : Files.readString(logFile)); | |
| diff --git a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MimirInfuser.java b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MimirInfuser.java | |
| new file mode 100644 | |
| index 0000000000..4cf53bf0c2 | |
| --- /dev/null | |
| +++ b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/MimirInfuser.java | |
| @@ -0,0 +1,57 @@ | |
| +/* | |
| + * Licensed to the Apache Software Foundation (ASF) under one | |
| + * or more contributor license agreements. See the NOTICE file | |
| + * distributed with this work for additional information | |
| + * regarding copyright ownership. The ASF licenses this file | |
| + * to you under the Apache License, Version 2.0 (the | |
| + * "License"); you may not use this file except in compliance | |
| + * with the License. You may obtain a copy of the License at | |
| + * | |
| + * http://www.apache.org/licenses/LICENSE-2.0 | |
| + * | |
| + * Unless required by applicable law or agreed to in writing, | |
| + * software distributed under the License is distributed on an | |
| + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| + * KIND, either express or implied. See the License for the | |
| + * specific language governing permissions and limitations | |
| + * under the License. | |
| + */ | |
| +package org.apache.maven.cling.executor; | |
| + | |
| +import java.io.IOException; | |
| +import java.nio.file.Files; | |
| +import java.nio.file.Path; | |
| +import java.nio.file.StandardCopyOption; | |
| + | |
| +import static java.util.Objects.requireNonNull; | |
| + | |
| +/** | |
| + * Class that sets up Mimir for maven-executor tests IF outer build uses Mimir as well (CI setup). | |
| + */ | |
| +public final class MimirInfuser { | |
| + public static void infuse(Path userHome) throws IOException { | |
| + requireNonNull(userHome); | |
| + // GH CI copies this to place, or user may have it already | |
| + Path realUserWideExtensions = | |
| + Path.of(System.getProperty("user.home")).resolve(".m2").resolve("extensions.xml"); | |
| + if (Files.isRegularFile(realUserWideExtensions)) { | |
| + String realUserWideExtensionsString = Files.readString(realUserWideExtensions); | |
| + if (realUserWideExtensionsString.contains("<groupId>eu.maveniverse.maven.mimir</groupId>") | |
| + && realUserWideExtensionsString.contains("<artifactId>extension</artifactId>")) { | |
| + Path userWideExtensions = userHome.resolve(".m2").resolve("extensions.xml"); | |
| + // some tests do prepare project and user wide extensions; skip those for now | |
| + if (!Files.isRegularFile(userWideExtensions)) { | |
| + Files.createDirectories(userWideExtensions.getParent()); | |
| + Files.copy(realUserWideExtensions, userWideExtensions, StandardCopyOption.REPLACE_EXISTING); | |
| + | |
| + Path mimirProperties = userHome.resolve(".mimir").resolve("mimir.properties"); | |
| + Files.createDirectories(mimirProperties.getParent()); | |
| + Files.copy( | |
| + Path.of("target/test-classes/ut-mimir.properties"), | |
| + mimirProperties, | |
| + StandardCopyOption.REPLACE_EXISTING); | |
| + } | |
| + } | |
| + } | |
| + } | |
| +} | |
| diff --git a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/impl/ToolboxToolTest.java b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/impl/ToolboxToolTest.java | |
| index 14ca0c0f5b..7787f0ca4b 100644 | |
| --- a/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/impl/ToolboxToolTest.java | |
| +++ b/impl/maven-executor/src/test/java/org/apache/maven/cling/executor/impl/ToolboxToolTest.java | |
| @@ -24,10 +24,10 @@ | |
| import java.nio.file.Paths; | |
| import java.util.Map; | |
| -import eu.maveniverse.maven.mimir.testing.MimirInfuser; | |
| import org.apache.maven.api.cli.ExecutorRequest; | |
| import org.apache.maven.cling.executor.ExecutorHelper; | |
| import org.apache.maven.cling.executor.MavenExecutorTestSupport; | |
| +import org.apache.maven.cling.executor.MimirInfuser; | |
| import org.apache.maven.cling.executor.internal.HelperImpl; | |
| import org.apache.maven.cling.executor.internal.ToolboxTool; | |
| import org.junit.jupiter.api.BeforeAll; | |
| @@ -50,7 +50,7 @@ public class ToolboxToolTest { | |
| @BeforeAll | |
| static void beforeAll() throws Exception { | |
| - MimirInfuser.infuseUW(userHome); | |
| + MimirInfuser.infuse(userHome); | |
| } | |
| private ExecutorRequest.Builder getExecutorRequest(ExecutorHelper helper) { | |
| diff --git a/impl/maven-executor/src/test/resources-filtered/ut-mimir.properties b/impl/maven-executor/src/test/resources-filtered/ut-mimir.properties | |
| new file mode 100644 | |
| index 0000000000..74c68a3a18 | |
| --- /dev/null | |
| +++ b/impl/maven-executor/src/test/resources-filtered/ut-mimir.properties | |
| @@ -0,0 +1,8 @@ | |
| +# Used IF outer build uses Mimir (CI setup) | |
| + | |
| +# we change user.home in IT, so we want this interpolated | |
| +mimir.daemon.basedir=${user.home}/.mimir | |
| +# outer build already did this | |
| +mimir.daemon.autoupdate=false | |
| +# outer build already did this | |
| +mimir.daemon.autostart=false | |
| diff --git a/impl/maven-impl/pom.xml b/impl/maven-impl/pom.xml | |
| index ca1b5ddbe8..a9d4010a28 100644 | |
| --- a/impl/maven-impl/pom.xml | |
| +++ b/impl/maven-impl/pom.xml | |
| @@ -23,7 +23,7 @@ under the License. | |
| <parent> | |
| <groupId>org.apache.maven</groupId> | |
| <artifactId>maven-impl-modules</artifactId> | |
| - <version>4.1.0-SNAPSHOT</version> | |
| + <version>4.0.0-SNAPSHOT</version> | |
| </parent> | |
| <artifactId>maven-impl</artifactId> | |
| @@ -145,6 +145,16 @@ under the License. | |
| <artifactId>mockito-junit-jupiter</artifactId> | |
| <scope>test</scope> | |
| </dependency> | |
| + <dependency> | |
| + <groupId>org.hamcrest</groupId> | |
| + <artifactId>hamcrest</artifactId> | |
| + <scope>test</scope> | |
| + </dependency> | |
| + <dependency> | |
| + <groupId>org.assertj</groupId> | |
| + <artifactId>assertj-core</artifactId> | |
| + <scope>test</scope> | |
| + </dependency> | |
| <dependency> | |
| <groupId>org.apache.maven.resolver</groupId> | |
| <artifactId>maven-resolver-transport-file</artifactId> | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/api/services/model/ModelResolver.java b/impl/maven-impl/src/main/java/org/apache/maven/api/services/model/ModelResolver.java | |
| index 668f450bc7..0a7cbb621c 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/api/services/model/ModelResolver.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/api/services/model/ModelResolver.java | |
| @@ -85,16 +85,8 @@ record ModelResolverRequest( | |
| @Nonnull String groupId, | |
| @Nonnull String artifactId, | |
| @Nonnull String version, | |
| - @Nullable String classifier, | |
| - @Nullable String extension) | |
| + @Nullable String classifier) | |
| implements Request<Session> { | |
| - public ModelResolverRequest { | |
| - Objects.requireNonNull(session, "session cannot be null"); | |
| - Objects.requireNonNull(groupId, "groupId cannot be null"); | |
| - Objects.requireNonNull(artifactId, "artifactId cannot be null"); | |
| - Objects.requireNonNull(version, "version cannot be null"); | |
| - } | |
| - | |
| @Nonnull | |
| @Override | |
| public Session getSession() { | |
| @@ -114,13 +106,12 @@ public boolean equals(Object o) { | |
| && Objects.equals(groupId, that.groupId) | |
| && Objects.equals(artifactId, that.artifactId) | |
| && Objects.equals(version, that.version) | |
| - && Objects.equals(classifier, that.classifier) | |
| - && Objects.equals(extension, that.extension); | |
| + && Objects.equals(classifier, that.classifier); | |
| } | |
| @Override | |
| public int hashCode() { | |
| - return Objects.hash(repositories, groupId, artifactId, version, classifier, extension); | |
| + return Objects.hash(repositories, groupId, artifactId, version, classifier); | |
| } | |
| @Override | |
| @@ -132,7 +123,6 @@ public String toString() { | |
| + ", artifactId=" + artifactId | |
| + ", version=" + version | |
| + ", classifier=" + classifier | |
| - + ", extension=" + extension | |
| + ']'; | |
| } | |
| } | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/api/services/model/ModelValidator.java b/impl/maven-impl/src/main/java/org/apache/maven/api/services/model/ModelValidator.java | |
| index 116b918959..8d0e5cbdac 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/api/services/model/ModelValidator.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/api/services/model/ModelValidator.java | |
| @@ -49,18 +49,10 @@ public interface ModelValidator { | |
| * Denotes validation as performed by Maven 4.0. This validation level is meant for new projects. | |
| */ | |
| int VALIDATION_LEVEL_MAVEN_4_0 = 40; | |
| - /** | |
| - * Denotes validation as performed by Maven 4.1. This validation level is meant for new projects. | |
| - */ | |
| - int VALIDATION_LEVEL_MAVEN_4_1 = 41; | |
| - /** | |
| - * Denotes validation as performed by Maven 4.2. This validation level is meant for new projects. | |
| - */ | |
| - int VALIDATION_LEVEL_MAVEN_4_2 = 42; | |
| /** | |
| * Denotes strict validation as recommended by the current Maven version. | |
| */ | |
| - int VALIDATION_LEVEL_STRICT = VALIDATION_LEVEL_MAVEN_4_2; | |
| + int VALIDATION_LEVEL_STRICT = VALIDATION_LEVEL_MAVEN_4_0; | |
| /** | |
| * Checks the specified file model for missing or invalid values. This model is directly created from the POM | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/AbstractSession.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/AbstractSession.java | |
| index 7992df53b0..605a36b903 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/AbstractSession.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/AbstractSession.java | |
| @@ -23,19 +23,17 @@ | |
| import java.util.Arrays; | |
| import java.util.Collection; | |
| import java.util.Collections; | |
| -import java.util.HashMap; | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.NoSuchElementException; | |
| import java.util.Objects; | |
| import java.util.Optional; | |
| -import java.util.Set; | |
| +import java.util.WeakHashMap; | |
| import java.util.concurrent.ConcurrentHashMap; | |
| import java.util.concurrent.CopyOnWriteArrayList; | |
| import java.util.function.Function; | |
| import java.util.function.Supplier; | |
| import java.util.stream.Collectors; | |
| -import java.util.stream.Stream; | |
| import org.apache.maven.api.Artifact; | |
| import org.apache.maven.api.ArtifactCoordinates; | |
| @@ -98,11 +96,6 @@ | |
| import org.apache.maven.api.services.VersionRangeResolver; | |
| import org.apache.maven.api.services.VersionResolver; | |
| import org.apache.maven.api.services.VersionResolverException; | |
| -import org.apache.maven.di.Injector; | |
| -import org.apache.maven.di.Key; | |
| -import org.apache.maven.di.impl.Binding; | |
| -import org.apache.maven.di.impl.InjectorImpl; | |
| -import org.apache.maven.impl.cache.Cache; | |
| import org.eclipse.aether.DefaultRepositorySystemSession; | |
| import org.eclipse.aether.RepositorySystem; | |
| import org.eclipse.aether.RepositorySystemSession; | |
| @@ -119,17 +112,16 @@ public abstract class AbstractSession implements InternalSession { | |
| protected final RepositorySystem repositorySystem; | |
| protected final List<RemoteRepository> repositories; | |
| protected final Lookup lookup; | |
| - protected final Injector injector; | |
| private final Map<Class<? extends Service>, Service> services = new ConcurrentHashMap<>(); | |
| private final List<Listener> listeners = new CopyOnWriteArrayList<>(); | |
| - private final Cache<org.eclipse.aether.graph.DependencyNode, Node> allNodes = | |
| - Cache.newCache(Cache.ReferenceType.WEAK, "AbstractSession-Nodes"); | |
| - private final Map<Class<? extends Artifact>, Cache<org.eclipse.aether.artifact.Artifact, Artifact>> allArtifacts = | |
| + private final Map<org.eclipse.aether.graph.DependencyNode, Node> allNodes = | |
| + Collections.synchronizedMap(new WeakHashMap<>()); | |
| + private final Map<Class<? extends Artifact>, Map<org.eclipse.aether.artifact.Artifact, Artifact>> allArtifacts = | |
| new ConcurrentHashMap<>(); | |
| - private final Cache<org.eclipse.aether.repository.RemoteRepository, RemoteRepository> allRepositories = | |
| - Cache.newCache(Cache.ReferenceType.WEAK, "AbstractSession-Repositories"); | |
| - private final Cache<org.eclipse.aether.graph.Dependency, Dependency> allDependencies = | |
| - Cache.newCache(Cache.ReferenceType.WEAK, "AbstractSession-Dependencies"); | |
| + private final Map<org.eclipse.aether.repository.RemoteRepository, RemoteRepository> allRepositories = | |
| + Collections.synchronizedMap(new WeakHashMap<>()); | |
| + private final Map<org.eclipse.aether.graph.Dependency, Dependency> allDependencies = | |
| + Collections.synchronizedMap(new WeakHashMap<>()); | |
| private volatile RequestCache requestCache; | |
| static { | |
| @@ -146,24 +138,6 @@ public AbstractSession( | |
| this.repositorySystem = repositorySystem; | |
| this.repositories = getRepositories(repositories, resolverRepositories); | |
| this.lookup = lookup; | |
| - this.injector = lookup != null ? lookup.lookupOptional(Injector.class).orElse(null) : null; | |
| - } | |
| - | |
| - @SuppressWarnings("unchecked") | |
| - private static Stream<Class<? extends Service>> collectServiceInterfaces(Class<?> clazz) { | |
| - if (clazz == null) { | |
| - return Stream.empty(); | |
| - } else if (clazz.isInterface()) { | |
| - return Stream.concat( | |
| - Service.class.isAssignableFrom(clazz) ? Stream.of((Class<Service>) clazz) : Stream.empty(), | |
| - Stream.of(clazz.getInterfaces()).flatMap(AbstractSession::collectServiceInterfaces)) | |
| - .filter(itf -> itf != Service.class); | |
| - } else { | |
| - return Stream.concat( | |
| - Stream.of(clazz.getInterfaces()).flatMap(AbstractSession::collectServiceInterfaces), | |
| - collectServiceInterfaces(clazz.getSuperclass())) | |
| - .filter(itf -> itf != Service.class); | |
| - } | |
| } | |
| @Override | |
| @@ -251,8 +225,8 @@ public Artifact getArtifact(@Nonnull org.eclipse.aether.artifact.Artifact artifa | |
| @SuppressWarnings("unchecked") | |
| @Override | |
| public <T extends Artifact> T getArtifact(Class<T> clazz, org.eclipse.aether.artifact.Artifact artifact) { | |
| - Cache<org.eclipse.aether.artifact.Artifact, Artifact> map = allArtifacts.computeIfAbsent( | |
| - clazz, c -> Cache.newCache(Cache.ReferenceType.WEAK, "AbstractSession-Artifacts-" + c.getSimpleName())); | |
| + Map<org.eclipse.aether.artifact.Artifact, Artifact> map = | |
| + allArtifacts.computeIfAbsent(clazz, c -> Collections.synchronizedMap(new WeakHashMap<>())); | |
| if (clazz == Artifact.class) { | |
| return (T) map.computeIfAbsent(artifact, a -> new DefaultArtifact(this, a)); | |
| } else if (clazz == DownloadedArtifact.class) { | |
| @@ -279,12 +253,6 @@ public List<org.eclipse.aether.repository.RemoteRepository> toRepositories(List< | |
| return repositories == null ? null : map(repositories, this::toRepository); | |
| } | |
| - @Override | |
| - public List<org.eclipse.aether.repository.RemoteRepository> toResolvingRepositories( | |
| - List<RemoteRepository> repositories) { | |
| - return getRepositorySystem().newResolutionRepositories(getSession(), toRepositories(repositories)); | |
| - } | |
| - | |
| @Override | |
| public org.eclipse.aether.repository.RemoteRepository toRepository(RemoteRepository repository) { | |
| if (repository instanceof DefaultRemoteRepository defaultRemoteRepository) { | |
| @@ -402,27 +370,6 @@ public <T extends Service> T getService(Class<T> clazz) throws NoSuchElementExce | |
| return t; | |
| } | |
| - @Override | |
| - public Map<Class<? extends Service>, Supplier<? extends Service>> getAllServices() { | |
| - Map<Class<? extends Service>, Supplier<? extends Service>> allServices = new HashMap<>(services.size()); | |
| - // In case the injector is known, lazily populate the map to avoid creating all services upfront. | |
| - if (injector instanceof InjectorImpl injector) { | |
| - Set<Binding<Service>> bindings = injector.getAllBindings(Service.class); | |
| - bindings.stream() | |
| - .map(Binding::getOriginalKey) | |
| - .map(Key::getRawType) | |
| - .flatMap(AbstractSession::collectServiceInterfaces) | |
| - .distinct() | |
| - .forEach(itf -> allServices.put(itf, () -> injector.getInstance(Key.of(itf)))); | |
| - } else { | |
| - List<Service> services = this.injector.getInstance(new Key<List<Service>>() {}); | |
| - for (Service service : services) { | |
| - collectServiceInterfaces(service.getClass()).forEach(itf -> allServices.put(itf, () -> service)); | |
| - } | |
| - } | |
| - return allServices; | |
| - } | |
| - | |
| private Service lookup(Class<? extends Service> c) { | |
| try { | |
| return lookup.lookup(c); | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultArtifactResolver.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultArtifactResolver.java | |
| index 9f22790f39..3614056b28 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultArtifactResolver.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultArtifactResolver.java | |
| @@ -91,7 +91,7 @@ protected ArtifactResolverResult doResolve(ArtifactResolverRequest request) { | |
| InternalSession session = InternalSession.from(request.getSession()); | |
| RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(session, request); | |
| try { | |
| - List<RemoteRepository> repositories = session.toResolvingRepositories( | |
| + List<RemoteRepository> repositories = session.toRepositories( | |
| request.getRepositories() != null ? request.getRepositories() : session.getRemoteRepositories()); | |
| List<ResolverRequest> requests = new ArrayList<>(); | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolver.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolver.java | |
| index d29c3f369a..ac6ba73d5f 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolver.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolver.java | |
| @@ -21,9 +21,7 @@ | |
| import java.io.IOException; | |
| import java.nio.file.Path; | |
| import java.util.Collection; | |
| -import java.util.HashMap; | |
| import java.util.List; | |
| -import java.util.Map; | |
| import java.util.Objects; | |
| import java.util.Set; | |
| import java.util.function.Predicate; | |
| @@ -39,7 +37,6 @@ | |
| import org.apache.maven.api.Project; | |
| import org.apache.maven.api.RemoteRepository; | |
| import org.apache.maven.api.Session; | |
| -import org.apache.maven.api.Version; | |
| import org.apache.maven.api.annotations.Nonnull; | |
| import org.apache.maven.api.annotations.Nullable; | |
| import org.apache.maven.api.di.Named; | |
| @@ -71,45 +68,6 @@ | |
| @Singleton | |
| public class DefaultDependencyResolver implements DependencyResolver { | |
| - /** | |
| - * Cache of information about the modules contained in a path element. | |
| - * Keys are the Java versions targeted by the project. | |
| - * | |
| - * <p><b>TODO:</b> This field should not be in this class, because the cache should be global to the session. | |
| - * This field exists here only temporarily, until clarified where to store session-wide caches.</p> | |
| - */ | |
| - private final Map<Runtime.Version, PathModularizationCache> moduleCaches; | |
| - | |
| - /** | |
| - * Creates an initially empty resolver. | |
| - */ | |
| - public DefaultDependencyResolver() { | |
| - // TODO: the cache should not be instantiated here, but should rather be session-wide. | |
| - moduleCaches = new HashMap<>(); | |
| - } | |
| - | |
| - /** | |
| - * {@return the cache for the given request}. | |
| - * | |
| - * @param request the request for which to get the target version | |
| - * @throws IllegalArgumentException if the version string cannot be interpreted as a valid version | |
| - */ | |
| - private PathModularizationCache moduleCache(DependencyResolverRequest request) { | |
| - return moduleCaches.computeIfAbsent(getTargetVersion(request), PathModularizationCache::new); | |
| - } | |
| - | |
| - /** | |
| - * Returns the target version of the given request as a Java version object. | |
| - * | |
| - * @param request the request for which to get the target version | |
| - * @return the target version as a Java object | |
| - * @throws IllegalArgumentException if the version string cannot be interpreted as a valid version | |
| - */ | |
| - static Runtime.Version getTargetVersion(DependencyResolverRequest request) { | |
| - Version target = request.getTargetVersion(); | |
| - return (target != null) ? Runtime.Version.parse(target.toString()) : Runtime.version(); | |
| - } | |
| - | |
| @Nonnull | |
| @Override | |
| public DependencyResolverResult collect(@Nonnull DependencyResolverRequest request) | |
| @@ -152,7 +110,7 @@ public DependencyResolverResult collect(@Nonnull DependencyResolverRequest reque | |
| .setRoot(root != null ? session.toDependency(root, false) : null) | |
| .setDependencies(session.toDependencies(dependencies, false)) | |
| .setManagedDependencies(session.toDependencies(managedDependencies, true)) | |
| - .setRepositories(session.toResolvingRepositories(remoteRepositories)) | |
| + .setRepositories(session.toRepositories(remoteRepositories)) | |
| .setRequestContext(trace.context()) | |
| .setTrace(trace.trace()); | |
| collectRequest.setResolutionScope(resolutionScope); | |
| @@ -168,11 +126,7 @@ public DependencyResolverResult collect(@Nonnull DependencyResolverRequest reque | |
| final CollectResult result = | |
| session.getRepositorySystem().collectDependencies(systemSession, collectRequest); | |
| return new DefaultDependencyResolverResult( | |
| - null, | |
| - moduleCache(request), | |
| - result.getExceptions(), | |
| - session.getNode(result.getRoot(), request.getVerbose()), | |
| - 0); | |
| + null, null, result.getExceptions(), session.getNode(result.getRoot(), request.getVerbose()), 0); | |
| } catch (DependencyCollectionException e) { | |
| throw new DependencyResolverException("Unable to collect dependencies", e); | |
| } | |
| @@ -217,8 +171,8 @@ public DependencyResolverResult resolve(DependencyResolverRequest request) | |
| InternalSession session = | |
| InternalSession.from(requireNonNull(request, "request").getSession()); | |
| RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(session, request); | |
| - DependencyResolverResult result; | |
| try { | |
| + DependencyResolverResult result; | |
| DependencyResolverResult collectorResult = collect(request); | |
| List<RemoteRepository> repositories = request.getRepositories() != null | |
| ? request.getRepositories() | |
| @@ -237,17 +191,18 @@ public DependencyResolverResult resolve(DependencyResolverRequest request) | |
| .map(Artifact::toCoordinates) | |
| .collect(Collectors.toList()); | |
| Predicate<PathType> filter = request.getPathTypeFilter(); | |
| - DefaultDependencyResolverResult resolverResult = new DefaultDependencyResolverResult( | |
| - null, | |
| - moduleCache(request), | |
| - collectorResult.getExceptions(), | |
| - collectorResult.getRoot(), | |
| - nodes.size()); | |
| if (request.getRequestType() == DependencyResolverRequest.RequestType.FLATTEN) { | |
| + DefaultDependencyResolverResult flattenResult = new DefaultDependencyResolverResult( | |
| + null, null, collectorResult.getExceptions(), collectorResult.getRoot(), nodes.size()); | |
| for (Node node : nodes) { | |
| - resolverResult.addNode(node); | |
| + flattenResult.addNode(node); | |
| } | |
| + result = flattenResult; | |
| } else { | |
| + PathModularizationCache cache = | |
| + new PathModularizationCache(); // TODO: should be project-wide cache. | |
| + DefaultDependencyResolverResult resolverResult = new DefaultDependencyResolverResult( | |
| + null, cache, collectorResult.getExceptions(), collectorResult.getRoot(), nodes.size()); | |
| ArtifactResolverResult artifactResolverResult = | |
| session.getService(ArtifactResolver.class).resolve(session, coordinates, repositories); | |
| for (Node node : nodes) { | |
| @@ -262,13 +217,13 @@ public DependencyResolverResult resolve(DependencyResolverRequest request) | |
| throw cannotReadModuleInfo(path, e); | |
| } | |
| } | |
| + result = resolverResult; | |
| } | |
| - result = resolverResult; | |
| } | |
| + return result; | |
| } finally { | |
| RequestTraceHelper.exit(trace); | |
| } | |
| - return result; | |
| } | |
| private static DependencyResolverException cannotReadModuleInfo(final Path path, final IOException cause) { | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolverResult.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolverResult.java | |
| index a97062ae5a..fa7ace6e0d 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolverResult.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolverResult.java | |
| @@ -27,7 +27,6 @@ | |
| import java.util.LinkedHashMap; | |
| import java.util.List; | |
| import java.util.Map; | |
| -import java.util.Objects; | |
| import java.util.Optional; | |
| import java.util.Set; | |
| import java.util.function.Predicate; | |
| @@ -57,7 +56,6 @@ public class DefaultDependencyResolverResult implements DependencyResolverResult | |
| * The corresponding request. | |
| */ | |
| private final DependencyResolverRequest request; | |
| - | |
| /** | |
| * The exceptions that occurred while building the dependency graph. | |
| */ | |
| @@ -99,29 +97,6 @@ public class DefaultDependencyResolverResult implements DependencyResolverResult | |
| */ | |
| private final PathModularizationCache cache; | |
| - /** | |
| - * Creates an initially empty result with a temporary cache. | |
| - * Callers should add path elements by calls to {@link #addDependency(Node, Dependency, Predicate, Path)}. | |
| - * | |
| - * <p><b>WARNING: this constructor may be removed in a future Maven release.</b> | |
| - * The reason is because {@code DefaultDependencyResolverResult} needs a cache, which should | |
| - * preferably be session-wide. How to manage such caches has not yet been clarified.</p> | |
| - * | |
| - * @param request the corresponding request | |
| - * @param exceptions the exceptions that occurred while building the dependency graph | |
| - * @param root the root node of the dependency graph | |
| - * @param count estimated number of dependencies | |
| - */ | |
| - public DefaultDependencyResolverResult( | |
| - DependencyResolverRequest request, List<Exception> exceptions, Node root, int count) { | |
| - this( | |
| - request, | |
| - new PathModularizationCache(DefaultDependencyResolver.getTargetVersion(request)), | |
| - exceptions, | |
| - root, | |
| - count); | |
| - } | |
| - | |
| /** | |
| * Creates an initially empty result. Callers should add path elements by calls | |
| * to {@link #addDependency(Node, Dependency, Predicate, Path)}. | |
| @@ -132,14 +107,14 @@ public DefaultDependencyResolverResult( | |
| * @param root the root node of the dependency graph | |
| * @param count estimated number of dependencies | |
| */ | |
| - DefaultDependencyResolverResult( | |
| + public DefaultDependencyResolverResult( | |
| DependencyResolverRequest request, | |
| PathModularizationCache cache, | |
| List<Exception> exceptions, | |
| Node root, | |
| int count) { | |
| this.request = request; | |
| - this.cache = Objects.requireNonNull(cache); | |
| + this.cache = cache; | |
| this.exceptions = exceptions; | |
| this.root = root; | |
| nodes = new ArrayList<>(count); | |
| @@ -375,7 +350,7 @@ public DependencyResolverRequest getRequest() { | |
| @Override | |
| public List<Exception> getExceptions() { | |
| - return Collections.unmodifiableList(exceptions); | |
| + return exceptions; | |
| } | |
| @Override | |
| @@ -385,22 +360,22 @@ public Node getRoot() { | |
| @Override | |
| public List<Node> getNodes() { | |
| - return Collections.unmodifiableList(nodes); | |
| + return nodes; | |
| } | |
| @Override | |
| public List<Path> getPaths() { | |
| - return Collections.unmodifiableList(paths); | |
| + return paths; | |
| } | |
| @Override | |
| public Map<PathType, List<Path>> getDispatchedPaths() { | |
| - return Collections.unmodifiableMap(dispatchedPaths); | |
| + return dispatchedPaths; | |
| } | |
| @Override | |
| public Map<Dependency, Path> getDependencies() { | |
| - return Collections.unmodifiableMap(dependencies); | |
| + return dependencies; | |
| } | |
| @Override | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultModelXmlFactory.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultModelXmlFactory.java | |
| index e9ac14d848..f447627cc7 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultModelXmlFactory.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultModelXmlFactory.java | |
| @@ -18,15 +18,6 @@ | |
| */ | |
| package org.apache.maven.impl; | |
| -import javax.xml.stream.XMLInputFactory; | |
| -import javax.xml.stream.XMLStreamConstants; | |
| -import javax.xml.stream.XMLStreamException; | |
| -import javax.xml.stream.XMLStreamReader; | |
| - | |
| -import java.io.ByteArrayInputStream; | |
| -import java.io.ByteArrayOutputStream; | |
| -import java.io.CharArrayReader; | |
| -import java.io.CharArrayWriter; | |
| import java.io.InputStream; | |
| import java.io.OutputStream; | |
| import java.io.Reader; | |
| @@ -39,7 +30,6 @@ | |
| import org.apache.maven.api.annotations.Nonnull; | |
| import org.apache.maven.api.di.Named; | |
| import org.apache.maven.api.di.Singleton; | |
| -import org.apache.maven.api.model.InputLocation; | |
| import org.apache.maven.api.model.InputSource; | |
| import org.apache.maven.api.model.Model; | |
| import org.apache.maven.api.services.xml.ModelXmlFactory; | |
| @@ -97,36 +87,10 @@ private Model doRead(XmlReaderRequest request) throws XmlReaderException { | |
| throw new IllegalArgumentException("path, url, reader or inputStream must be non null"); | |
| } | |
| try { | |
| - // If modelId is not provided and we're reading from a file, try to extract it | |
| - String modelId = request.getModelId(); | |
| - String location = request.getLocation(); | |
| - | |
| - if (modelId == null) { | |
| - if (inputStream != null) { | |
| - ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
| - inputStream.transferTo(baos); | |
| - byte[] buf = baos.toByteArray(); | |
| - modelId = extractModelId(new ByteArrayInputStream(buf)); | |
| - inputStream = new ByteArrayInputStream(buf); | |
| - } else if (reader != null) { | |
| - CharArrayWriter caw = new CharArrayWriter(); | |
| - reader.transferTo(caw); | |
| - char[] buf = caw.toCharArray(); | |
| - modelId = extractModelId(new CharArrayReader(buf)); | |
| - reader = new CharArrayReader(buf); | |
| - } else if (path != null) { | |
| - try (InputStream is = Files.newInputStream(path)) { | |
| - modelId = extractModelId(is); | |
| - if (location == null) { | |
| - location = path.toUri().toString(); | |
| - } | |
| - } | |
| - } | |
| - } | |
| - | |
| InputSource source = null; | |
| - if (modelId != null || location != null) { | |
| - source = InputSource.of(modelId, path != null ? path.toUri().toString() : null); | |
| + if (request.getModelId() != null || request.getLocation() != null) { | |
| + source = new InputSource( | |
| + request.getModelId(), path != null ? path.toUri().toString() : null); | |
| } | |
| MavenStaxReader xml = request.getTransformer() != null | |
| ? new MavenStaxReader(request.getTransformer()::transform) | |
| @@ -157,29 +121,22 @@ public void write(XmlWriterRequest<Model> request) throws XmlWriterException { | |
| Path path = request.getPath(); | |
| OutputStream outputStream = request.getOutputStream(); | |
| Writer writer = request.getWriter(); | |
| - | |
| + Function<Object, String> inputLocationFormatter = request.getInputLocationFormatter(); | |
| if (writer == null && outputStream == null && path == null) { | |
| throw new IllegalArgumentException("writer, outputStream or path must be non null"); | |
| } | |
| - | |
| try { | |
| - MavenStaxWriter xmlWriter = new MavenStaxWriter(); | |
| - xmlWriter.setAddLocationInformation(false); | |
| - | |
| - Function<Object, String> formatter = request.getInputLocationFormatter(); | |
| - if (formatter != null) { | |
| - xmlWriter.setAddLocationInformation(true); | |
| - Function<InputLocation, String> adapter = formatter::apply; | |
| - xmlWriter.setStringFormatter(adapter); | |
| + MavenStaxWriter w = new MavenStaxWriter(); | |
| + if (inputLocationFormatter != null) { | |
| + w.setStringFormatter((Function) inputLocationFormatter); | |
| } | |
| - | |
| if (writer != null) { | |
| - xmlWriter.write(writer, content); | |
| + w.write(writer, content); | |
| } else if (outputStream != null) { | |
| - xmlWriter.write(outputStream, content); | |
| + w.write(outputStream, content); | |
| } else { | |
| try (OutputStream os = Files.newOutputStream(path)) { | |
| - xmlWriter.write(os, content); | |
| + w.write(os, content); | |
| } | |
| } | |
| } catch (Exception e) { | |
| @@ -187,147 +144,6 @@ public void write(XmlWriterRequest<Model> request) throws XmlWriterException { | |
| } | |
| } | |
| - static class InputFactoryHolder { | |
| - static final XMLInputFactory XML_INPUT_FACTORY; | |
| - | |
| - static { | |
| - XMLInputFactory factory = XMLInputFactory.newFactory(); | |
| - factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, true); | |
| - factory.setProperty(XMLInputFactory.IS_COALESCING, true); | |
| - XML_INPUT_FACTORY = factory; | |
| - } | |
| - } | |
| - | |
| - /** | |
| - * Extracts the modelId (groupId:artifactId:version) from a POM XML stream | |
| - * by parsing just enough XML to get the GAV coordinates. | |
| - * | |
| - * @param inputStream the input stream to read from | |
| - * @return the modelId in format "groupId:artifactId:version" or null if not determinable | |
| - */ | |
| - private String extractModelId(InputStream inputStream) { | |
| - try { | |
| - XMLStreamReader reader = InputFactoryHolder.XML_INPUT_FACTORY.createXMLStreamReader(inputStream); | |
| - try { | |
| - return extractModelId(reader); | |
| - } finally { | |
| - reader.close(); | |
| - } | |
| - } catch (Exception e) { | |
| - // If extraction fails, return null and let the normal parsing handle it | |
| - // This is not a critical failure | |
| - return null; | |
| - } | |
| - } | |
| - | |
| - private String extractModelId(Reader reader) { | |
| - try { | |
| - // Use a buffered stream to allow efficient reading | |
| - XMLStreamReader xmlReader = InputFactoryHolder.XML_INPUT_FACTORY.createXMLStreamReader(reader); | |
| - try { | |
| - return extractModelId(xmlReader); | |
| - } finally { | |
| - xmlReader.close(); | |
| - } | |
| - } catch (Exception e) { | |
| - // If extraction fails, return null and let the normal parsing handle it | |
| - // This is not a critical failure | |
| - return null; | |
| - } | |
| - } | |
| - | |
| - private static String extractModelId(XMLStreamReader reader) throws XMLStreamException { | |
| - String groupId = null; | |
| - String artifactId = null; | |
| - String version = null; | |
| - String parentGroupId = null; | |
| - String parentVersion = null; | |
| - | |
| - boolean inProject = false; | |
| - boolean inParent = false; | |
| - String currentElement = null; | |
| - | |
| - while (reader.hasNext()) { | |
| - int event = reader.next(); | |
| - | |
| - if (event == XMLStreamConstants.START_ELEMENT) { | |
| - String localName = reader.getLocalName(); | |
| - | |
| - if ("project".equals(localName)) { | |
| - inProject = true; | |
| - } else if ("parent".equals(localName) && inProject) { | |
| - inParent = true; | |
| - } else if (inProject | |
| - && ("groupId".equals(localName) | |
| - || "artifactId".equals(localName) | |
| - || "version".equals(localName))) { | |
| - currentElement = localName; | |
| - } | |
| - } else if (event == XMLStreamConstants.END_ELEMENT) { | |
| - String localName = reader.getLocalName(); | |
| - | |
| - if ("parent".equals(localName)) { | |
| - inParent = false; | |
| - } else if ("project".equals(localName)) { | |
| - break; // We've processed the main project element | |
| - } | |
| - currentElement = null; | |
| - } else if (event == XMLStreamConstants.CHARACTERS && currentElement != null) { | |
| - String text = reader.getText().trim(); | |
| - if (!text.isEmpty()) { | |
| - if (inParent) { | |
| - switch (currentElement) { | |
| - case "groupId": | |
| - parentGroupId = text; | |
| - break; | |
| - case "version": | |
| - parentVersion = text; | |
| - break; | |
| - default: | |
| - // Ignore other elements | |
| - break; | |
| - } | |
| - } else { | |
| - switch (currentElement) { | |
| - case "groupId": | |
| - groupId = text; | |
| - break; | |
| - case "artifactId": | |
| - artifactId = text; | |
| - break; | |
| - case "version": | |
| - version = text; | |
| - break; | |
| - default: | |
| - // Ignore other elements | |
| - break; | |
| - } | |
| - } | |
| - } | |
| - } | |
| - | |
| - // Early exit if we have enough information | |
| - if (artifactId != null && groupId != null && version != null) { | |
| - break; | |
| - } | |
| - } | |
| - | |
| - // Use parent values as fallback | |
| - if (groupId == null) { | |
| - groupId = parentGroupId; | |
| - } | |
| - if (version == null) { | |
| - version = parentVersion; | |
| - } | |
| - | |
| - // Return modelId if we have all required components | |
| - if (groupId != null && artifactId != null && version != null) { | |
| - return groupId + ":" + artifactId + ":" + version; | |
| - } | |
| - | |
| - return null; | |
| - } | |
| - | |
| /** | |
| * Simply parse the given xml string. | |
| * | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsBuilder.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsBuilder.java | |
| index be7dd9e863..76695f4b1f 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsBuilder.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsBuilder.java | |
| @@ -268,22 +268,6 @@ private Settings decrypt( | |
| UnaryOperator<String> decryptFunction = str -> { | |
| if (str != null && !str.isEmpty() && !str.contains("${") && secDispatcher.isAnyEncryptedString(str)) { | |
| if (secDispatcher.isLegacyEncryptedString(str)) { | |
| - // the call above return true for too broad types of strings, original idea with 2.x sec-dispatcher | |
| - // was to make it possible to add "descriptions" to encrypted passwords. Maven 4 is | |
| - // limiting itself to decryption of ONLY the simplest cases of legacy passwords, those having form | |
| - // as documented on page: https://maven.apache.org/guides/mini/guide-encryption.html | |
| - // Examples of decrypted legacy passwords: | |
| - // <password>{COQLCE6DU6GtcS5P=}</password> | |
| - // <password>Oleg reset this password on 2009-03-11 {COQLCE6DU6GtcS5P=}</password> | |
| - | |
| - // In short, secDispatcher#isLegacyEncryptedString(str) did return true, but we apply more scrutiny | |
| - // and check does string start with "{" or contains " {" (whitespace before opening curly braces), | |
| - // and that it ends with "}" strictly. Otherwise, we refuse it. | |
| - if ((!str.startsWith("{") && !str.contains(" {")) || !str.endsWith("}")) { | |
| - // this is not a legacy password we care for | |
| - return str; | |
| - } | |
| - | |
| // add a problem | |
| preMaven4Passwords.incrementAndGet(); | |
| } | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsValidator.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsValidator.java | |
| index b2df07a6e2..21284afa0c 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsValidator.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsValidator.java | |
| @@ -271,7 +271,7 @@ private void validateRepositories( | |
| */ | |
| private static boolean validateStringEmpty( | |
| ProblemCollector<BuilderProblem> problems, String fieldName, String string, String message) { | |
| - if (string == null || string.isEmpty()) { | |
| + if (string == null || string.length() == 0) { | |
| return true; | |
| } | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsXmlFactory.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsXmlFactory.java | |
| index 0aecc0460b..348c8a9a8b 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsXmlFactory.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsXmlFactory.java | |
| @@ -53,7 +53,7 @@ public Settings read(@Nonnull XmlReaderRequest request) throws XmlReaderExceptio | |
| try { | |
| InputSource source = null; | |
| if (request.getModelId() != null || request.getLocation() != null) { | |
| - source = InputSource.of(request.getLocation()); | |
| + source = new InputSource(request.getLocation()); | |
| } | |
| SettingsStaxReader xml = request.getTransformer() != null | |
| ? new SettingsStaxReader(request.getTransformer()::transform) | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultToolchainsXmlFactory.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultToolchainsXmlFactory.java | |
| index 89452d1367..18a6bd8368 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultToolchainsXmlFactory.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultToolchainsXmlFactory.java | |
| @@ -55,7 +55,7 @@ public PersistedToolchains read(@Nonnull XmlReaderRequest request) throws XmlRea | |
| try { | |
| InputSource source = null; | |
| if (request.getModelId() != null || request.getLocation() != null) { | |
| - source = InputSource.of(request.getLocation()); | |
| + source = new InputSource(request.getLocation()); | |
| } | |
| MavenToolchainsStaxReader xml = request.getTransformer() != null | |
| ? new MavenToolchainsStaxReader(request.getTransformer()::transform) | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionRangeResolver.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionRangeResolver.java | |
| index b0097d5248..df182d976a 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionRangeResolver.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionRangeResolver.java | |
| @@ -69,7 +69,7 @@ public VersionRangeResolverResult doResolve(VersionRangeResolverRequest request) | |
| session.getSession(), | |
| new VersionRangeRequest( | |
| session.toArtifact(request.getArtifactCoordinates()), | |
| - session.toResolvingRepositories( | |
| + session.toRepositories( | |
| request.getRepositories() != null | |
| ? request.getRepositories() | |
| : session.getRemoteRepositories()), | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionResolver.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionResolver.java | |
| index 1f233f604b..c80a1d24ad 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionResolver.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionResolver.java | |
| @@ -61,7 +61,7 @@ protected VersionResolverResult doResolve(VersionResolverRequest request) throws | |
| try { | |
| VersionRequest req = new VersionRequest( | |
| session.toArtifact(request.getArtifactCoordinates()), | |
| - session.toResolvingRepositories( | |
| + session.toRepositories( | |
| request.getRepositories() != null | |
| ? request.getRepositories() | |
| : session.getRemoteRepositories()), | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java | |
| index 7d9945077f..e39836e255 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java | |
| @@ -20,9 +20,7 @@ | |
| import java.util.Collection; | |
| import java.util.List; | |
| -import java.util.Map; | |
| import java.util.function.Function; | |
| -import java.util.function.Supplier; | |
| import org.apache.maven.api.Artifact; | |
| import org.apache.maven.api.ArtifactCoordinates; | |
| @@ -32,7 +30,6 @@ | |
| import org.apache.maven.api.Node; | |
| import org.apache.maven.api.RemoteRepository; | |
| import org.apache.maven.api.Repository; | |
| -import org.apache.maven.api.Service; | |
| import org.apache.maven.api.Session; | |
| import org.apache.maven.api.WorkspaceRepository; | |
| import org.apache.maven.api.annotations.Nonnull; | |
| @@ -101,8 +98,6 @@ <REQ extends Request<?>, REP extends Result<REQ>> List<REP> requests( | |
| List<org.eclipse.aether.repository.RemoteRepository> toRepositories(List<RemoteRepository> repositories); | |
| - List<org.eclipse.aether.repository.RemoteRepository> toResolvingRepositories(List<RemoteRepository> repositories); | |
| - | |
| org.eclipse.aether.repository.RemoteRepository toRepository(RemoteRepository repository); | |
| org.eclipse.aether.repository.LocalRepository toRepository(LocalRepository repository); | |
| @@ -143,12 +138,4 @@ List<org.eclipse.aether.graph.Dependency> toDependencies( | |
| * @see RequestTraceHelper#enter(Session, Object) For the recommended way to manage traces | |
| */ | |
| RequestTrace getCurrentTrace(); | |
| - | |
| - /** | |
| - * Retrieves a map of all services. | |
| - * | |
| - * @see #getService(Class) | |
| - */ | |
| - @Nonnull | |
| - Map<Class<? extends Service>, Supplier<? extends Service>> getAllServices(); | |
| } | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/PathModularization.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/PathModularization.java | |
| index a40e57215a..db0c950995 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/PathModularization.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/PathModularization.java | |
| @@ -43,7 +43,7 @@ | |
| * or module hierarchy, but not module source hierarchy. The latter is excluded because this class | |
| * is for path elements of compiled codes. | |
| */ | |
| -final class PathModularization { | |
| +class PathModularization { | |
| /** | |
| * A unique constant for all non-modular dependencies. | |
| */ | |
| @@ -132,11 +132,10 @@ private PathModularization() { | |
| * Otherwise builds an empty map. | |
| * | |
| * @param path directory or JAR file to test | |
| - * @param target the target Java release for which the project is built | |
| * @param resolve whether the module names are requested. If false, null values may be used instead | |
| * @throws IOException if an error occurred while reading the JAR file or the module descriptor | |
| */ | |
| - PathModularization(Path path, Runtime.Version target, boolean resolve) throws IOException { | |
| + PathModularization(Path path, boolean resolve) throws IOException { | |
| filename = path.getFileName().toString(); | |
| if (Files.isDirectory(path)) { | |
| /* | |
| @@ -193,7 +192,7 @@ private PathModularization() { | |
| * If no descriptor, the "Automatic-Module-Name" manifest attribute is | |
| * taken as a fallback. | |
| */ | |
| - try (JarFile jar = new JarFile(path.toFile(), false, JarFile.OPEN_READ, target)) { | |
| + try (JarFile jar = new JarFile(path.toFile())) { | |
| ZipEntry entry = jar.getEntry(MODULE_INFO); | |
| if (entry != null) { | |
| ModuleDescriptor descriptor = null; | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/PathModularizationCache.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/PathModularizationCache.java | |
| index 3ab71dc33c..e04ce136da 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/PathModularizationCache.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/PathModularizationCache.java | |
| @@ -24,7 +24,6 @@ | |
| import java.util.Collection; | |
| import java.util.HashMap; | |
| import java.util.Map; | |
| -import java.util.Objects; | |
| import java.util.Optional; | |
| import java.util.Set; | |
| import java.util.StringJoiner; | |
| @@ -39,7 +38,7 @@ | |
| * same dependency is used for different scope. For example a path used for compilation | |
| * is typically also used for tests. | |
| */ | |
| -final class PathModularizationCache { | |
| +class PathModularizationCache { | |
| /** | |
| * Module information for each JAR file or output directories. | |
| * Cached when first requested to avoid decoding the module descriptors multiple times. | |
| @@ -56,21 +55,12 @@ final class PathModularizationCache { | |
| */ | |
| private final Map<Path, PathType> pathTypes; | |
| - /** | |
| - * The target Java version for which the project is built. | |
| - * If unknown, it should be {@link Runtime#version()}. | |
| - */ | |
| - private final Runtime.Version targetVersion; | |
| - | |
| /** | |
| * Creates an initially empty cache. | |
| - * | |
| - * @param target the target Java release for which the project is built | |
| */ | |
| - PathModularizationCache(Runtime.Version target) { | |
| + PathModularizationCache() { | |
| moduleInfo = new HashMap<>(); | |
| pathTypes = new HashMap<>(); | |
| - targetVersion = Objects.requireNonNull(target); | |
| } | |
| /** | |
| @@ -80,7 +70,7 @@ final class PathModularizationCache { | |
| PathModularization getModuleInfo(Path path) throws IOException { | |
| PathModularization info = moduleInfo.get(path); | |
| if (info == null) { | |
| - info = new PathModularization(path, targetVersion, true); | |
| + info = new PathModularization(path, true); | |
| moduleInfo.put(path, info); | |
| pathTypes.put(path, info.getPathType()); | |
| } | |
| @@ -95,7 +85,7 @@ PathModularization getModuleInfo(Path path) throws IOException { | |
| private PathType getPathType(Path path) throws IOException { | |
| PathType type = pathTypes.get(path); | |
| if (type == null) { | |
| - type = new PathModularization(path, targetVersion, false).getPathType(); | |
| + type = new PathModularization(path, false).getPathType(); | |
| pathTypes.put(path, type); | |
| } | |
| return type; | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/PathSelector.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/PathSelector.java | |
| index a8cc3da2ec..20d68cd7bb 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/PathSelector.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/PathSelector.java | |
| @@ -449,21 +449,18 @@ private static String[] normalizePatterns(final Collection<String> patterns, fin | |
| pattern = pattern.substring(3); | |
| } | |
| pattern = pattern.replace("/**/**/", "/**/"); | |
| - | |
| - // Escape special characters, including braces | |
| - // Braces from user input must be literals; we'll inject our own braces for expansion below | |
| pattern = pattern.replace("\\", "\\\\") | |
| .replace("[", "\\[") | |
| .replace("]", "\\]") | |
| .replace("{", "\\{") | |
| .replace("}", "\\}"); | |
| - | |
| - // Transform ** patterns to use brace expansion for POSIX behavior | |
| - // This replaces the complex addPatternsWithOneDirRemoved logic | |
| - // We perform this after escaping so that only these injected braces participate in expansion | |
| - pattern = pattern.replace("**/", "{**/,}"); | |
| - | |
| normalized.add(DEFAULT_SYNTAX + pattern); | |
| + /* | |
| + * If the pattern starts or ends with "**", Java GLOB expects a directory level at | |
| + * that location while Maven seems to consider that "**" can mean "no directory". | |
| + * Add another pattern for reproducing this effect. | |
| + */ | |
| + addPatternsWithOneDirRemoved(normalized, pattern, 0); | |
| } else { | |
| normalized.add(pattern); | |
| } | |
| @@ -472,6 +469,37 @@ private static String[] normalizePatterns(final Collection<String> patterns, fin | |
| return simplify(normalized, excludes); | |
| } | |
| + /** | |
| + * Adds all variants of the given pattern with {@code **} removed. | |
| + * This is used for simulating the Maven behavior where {@code "**} may match zero directory. | |
| + * Tests suggest that we need an explicit GLOB pattern with no {@code "**"} for matching an absence of directory. | |
| + * | |
| + * @param patterns where to add the derived patterns | |
| + * @param pattern the pattern for which to add derived forms, without the "glob:" syntax prefix | |
| + * @param end should be 0 (reserved for recursive invocations of this method) | |
| + */ | |
| + private static void addPatternsWithOneDirRemoved(final Set<String> patterns, final String pattern, int end) { | |
| + final int length = pattern.length(); | |
| + int start; | |
| + while ((start = pattern.indexOf("**", end)) >= 0) { | |
| + end = start + 2; // 2 is the length of "**". | |
| + if (end < length) { | |
| + if (pattern.charAt(end) != '/') { | |
| + continue; | |
| + } | |
| + if (start == 0) { | |
| + end++; // Ommit the leading slash if there is nothing before it. | |
| + } | |
| + } | |
| + if (start > 0 && pattern.charAt(--start) != '/') { | |
| + continue; | |
| + } | |
| + String reduced = pattern.substring(0, start) + pattern.substring(end); | |
| + patterns.add(DEFAULT_SYNTAX + reduced); | |
| + addPatternsWithOneDirRemoved(patterns, reduced, start); | |
| + } | |
| + } | |
| + | |
| /** | |
| * Applies some heuristic rules for simplifying the set of patterns, | |
| * then returns the patterns as an array. | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/SettingsUtilsV4.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/SettingsUtilsV4.java | |
| index 0290464ebb..8a5d1e81a2 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/SettingsUtilsV4.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/SettingsUtilsV4.java | |
| @@ -361,10 +361,10 @@ private static org.apache.maven.api.settings.InputLocation toLocation( | |
| org.apache.maven.api.model.InputSource source = location.getSource(); | |
| Map<Object, org.apache.maven.api.settings.InputLocation> locs = location.getLocations().entrySet().stream() | |
| .collect(Collectors.toMap(Map.Entry::getKey, e -> toLocation(e.getValue()))); | |
| - return org.apache.maven.api.settings.InputLocation.of( | |
| + return new org.apache.maven.api.settings.InputLocation( | |
| location.getLineNumber(), | |
| location.getColumnNumber(), | |
| - source != null ? org.apache.maven.api.settings.InputSource.of(source.getLocation()) : null, | |
| + source != null ? new org.apache.maven.api.settings.InputSource(source.getLocation()) : null, | |
| locs); | |
| } else { | |
| return null; | |
| @@ -377,10 +377,10 @@ private static org.apache.maven.api.model.InputLocation toLocation( | |
| org.apache.maven.api.settings.InputSource source = location.getSource(); | |
| Map<Object, InputLocation> locs = location.getLocations().entrySet().stream() | |
| .collect(Collectors.toMap(Map.Entry::getKey, e -> toLocation(e.getValue()))); | |
| - return org.apache.maven.api.model.InputLocation.of( | |
| + return new org.apache.maven.api.model.InputLocation( | |
| location.getLineNumber(), | |
| location.getColumnNumber(), | |
| - source != null ? org.apache.maven.api.model.InputSource.of("", source.getLocation()) : null, | |
| + source != null ? new org.apache.maven.api.model.InputSource("", source.getLocation()) : null, | |
| locs); | |
| } else { | |
| return null; | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/Cache.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/Cache.java | |
| deleted file mode 100644 | |
| index 440a0a860e..0000000000 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/Cache.java | |
| +++ /dev/null | |
| @@ -1,789 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.impl.cache; | |
| - | |
| -import java.lang.ref.Reference; | |
| -import java.lang.ref.ReferenceQueue; | |
| -import java.lang.ref.SoftReference; | |
| -import java.lang.ref.WeakReference; | |
| -import java.util.Collection; | |
| -import java.util.Map; | |
| -import java.util.Objects; | |
| -import java.util.Set; | |
| -import java.util.concurrent.ConcurrentHashMap; | |
| -import java.util.concurrent.atomic.AtomicLong; | |
| -import java.util.function.BiPredicate; | |
| -import java.util.function.Function; | |
| - | |
| -/** | |
| - * A cache interface that provides configurable reference types for both keys and values, | |
| - * and supports automatic cleanup of garbage-collected entries. | |
| - * <p> | |
| - * This cache is designed for scenarios where: | |
| - * <ul> | |
| - * <li>Values should be eligible for garbage collection when memory is low</li> | |
| - * <li>Concurrent access is required</li> | |
| - * <li>Automatic cleanup of stale entries is desired</li> | |
| - * </ul> | |
| - * <p> | |
| - * The cache can use different reference types (none, soft, weak, hard) for both keys and values, | |
| - * depending on the factory method used to create the cache instance. | |
| - * <p> | |
| - * Note: All implementations are thread-safe and optimized for concurrent read access. | |
| - * | |
| - * @param <K> the type of keys maintained by this cache | |
| - * @param <V> the type of cached values | |
| - */ | |
| -public interface Cache<K, V> { | |
| - | |
| - /** | |
| - * Enumeration of reference types that can be used for individual entries. | |
| - */ | |
| - enum ReferenceType { | |
| - /** No caching - always compute the value */ | |
| - NONE, | |
| - /** Soft references - cleared before OutOfMemoryError */ | |
| - SOFT, | |
| - /** Weak references - cleared more aggressively */ | |
| - WEAK, | |
| - /** Hard references - never cleared by GC */ | |
| - HARD | |
| - } | |
| - | |
| - /** | |
| - * Computes a value for the given key if it's not already present, using the specified reference type. | |
| - * <p> | |
| - * This method allows fine-grained control over the reference type used for individual entries, | |
| - * overriding the cache's default reference type for this specific key-value pair. | |
| - * | |
| - * @param key the key whose associated value is to be returned or computed | |
| - * @param mappingFunction the function to compute a value | |
| - * @param referenceType the reference type to use for this entry (null uses cache default) | |
| - * @return the current (existing or computed) value associated with the specified key | |
| - */ | |
| - V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction, ReferenceType referenceType); | |
| - | |
| - default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { | |
| - return computeIfAbsent(key, mappingFunction, null); | |
| - } | |
| - | |
| - void removeIf(BiPredicate<K, V> o); | |
| - | |
| - V get(K key); | |
| - | |
| - int size(); | |
| - | |
| - void clear(); | |
| - | |
| - default boolean containsKey(K key) { | |
| - return get(key) != null; | |
| - } | |
| - | |
| - static <K, V> Cache<K, V> newCache(ReferenceType referenceType) { | |
| - return RefConcurrentMap.newCache(referenceType); | |
| - } | |
| - | |
| - static <K, V> Cache<K, V> newCache(ReferenceType referenceType, String name) { | |
| - return RefConcurrentMap.newCache(referenceType, name); | |
| - } | |
| - | |
| - /** | |
| - * Creates a new cache with separate reference types for keys and values. | |
| - * This allows fine-grained control over eviction behavior and enables | |
| - * better tracking of cache misses caused by key vs value evictions. | |
| - * | |
| - * @param keyReferenceType the reference type to use for keys | |
| - * @param valueReferenceType the reference type to use for values | |
| - * @return a new cache instance | |
| - */ | |
| - static <K, V> Cache<K, V> newCache(ReferenceType keyReferenceType, ReferenceType valueReferenceType) { | |
| - return RefConcurrentMap.newCache(keyReferenceType, valueReferenceType); | |
| - } | |
| - | |
| - static <K, V> Cache<K, V> newCache(ReferenceType keyReferenceType, ReferenceType valueReferenceType, String name) { | |
| - return RefConcurrentMap.newCache(keyReferenceType, valueReferenceType, name); | |
| - } | |
| - | |
| - /** | |
| - * Interface for listening to cache eviction events. | |
| - */ | |
| - interface EvictionListener { | |
| - /** | |
| - * Called when a key is evicted from the cache. | |
| - */ | |
| - void onKeyEviction(); | |
| - | |
| - /** | |
| - * Called when a value is evicted from the cache. | |
| - */ | |
| - void onValueEviction(); | |
| - } | |
| - | |
| - /** | |
| - * A concurrent map implementation that uses configurable reference types for both keys and values, | |
| - * and supports automatic cleanup of garbage-collected entries. | |
| - * <p> | |
| - * This implementation is package-private and accessed through the {@link Cache} interface. | |
| - * | |
| - * @param <K> the type of keys maintained by this map | |
| - * @param <V> the type of mapped values | |
| - */ | |
| - class RefConcurrentMap<K, V> implements Map<K, V>, Cache<K, V> { | |
| - | |
| - private final ReferenceQueue<K> keyQueue = new ReferenceQueue<>(); | |
| - private final ReferenceQueue<V> valueQueue = new ReferenceQueue<>(); | |
| - private final ConcurrentHashMap<RefConcurrentReference<K>, ComputeReference<V>> map = new ConcurrentHashMap<>(); | |
| - | |
| - // Default reference types for this map | |
| - private final ReferenceType defaultReferenceType; | |
| - private final ReferenceType keyReferenceType; | |
| - private final ReferenceType valueReferenceType; | |
| - | |
| - // Cache name for debugging | |
| - private final String name; | |
| - | |
| - // Eviction statistics | |
| - private final AtomicLong keyEvictions = new AtomicLong(0); | |
| - private final AtomicLong valueEvictions = new AtomicLong(0); | |
| - | |
| - // Eviction listener (weak reference to avoid memory leaks) | |
| - private volatile EvictionListener evictionListener; | |
| - | |
| - /** | |
| - * Private constructor - use factory methods to create instances. | |
| - */ | |
| - private RefConcurrentMap(ReferenceType defaultReferenceType) { | |
| - this.defaultReferenceType = defaultReferenceType; | |
| - this.keyReferenceType = defaultReferenceType; | |
| - this.valueReferenceType = defaultReferenceType; | |
| - this.name = "Cache-" + defaultReferenceType; | |
| - } | |
| - | |
| - /** | |
| - * Private constructor with separate key and value reference types. | |
| - */ | |
| - private RefConcurrentMap(ReferenceType keyReferenceType, ReferenceType valueReferenceType) { | |
| - this.defaultReferenceType = keyReferenceType; // For backward compatibility | |
| - this.keyReferenceType = keyReferenceType; | |
| - this.valueReferenceType = valueReferenceType; | |
| - this.name = "Cache-" + keyReferenceType + "/" + valueReferenceType; | |
| - } | |
| - | |
| - /** | |
| - * Private constructor with name. | |
| - */ | |
| - private RefConcurrentMap(ReferenceType defaultReferenceType, String name) { | |
| - this.defaultReferenceType = defaultReferenceType; | |
| - this.keyReferenceType = defaultReferenceType; | |
| - this.valueReferenceType = defaultReferenceType; | |
| - this.name = name; | |
| - } | |
| - | |
| - /** | |
| - * Private constructor with separate key and value reference types and name. | |
| - */ | |
| - private RefConcurrentMap(ReferenceType keyReferenceType, ReferenceType valueReferenceType, String name) { | |
| - this.defaultReferenceType = keyReferenceType; // For backward compatibility | |
| - this.keyReferenceType = keyReferenceType; | |
| - this.valueReferenceType = valueReferenceType; | |
| - this.name = name; | |
| - | |
| - // Debug logging to verify constructor assignment (disabled) | |
| - // System.err.println("DEBUG: RefConcurrentMap constructor - name=" + name + ", keyReferenceType=" | |
| - // + keyReferenceType + ", valueReferenceType=" + valueReferenceType); | |
| - } | |
| - | |
| - static <K, V> RefConcurrentMap<K, V> newCache(ReferenceType referenceType) { | |
| - return new RefConcurrentMap<>(referenceType); | |
| - } | |
| - | |
| - static <K, V> RefConcurrentMap<K, V> newCache( | |
| - ReferenceType keyReferenceType, ReferenceType valueReferenceType) { | |
| - return new RefConcurrentMap<>(keyReferenceType, valueReferenceType); | |
| - } | |
| - | |
| - static <K, V> RefConcurrentMap<K, V> newCache(ReferenceType referenceType, String name) { | |
| - return new RefConcurrentMap<>(referenceType, name); | |
| - } | |
| - | |
| - static <K, V> RefConcurrentMap<K, V> newCache( | |
| - ReferenceType keyReferenceType, ReferenceType valueReferenceType, String name) { | |
| - return new RefConcurrentMap<>(keyReferenceType, valueReferenceType, name); | |
| - } | |
| - | |
| - /** | |
| - * Sets an eviction listener to be notified of eviction events. | |
| - */ | |
| - public void setEvictionListener(EvictionListener listener) { | |
| - this.evictionListener = listener; | |
| - } | |
| - | |
| - // Base class for reference implementations | |
| - private abstract static class RefConcurrentReference<T> { | |
| - protected final int hash; | |
| - | |
| - RefConcurrentReference(T referent) { | |
| - this.hash = referent.hashCode(); | |
| - } | |
| - | |
| - public abstract Reference<T> getReference(); | |
| - | |
| - public abstract T get(); | |
| - | |
| - @Override | |
| - public boolean equals(Object obj) { | |
| - if (this == obj) { | |
| - return true; | |
| - } | |
| - if (!(obj instanceof RefConcurrentMap.RefConcurrentReference<?> other)) { | |
| - return false; | |
| - } | |
| - T thisRef = this.get(); | |
| - Object otherRef = other.get(); | |
| - // Use equals() for proper object comparison | |
| - return thisRef != null && thisRef.equals(otherRef); | |
| - } | |
| - | |
| - @Override | |
| - public int hashCode() { | |
| - return hash; | |
| - } | |
| - } | |
| - | |
| - // Soft reference implementation | |
| - private static class SoftRefConcurrentReference<T> extends RefConcurrentReference<T> { | |
| - final SoftReference<T> softRef; | |
| - | |
| - SoftRefConcurrentReference(T referent, ReferenceQueue<T> queue) { | |
| - super(referent); | |
| - this.softRef = new SoftReference<>(referent, queue); | |
| - } | |
| - | |
| - @Override | |
| - public SoftReference<T> getReference() { | |
| - return softRef; | |
| - } | |
| - | |
| - @Override | |
| - public T get() { | |
| - return softRef.get(); | |
| - } | |
| - } | |
| - | |
| - // Weak reference implementation | |
| - private static class WeakRefConcurrentReference<T> extends RefConcurrentReference<T> { | |
| - final WeakReference<T> weakRef; | |
| - | |
| - WeakRefConcurrentReference(T referent, ReferenceQueue<T> queue) { | |
| - super(referent); | |
| - this.weakRef = new WeakReference<>(referent, queue); | |
| - } | |
| - | |
| - @Override | |
| - public Reference<T> getReference() { | |
| - return weakRef; | |
| - } | |
| - | |
| - @Override | |
| - public T get() { | |
| - return weakRef.get(); | |
| - } | |
| - } | |
| - | |
| - // Hard reference implementation (strong references) | |
| - private static class HardRefConcurrentReference<T> extends RefConcurrentReference<T> { | |
| - private final T referent; | |
| - | |
| - HardRefConcurrentReference(T referent, ReferenceQueue<T> queue) { | |
| - super(referent); | |
| - this.referent = referent; | |
| - // Note: queue is ignored for hard references since they're never GC'd | |
| - } | |
| - | |
| - @Override | |
| - public Reference<T> getReference() { | |
| - // Return null since hard references don't use Reference objects | |
| - return null; | |
| - } | |
| - | |
| - @Override | |
| - public T get() { | |
| - return referent; | |
| - } | |
| - } | |
| - | |
| - // Base class for compute references | |
| - private abstract static class ComputeReference<V> { | |
| - protected final boolean computing; | |
| - | |
| - ComputeReference(boolean computing) { | |
| - this.computing = computing; | |
| - } | |
| - | |
| - public abstract V get(); | |
| - | |
| - public abstract Reference<V> getReference(); | |
| - } | |
| - | |
| - // Soft compute reference implementation | |
| - private static class SoftComputeReference<V> extends ComputeReference<V> { | |
| - final SoftReference<V> softRef; | |
| - | |
| - SoftComputeReference(V value, ReferenceQueue<V> queue) { | |
| - super(false); | |
| - this.softRef = new SoftReference<>(value, queue); | |
| - } | |
| - | |
| - private SoftComputeReference(ReferenceQueue<V> queue) { | |
| - super(true); | |
| - this.softRef = new SoftReference<>(null, queue); | |
| - } | |
| - | |
| - static <V> SoftComputeReference<V> computing(ReferenceQueue<V> queue) { | |
| - return new SoftComputeReference<>(queue); | |
| - } | |
| - | |
| - @Override | |
| - public V get() { | |
| - return softRef.get(); | |
| - } | |
| - | |
| - @Override | |
| - public Reference<V> getReference() { | |
| - return softRef; | |
| - } | |
| - } | |
| - | |
| - // Weak compute reference implementation | |
| - private static class WeakComputeReference<V> extends ComputeReference<V> { | |
| - final WeakReference<V> weakRef; | |
| - | |
| - WeakComputeReference(V value, ReferenceQueue<V> queue) { | |
| - super(false); | |
| - this.weakRef = new WeakReference<>(value, queue); | |
| - } | |
| - | |
| - private WeakComputeReference(ReferenceQueue<V> queue) { | |
| - super(true); | |
| - this.weakRef = new WeakReference<>(null, queue); | |
| - } | |
| - | |
| - static <V> WeakComputeReference<V> computing(ReferenceQueue<V> queue) { | |
| - return new WeakComputeReference<>(queue); | |
| - } | |
| - | |
| - @Override | |
| - public V get() { | |
| - return weakRef.get(); | |
| - } | |
| - | |
| - @Override | |
| - public Reference<V> getReference() { | |
| - return weakRef; | |
| - } | |
| - } | |
| - | |
| - // Hard compute reference implementation (strong references) | |
| - private static class HardComputeReference<V> extends ComputeReference<V> { | |
| - private final V value; | |
| - | |
| - HardComputeReference(V value, ReferenceQueue<V> queue) { | |
| - super(false); | |
| - this.value = value; | |
| - // Note: queue is ignored for hard references since they're never GC'd | |
| - } | |
| - | |
| - private HardComputeReference(ReferenceQueue<V> queue) { | |
| - super(true); | |
| - this.value = null; | |
| - } | |
| - | |
| - static <V> HardComputeReference<V> computing(ReferenceQueue<V> queue) { | |
| - return new HardComputeReference<>(queue); | |
| - } | |
| - | |
| - @Override | |
| - public V get() { | |
| - return value; | |
| - } | |
| - | |
| - @Override | |
| - public Reference<V> getReference() { | |
| - // Return null since hard references don't use Reference objects | |
| - return null; | |
| - } | |
| - } | |
| - | |
| - @Override | |
| - public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { | |
| - return computeIfAbsent(key, mappingFunction, null); | |
| - } | |
| - | |
| - /** | |
| - * Computes a value for the given key if it's not already present, using the specified reference type. | |
| - * <p> | |
| - * This method allows fine-grained control over the reference type used for individual entries, | |
| - * overriding the map's default reference type for this specific key-value pair. | |
| - * | |
| - * @param key the key whose associated value is to be returned or computed | |
| - * @param mappingFunction the function to compute a value | |
| - * @param referenceType the reference type to use for this entry (null uses map default) | |
| - * @return the current (existing or computed) value associated with the specified key | |
| - */ | |
| - public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction, ReferenceType referenceType) { | |
| - Objects.requireNonNull(key); | |
| - Objects.requireNonNull(mappingFunction); | |
| - | |
| - // Use the cache's configured key reference type, and the specified reference type for values (or fall back | |
| - // to default) | |
| - ReferenceType keyRefType = keyReferenceType; | |
| - ReferenceType valueRefType = referenceType != null ? referenceType : valueReferenceType; | |
| - | |
| - // Handle NONE reference type - always compute, never cache | |
| - if (keyRefType == ReferenceType.NONE || valueRefType == ReferenceType.NONE) { | |
| - return mappingFunction.apply(key); | |
| - } | |
| - | |
| - while (true) { | |
| - expungeStaleEntries(); | |
| - | |
| - RefConcurrentReference<K> keyRef = getKeyReference(key, keyRefType); | |
| - | |
| - // Try to get existing value | |
| - ComputeReference<V> valueRef = map.get(keyRef); | |
| - if (valueRef != null && !valueRef.computing) { | |
| - V value = valueRef.get(); | |
| - if (value != null) { | |
| - return value; | |
| - } | |
| - // Value was GC'd, remove it | |
| - map.remove(keyRef, valueRef); | |
| - } | |
| - | |
| - // Try to claim computation | |
| - ComputeReference<V> computingRef = getComputingReference(valueRefType); | |
| - valueRef = map.putIfAbsent(keyRef, computingRef); | |
| - | |
| - if (valueRef == null) { | |
| - // We claimed the computation | |
| - try { | |
| - V newValue = mappingFunction.apply(key); | |
| - if (newValue == null) { | |
| - map.remove(keyRef, computingRef); | |
| - return null; | |
| - } | |
| - | |
| - ComputeReference<V> newValueRef = getValueReference(newValue, valueRefType); | |
| - map.replace(keyRef, computingRef, newValueRef); | |
| - return newValue; | |
| - } catch (Throwable t) { | |
| - map.remove(keyRef, computingRef); | |
| - throw t; | |
| - } | |
| - } else if (!valueRef.computing) { | |
| - // Another thread has a value | |
| - V value = valueRef.get(); | |
| - if (value != null) { | |
| - return value; | |
| - } | |
| - // Value was GC'd | |
| - if (map.remove(keyRef, valueRef)) { | |
| - continue; | |
| - } | |
| - } | |
| - // Another thread is computing or the reference changed, try again | |
| - } | |
| - } | |
| - | |
| - /** | |
| - * Creates a computing reference using the specified reference type. | |
| - * If referenceType is null, uses the map's default reference type. | |
| - */ | |
| - private ComputeReference<V> getComputingReference(ReferenceType referenceType) { | |
| - return switch (referenceType) { | |
| - case SOFT -> SoftComputeReference.computing(valueQueue); | |
| - case WEAK -> WeakComputeReference.computing(valueQueue); | |
| - case HARD -> HardComputeReference.computing(valueQueue); | |
| - case NONE -> throw new IllegalArgumentException( | |
| - "NONE reference type should be handled before calling this method"); | |
| - }; | |
| - } | |
| - | |
| - /** | |
| - * Creates a value reference using the specified reference type. | |
| - * If referenceType is null, uses the map's value reference type. | |
| - */ | |
| - private ComputeReference<V> getValueReference(V value, ReferenceType referenceType) { | |
| - ReferenceType refType = referenceType != null ? referenceType : valueReferenceType; | |
| - return switch (refType) { | |
| - case SOFT -> new SoftComputeReference<>(value, valueQueue); | |
| - case WEAK -> new WeakComputeReference<>(value, valueQueue); | |
| - case HARD -> new HardComputeReference<>(value, valueQueue); | |
| - case NONE -> throw new IllegalArgumentException( | |
| - "NONE reference type should be handled before calling this method"); | |
| - }; | |
| - } | |
| - | |
| - /** | |
| - * Creates a key reference using the specified reference type. | |
| - * If referenceType is null, uses the map's key reference type. | |
| - */ | |
| - private RefConcurrentReference<K> getKeyReference(K key, ReferenceType referenceType) { | |
| - ReferenceType refType = referenceType != null ? referenceType : keyReferenceType; | |
| - return switch (refType) { | |
| - case SOFT -> new SoftRefConcurrentReference<>(key, keyQueue); | |
| - case WEAK -> new WeakRefConcurrentReference<>(key, keyQueue); | |
| - case HARD -> new HardRefConcurrentReference<>(key, keyQueue); | |
| - case NONE -> throw new IllegalArgumentException( | |
| - "NONE reference type should be handled before calling this method"); | |
| - }; | |
| - } | |
| - | |
| - private void expungeStaleEntries() { | |
| - // Remove entries where the key has been garbage collected | |
| - Reference<?> ref; | |
| - int keyEvictionCount = 0; | |
| - while ((ref = keyQueue.poll()) != null) { | |
| - keyEvictionCount++; | |
| - // System.err.println("DEBUG: Key reference polled from queue: " | |
| - // + ref.getClass().getSimpleName() + " (cache=" + name + ", keyRefType=" + keyReferenceType | |
| - // + ", valueRefType=" | |
| - // + valueReferenceType + ")"); | |
| - final Reference<?> finalRef = ref; | |
| - // Find and remove map entries where the key reference matches | |
| - // Hard references return null from getReference(), so they won't match | |
| - boolean removed = map.entrySet().removeIf(entry -> { | |
| - Reference<?> keyRef = entry.getKey().getReference(); | |
| - return keyRef != null && keyRef == finalRef; | |
| - }); | |
| - if (removed) { | |
| - keyEvictions.incrementAndGet(); | |
| - // Debug logging to understand what's happening | |
| - // System.err.println( | |
| - // "DEBUG: Key eviction detected - cache=" + name + ", keyReferenceType=" + keyReferenceType | |
| - // + ", valueReferenceType=" + valueReferenceType + ", finalRef=" | |
| - // + finalRef.getClass().getSimpleName() + ", mapSize=" + map.size()); | |
| - // Notify eviction listener | |
| - EvictionListener listener = evictionListener; | |
| - if (listener != null) { | |
| - listener.onKeyEviction(); | |
| - } | |
| - } | |
| - } | |
| - // Remove entries where the value has been garbage collected | |
| - int valueEvictionCount = 0; | |
| - while ((ref = valueQueue.poll()) != null) { | |
| - valueEvictionCount++; | |
| - // System.err.println("DEBUG: Value reference polled from queue: " | |
| - // + ref.getClass().getSimpleName() + " (cache=" + name + ", keyRefType=" + keyReferenceType | |
| - // + ", valueRefType=" | |
| - // + valueReferenceType + ")"); | |
| - final Reference<?> finalRef = ref; | |
| - // Find and remove map entries where the value reference matches | |
| - // Hard references return null from getReference(), so they won't match | |
| - boolean removed = map.entrySet().removeIf(entry -> { | |
| - Reference<?> valueRef = entry.getValue().getReference(); | |
| - return valueRef != null && valueRef == finalRef; | |
| - }); | |
| - if (removed) { | |
| - valueEvictions.incrementAndGet(); | |
| - // Debug logging to understand what's happening | |
| - // System.err.println( | |
| - // "DEBUG: Value eviction detected - cache=" + name + ", keyReferenceType=" + | |
| - // keyReferenceType | |
| - // + ", valueReferenceType=" + valueReferenceType + ", finalRef=" | |
| - // + finalRef.getClass().getSimpleName() + ", mapSize=" + map.size()); | |
| - // Notify eviction listener | |
| - EvictionListener listener = evictionListener; | |
| - if (listener != null) { | |
| - listener.onValueEviction(); | |
| - } | |
| - } | |
| - } | |
| - | |
| - // Debug logging for eviction activity (only if system property is set) | |
| - if ((keyEvictionCount > 0 || valueEvictionCount > 0) && Boolean.getBoolean("maven.cache.debug.evictions")) { | |
| - System.err.println("DEBUG: expungeStaleEntries() - cache=" + name + ", keyEvictions: " | |
| - + keyEvictionCount + ", valueEvictions: " + valueEvictionCount + ", mapSize: " + map.size()); | |
| - } | |
| - } | |
| - | |
| - @Override | |
| - public int size() { | |
| - expungeStaleEntries(); | |
| - return map.size(); | |
| - } | |
| - | |
| - @Override | |
| - public boolean isEmpty() { | |
| - expungeStaleEntries(); | |
| - return map.isEmpty(); | |
| - } | |
| - | |
| - @Override | |
| - public boolean containsKey(Object key) { | |
| - expungeStaleEntries(); | |
| - | |
| - // Handle NONE reference type - always compute, never cache | |
| - if (keyReferenceType == ReferenceType.NONE) { | |
| - return false; | |
| - } | |
| - | |
| - return map.containsKey(getKeyReference((K) key, null)); | |
| - } | |
| - | |
| - @Override | |
| - public boolean containsValue(Object value) { | |
| - expungeStaleEntries(); | |
| - | |
| - // Handle NONE reference type - always compute, never cache | |
| - if (valueReferenceType == ReferenceType.NONE) { | |
| - return false; | |
| - } | |
| - | |
| - for (ComputeReference<V> ref : map.values()) { | |
| - V v = ref.get(); | |
| - if (v != null && Objects.equals(v, value)) { | |
| - return true; | |
| - } | |
| - } | |
| - return false; | |
| - } | |
| - | |
| - @Override | |
| - public V get(Object key) { | |
| - expungeStaleEntries(); | |
| - | |
| - // Handle NONE reference type - always compute, never cache | |
| - if (keyReferenceType == ReferenceType.NONE) { | |
| - return null; | |
| - } | |
| - | |
| - ComputeReference<V> ref = map.get(getKeyReference((K) key, null)); | |
| - return ref != null ? ref.get() : null; | |
| - } | |
| - | |
| - @Override | |
| - public V put(K key, V value) { | |
| - Objects.requireNonNull(key); | |
| - Objects.requireNonNull(value); | |
| - expungeStaleEntries(); | |
| - | |
| - // Handle NONE reference type - always compute, never cache | |
| - if (keyReferenceType == ReferenceType.NONE || valueReferenceType == ReferenceType.NONE) { | |
| - return null; | |
| - } | |
| - | |
| - ComputeReference<V> oldValueRef = map.put(getKeyReference(key, null), getValueReference(value, null)); | |
| - | |
| - return oldValueRef != null ? oldValueRef.get() : null; | |
| - } | |
| - | |
| - @Override | |
| - public V remove(Object key) { | |
| - expungeStaleEntries(); | |
| - ComputeReference<V> valueRef = map.remove(getKeyReference((K) key, null)); | |
| - return valueRef != null ? valueRef.get() : null; | |
| - } | |
| - | |
| - public void removeIf(BiPredicate<K, V> filter) { | |
| - expungeStaleEntries(); | |
| - map.entrySet() | |
| - .removeIf(e -> filter.test(e.getKey().get(), e.getValue().get())); | |
| - } | |
| - | |
| - @Override | |
| - public void putAll(Map<? extends K, ? extends V> m) { | |
| - Objects.requireNonNull(m); | |
| - for (Entry<? extends K, ? extends V> e : m.entrySet()) { | |
| - put(e.getKey(), e.getValue()); | |
| - } | |
| - } | |
| - | |
| - @Override | |
| - public void clear() { | |
| - map.clear(); | |
| - expungeStaleEntries(); | |
| - } | |
| - | |
| - @Override | |
| - public Set<K> keySet() { | |
| - throw new UnsupportedOperationException("keySet not supported"); | |
| - } | |
| - | |
| - @Override | |
| - public Collection<V> values() { | |
| - throw new UnsupportedOperationException("values not supported"); | |
| - } | |
| - | |
| - @Override | |
| - public Set<Entry<K, V>> entrySet() { | |
| - throw new UnsupportedOperationException("entrySet not supported"); | |
| - } | |
| - | |
| - /** | |
| - * Returns the number of entries evicted due to key garbage collection. | |
| - */ | |
| - long getKeyEvictions() { | |
| - return keyEvictions.get(); | |
| - } | |
| - | |
| - /** | |
| - * Returns the number of entries evicted due to value garbage collection. | |
| - */ | |
| - long getValueEvictions() { | |
| - return valueEvictions.get(); | |
| - } | |
| - | |
| - /** | |
| - * Returns the total number of evictions (keys + values). | |
| - */ | |
| - long getTotalEvictions() { | |
| - return keyEvictions.get() + valueEvictions.get(); | |
| - } | |
| - | |
| - /** | |
| - * Returns the key reference type used by this cache. | |
| - */ | |
| - public ReferenceType getKeyReferenceType() { | |
| - return keyReferenceType; | |
| - } | |
| - | |
| - /** | |
| - * Returns the value reference type used by this cache. | |
| - */ | |
| - public ReferenceType getValueReferenceType() { | |
| - return valueReferenceType; | |
| - } | |
| - | |
| - /** | |
| - * Returns a string representation of the reference type combination. | |
| - */ | |
| - public String getReferenceTypeKey() { | |
| - return keyReferenceType + "/" + valueReferenceType; | |
| - } | |
| - | |
| - /** | |
| - * Returns the cache name for debugging purposes. | |
| - */ | |
| - public String getName() { | |
| - return name; | |
| - } | |
| - } | |
| -} | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheConfig.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheConfig.java | |
| deleted file mode 100644 | |
| index 34ae9ac4ec..0000000000 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheConfig.java | |
| +++ /dev/null | |
| @@ -1,93 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.impl.cache; | |
| - | |
| -import org.apache.maven.api.cache.CacheRetention; | |
| - | |
| -/** | |
| - * Configuration for cache behavior including scope and reference types. | |
| - * Supports separate reference types for keys and values to enable fine-grained | |
| - * control over eviction behavior and better cache miss analysis. | |
| - * | |
| - * @param scope the cache retention scope | |
| - * @param referenceType the reference type to use for cache entries (backward compatibility) | |
| - * @param keyReferenceType the reference type to use for keys (null means use referenceType) | |
| - * @param valueReferenceType the reference type to use for values (null means use referenceType) | |
| - */ | |
| -public record CacheConfig( | |
| - CacheRetention scope, | |
| - Cache.ReferenceType referenceType, | |
| - Cache.ReferenceType keyReferenceType, | |
| - Cache.ReferenceType valueReferenceType) { | |
| - | |
| - /** | |
| - * Backward compatibility constructor. | |
| - */ | |
| - public CacheConfig(CacheRetention scope, Cache.ReferenceType referenceType) { | |
| - this(scope, referenceType, null, null); | |
| - } | |
| - | |
| - /** | |
| - * Default cache configuration with REQUEST_SCOPED and SOFT reference type. | |
| - */ | |
| - public static final CacheConfig DEFAULT = new CacheConfig(CacheRetention.REQUEST_SCOPED, Cache.ReferenceType.SOFT); | |
| - | |
| - /** | |
| - * Creates a cache configuration with the specified scope and default SOFT reference type. | |
| - */ | |
| - public static CacheConfig withScope(CacheRetention scope) { | |
| - return new CacheConfig(scope, Cache.ReferenceType.SOFT); | |
| - } | |
| - | |
| - /** | |
| - * Creates a cache configuration with the specified reference type and default REQUEST_SCOPED scope. | |
| - */ | |
| - public static CacheConfig withReferenceType(Cache.ReferenceType referenceType) { | |
| - return new CacheConfig(CacheRetention.REQUEST_SCOPED, referenceType); | |
| - } | |
| - | |
| - /** | |
| - * Creates a cache configuration with separate key and value reference types. | |
| - */ | |
| - public static CacheConfig withKeyValueReferenceTypes( | |
| - CacheRetention scope, Cache.ReferenceType keyReferenceType, Cache.ReferenceType valueReferenceType) { | |
| - return new CacheConfig(scope, keyReferenceType, keyReferenceType, valueReferenceType); | |
| - } | |
| - | |
| - /** | |
| - * Returns the effective key reference type. | |
| - */ | |
| - public Cache.ReferenceType getEffectiveKeyReferenceType() { | |
| - return keyReferenceType != null ? keyReferenceType : referenceType; | |
| - } | |
| - | |
| - /** | |
| - * Returns the effective value reference type. | |
| - */ | |
| - public Cache.ReferenceType getEffectiveValueReferenceType() { | |
| - return valueReferenceType != null ? valueReferenceType : referenceType; | |
| - } | |
| - | |
| - /** | |
| - * Returns true if this configuration uses separate reference types for keys and values. | |
| - */ | |
| - public boolean hasSeparateKeyValueReferenceTypes() { | |
| - return keyReferenceType != null || valueReferenceType != null; | |
| - } | |
| -} | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheConfigurationResolver.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheConfigurationResolver.java | |
| deleted file mode 100644 | |
| index d0b162ba0f..0000000000 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheConfigurationResolver.java | |
| +++ /dev/null | |
| @@ -1,185 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.impl.cache; | |
| - | |
| -import java.util.List; | |
| -import java.util.concurrent.ConcurrentHashMap; | |
| -import java.util.concurrent.ConcurrentMap; | |
| - | |
| -import org.apache.maven.api.Constants; | |
| -import org.apache.maven.api.Session; | |
| -import org.apache.maven.api.cache.CacheMetadata; | |
| -import org.apache.maven.api.cache.CacheRetention; | |
| -import org.apache.maven.api.services.Request; | |
| -import org.slf4j.Logger; | |
| -import org.slf4j.LoggerFactory; | |
| - | |
| -/** | |
| - * Resolves cache configuration for requests based on user-defined selectors. | |
| - */ | |
| -public class CacheConfigurationResolver { | |
| - private static final Logger LOGGER = LoggerFactory.getLogger(CacheConfigurationResolver.class); | |
| - | |
| - /** | |
| - * Cache for parsed selectors per session to avoid re-parsing. | |
| - */ | |
| - private static final ConcurrentMap<String, List<CacheSelector>> SELECTOR_CACHE = new ConcurrentHashMap<>(); | |
| - | |
| - /** | |
| - * Resolves cache configuration for the given request and session. | |
| - * | |
| - * @param req the request to resolve configuration for | |
| - * @param session the session containing user properties | |
| - * @return the resolved cache configuration | |
| - */ | |
| - public static CacheConfig resolveConfig(Request<?> req, Session session) { | |
| - // First check if request implements CacheMetadata for backward compatibility | |
| - CacheRetention legacyRetention = null; | |
| - if (req instanceof CacheMetadata metadata) { | |
| - legacyRetention = metadata.getCacheRetention(); | |
| - } | |
| - | |
| - // Check for key reference type configuration | |
| - Cache.ReferenceType keyRefType = null; | |
| - String keyRefsString = session.getUserProperties().get(Constants.MAVEN_CACHE_KEY_REFS); | |
| - if (keyRefsString != null && !keyRefsString.trim().isEmpty()) { | |
| - try { | |
| - keyRefType = Cache.ReferenceType.valueOf(keyRefsString.trim().toUpperCase()); | |
| - } catch (IllegalArgumentException e) { | |
| - LOGGER.warn("Invalid key reference types '{}', using defaults", keyRefsString); | |
| - } | |
| - } | |
| - | |
| - // Check for value reference type configuration | |
| - Cache.ReferenceType valueRefType = null; | |
| - String valueRefsString = session.getUserProperties().get(Constants.MAVEN_CACHE_VALUE_REFS); | |
| - if (valueRefsString != null && !valueRefsString.trim().isEmpty()) { | |
| - try { | |
| - valueRefType = | |
| - Cache.ReferenceType.valueOf(valueRefsString.trim().toUpperCase()); | |
| - } catch (IllegalArgumentException e) { | |
| - LOGGER.warn("Invalid value reference types '{}', using defaults", valueRefsString); | |
| - } | |
| - } | |
| - | |
| - // Get user-defined configuration | |
| - String configString = session.getUserProperties().get(Constants.MAVEN_CACHE_CONFIG_PROPERTY); | |
| - if (configString == null || configString.trim().isEmpty()) { | |
| - // No user configuration, use legacy behavior or defaults | |
| - if (legacyRetention != null) { | |
| - CacheConfig config = new CacheConfig( | |
| - legacyRetention, getDefaultReferenceType(legacyRetention), keyRefType, valueRefType); | |
| - return config; | |
| - } | |
| - if (keyRefType != null && valueRefType != null) { | |
| - return new CacheConfig( | |
| - CacheConfig.DEFAULT.scope(), CacheConfig.DEFAULT.referenceType(), keyRefType, valueRefType); | |
| - } | |
| - return CacheConfig.DEFAULT; | |
| - } | |
| - | |
| - // Parse and cache selectors | |
| - List<CacheSelector> selectors = SELECTOR_CACHE.computeIfAbsent(configString, CacheSelectorParser::parse); | |
| - | |
| - // Find all matching selectors and merge them (most specific first) | |
| - PartialCacheConfig mergedConfig = null; | |
| - for (CacheSelector selector : selectors) { | |
| - if (selector.matches(req)) { | |
| - if (mergedConfig == null) { | |
| - mergedConfig = selector.config(); | |
| - LOGGER.debug( | |
| - "Cache config for {}: matched selector '{}' with config {}", | |
| - req.getClass().getSimpleName(), | |
| - selector, | |
| - selector.config()); | |
| - } else { | |
| - PartialCacheConfig previousConfig = mergedConfig; | |
| - mergedConfig = mergedConfig.mergeWith(selector.config()); | |
| - LOGGER.debug( | |
| - "Cache config for {}: merged selector '{}' with previous config {} -> {}", | |
| - req.getClass().getSimpleName(), | |
| - selector, | |
| - previousConfig, | |
| - mergedConfig); | |
| - } | |
| - | |
| - // If we have a complete configuration, we can stop | |
| - if (mergedConfig.isComplete()) { | |
| - break; | |
| - } | |
| - } | |
| - } | |
| - | |
| - // Convert merged partial config to complete config | |
| - if (mergedConfig != null && !mergedConfig.isEmpty()) { | |
| - CacheConfig finalConfig = mergedConfig.toComplete(); | |
| - // Apply key/value reference types if specified | |
| - if (keyRefType != null && valueRefType != null) { | |
| - finalConfig = | |
| - new CacheConfig(finalConfig.scope(), finalConfig.referenceType(), keyRefType, valueRefType); | |
| - } | |
| - LOGGER.debug("Final cache config for {}: {}", req.getClass().getSimpleName(), finalConfig); | |
| - return finalConfig; | |
| - } | |
| - | |
| - // No selector matched, use legacy behavior or defaults | |
| - if (legacyRetention != null) { | |
| - CacheConfig config = new CacheConfig( | |
| - legacyRetention, getDefaultReferenceType(legacyRetention), keyRefType, valueRefType); | |
| - LOGGER.debug( | |
| - "Cache config for {}: {} (legacy CacheMetadata)", | |
| - req.getClass().getSimpleName(), | |
| - config); | |
| - return config; | |
| - } | |
| - | |
| - if (keyRefType != null && valueRefType != null) { | |
| - CacheConfig config = new CacheConfig( | |
| - CacheConfig.DEFAULT.scope(), CacheConfig.DEFAULT.referenceType(), keyRefType, valueRefType); | |
| - LOGGER.debug( | |
| - "Cache config for {}: {} (with key/value refs)", | |
| - req.getClass().getSimpleName(), | |
| - config); | |
| - return config; | |
| - } | |
| - | |
| - LOGGER.debug("Cache config for {}: {} (default)", req.getClass().getSimpleName(), CacheConfig.DEFAULT); | |
| - return CacheConfig.DEFAULT; | |
| - } | |
| - | |
| - /** | |
| - * Gets the default reference type for a given cache retention. | |
| - * This maintains backward compatibility with the original hardcoded behavior. | |
| - */ | |
| - private static Cache.ReferenceType getDefaultReferenceType(CacheRetention retention) { | |
| - return switch (retention) { | |
| - case SESSION_SCOPED -> Cache.ReferenceType.SOFT; | |
| - case REQUEST_SCOPED -> Cache.ReferenceType.SOFT; // Changed from HARD to SOFT for consistency | |
| - case PERSISTENT -> Cache.ReferenceType.HARD; | |
| - case DISABLED -> Cache.ReferenceType.NONE; | |
| - }; | |
| - } | |
| - | |
| - /** | |
| - * Clears the selector cache. Useful for testing. | |
| - */ | |
| - public static void clearCache() { | |
| - SELECTOR_CACHE.clear(); | |
| - } | |
| -} | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheSelector.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheSelector.java | |
| deleted file mode 100644 | |
| index ecfbb16601..0000000000 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheSelector.java | |
| +++ /dev/null | |
| @@ -1,160 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.impl.cache; | |
| - | |
| -import java.util.Objects; | |
| - | |
| -import org.apache.maven.api.services.Request; | |
| -import org.apache.maven.api.services.RequestTrace; | |
| - | |
| -/** | |
| - * A cache selector that matches requests based on their type and optional parent request type. | |
| - * | |
| - * Supports CSS-like selectors: | |
| - * - "RequestType" matches any request of that type | |
| - * - "ParentType RequestType" matches RequestType with ParentType as parent | |
| - * - "ParentType *" matches any request with ParentType as parent | |
| - * - "* RequestType" matches RequestType with any parent (equivalent to just "RequestType") | |
| - * | |
| - * @param parentRequestType | |
| - * @param requestType | |
| - * @param config | |
| - */ | |
| -public record CacheSelector(String parentRequestType, String requestType, PartialCacheConfig config) { | |
| - | |
| - public CacheSelector { | |
| - Objects.requireNonNull(requestType, "requestType cannot be null"); | |
| - Objects.requireNonNull(config, "config cannot be null"); | |
| - } | |
| - | |
| - /** | |
| - * Creates a selector that matches any request of the specified type. | |
| - */ | |
| - public static CacheSelector forRequestType(String requestType, PartialCacheConfig config) { | |
| - return new CacheSelector(null, requestType, config); | |
| - } | |
| - | |
| - /** | |
| - * Creates a selector that matches requests with a specific parent type. | |
| - */ | |
| - public static CacheSelector forParentAndRequestType( | |
| - String parentRequestType, String requestType, PartialCacheConfig config) { | |
| - return new CacheSelector(parentRequestType, requestType, config); | |
| - } | |
| - | |
| - /** | |
| - * Checks if this selector matches the given request. | |
| - * | |
| - * @param req the request to match | |
| - * @return true if this selector matches the request | |
| - */ | |
| - public boolean matches(Request<?> req) { | |
| - // Check if request type matches any of the implemented interfaces | |
| - if (!"*".equals(requestType) && !matchesAnyInterface(req.getClass(), requestType)) { | |
| - return false; | |
| - } | |
| - | |
| - // If no parent type specified, it matches | |
| - if (parentRequestType == null) { | |
| - return true; | |
| - } | |
| - | |
| - // Check parent request type | |
| - if (!matchesParentRequestType(req, parentRequestType)) { | |
| - return false; | |
| - } | |
| - | |
| - return true; | |
| - } | |
| - | |
| - /** | |
| - * Checks if a class or any of its implemented interfaces matches the given type name. | |
| - * | |
| - * @param clazz the class to check | |
| - * @param typeName the type name to match against | |
| - * @return true if the class or any of its interfaces matches the type name | |
| - */ | |
| - private boolean matchesAnyInterface(Class<?> clazz, String typeName) { | |
| - // Check the class itself first | |
| - if (typeName.equals(getShortClassName(clazz))) { | |
| - return true; | |
| - } | |
| - | |
| - // Check all implemented interfaces | |
| - for (Class<?> iface : clazz.getInterfaces()) { | |
| - if (typeName.equals(getShortClassName(iface))) { | |
| - return true; | |
| - } | |
| - // Recursively check parent interfaces | |
| - if (matchesAnyInterface(iface, typeName)) { | |
| - return true; | |
| - } | |
| - } | |
| - | |
| - // Check superclass if it exists | |
| - Class<?> superClass = clazz.getSuperclass(); | |
| - if (superClass != null && superClass != Object.class) { | |
| - return matchesAnyInterface(superClass, typeName); | |
| - } | |
| - | |
| - return false; | |
| - } | |
| - | |
| - /** | |
| - * Checks if the parent request type matches the given selector pattern. | |
| - * | |
| - * @param req the request to check | |
| - * @param parentRequestType the parent request type pattern to match | |
| - * @return true if the parent matches the pattern | |
| - */ | |
| - private boolean matchesParentRequestType(Request<?> req, String parentRequestType) { | |
| - if ("*".equals(parentRequestType)) { | |
| - return true; | |
| - } | |
| - | |
| - RequestTrace trace = req.getTrace(); | |
| - if (trace == null || trace.parent() == null) { | |
| - return false; | |
| - } | |
| - | |
| - Object parentData = trace.parent().data(); | |
| - if (!(parentData instanceof Request<?> parentReq)) { | |
| - return false; | |
| - } | |
| - | |
| - // Check if parent request matches any interface with the given name | |
| - return matchesAnyInterface(parentReq.getClass(), parentRequestType); | |
| - } | |
| - | |
| - /** | |
| - * Gets the short class name (without package) of a class. | |
| - */ | |
| - private String getShortClassName(Class<?> clazz) { | |
| - String name = clazz.getSimpleName(); | |
| - return name.isEmpty() ? clazz.getName() : name; | |
| - } | |
| - | |
| - @Override | |
| - public String toString() { | |
| - if (parentRequestType == null) { | |
| - return requestType; | |
| - } | |
| - return parentRequestType + " " + requestType; | |
| - } | |
| -} | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheSelectorParser.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheSelectorParser.java | |
| deleted file mode 100644 | |
| index 143a8b694e..0000000000 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheSelectorParser.java | |
| +++ /dev/null | |
| @@ -1,193 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.impl.cache; | |
| - | |
| -import java.util.ArrayList; | |
| -import java.util.List; | |
| -import java.util.Locale; | |
| -import java.util.regex.Matcher; | |
| -import java.util.regex.Pattern; | |
| - | |
| -import org.apache.maven.api.cache.CacheRetention; | |
| -import org.slf4j.Logger; | |
| -import org.slf4j.LoggerFactory; | |
| - | |
| -/** | |
| - * Parser for cache selector configuration strings. | |
| - * | |
| - * Supports syntax like: | |
| - * <pre> | |
| - * ArtifactResolutionRequest { scope: session, ref: soft } | |
| - * ModelBuildRequest { scope: request, ref: soft } | |
| - * ModelBuilderRequest VersionRangeRequest { ref: hard } | |
| - * ModelBuildRequest * { ref: hard } | |
| - * VersionRangeRequest { scope: session } | |
| - * * { ref: weak } | |
| - * </pre> | |
| - */ | |
| -public class CacheSelectorParser { | |
| - private static final Logger LOGGER = LoggerFactory.getLogger(CacheSelectorParser.class); | |
| - | |
| - // Pattern to match selector rules: "[ParentType] RequestType { properties }" | |
| - private static final Pattern RULE_PATTERN = | |
| - Pattern.compile("([\\w*]+)(?:\\s+([\\w*]+))?\\s*\\{([^}]+)\\}", Pattern.MULTILINE); | |
| - | |
| - // Pattern to match properties within braces: "key: value" | |
| - private static final Pattern PROPERTY_PATTERN = Pattern.compile("(\\w+)\\s*:\\s*([\\w]+)"); | |
| - | |
| - /** | |
| - * Parses a cache configuration string into a list of cache selectors. | |
| - * | |
| - * @param configString the configuration string to parse | |
| - * @return list of parsed cache selectors, ordered by specificity (most specific first) | |
| - */ | |
| - public static List<CacheSelector> parse(String configString) { | |
| - List<CacheSelector> selectors = new ArrayList<>(); | |
| - | |
| - if (configString == null || configString.trim().isEmpty()) { | |
| - return selectors; | |
| - } | |
| - | |
| - Matcher ruleMatcher = RULE_PATTERN.matcher(configString); | |
| - while (ruleMatcher.find()) { | |
| - CacheSelector selector = parseRule(ruleMatcher); | |
| - selectors.add(selector); | |
| - } | |
| - | |
| - // Sort by specificity (most specific first) | |
| - selectors.sort((a, b) -> compareSpecificity(b, a)); | |
| - | |
| - return selectors; | |
| - } | |
| - | |
| - /** | |
| - * Parses a single rule from a regex matcher. | |
| - */ | |
| - private static CacheSelector parseRule(Matcher ruleMatcher) { | |
| - String firstType = ruleMatcher.group(1); | |
| - String secondType = ruleMatcher.group(2); | |
| - String properties = ruleMatcher.group(3); | |
| - | |
| - // Determine parent and request types | |
| - String parentType = null; | |
| - String requestType = firstType; | |
| - | |
| - if (secondType != null) { | |
| - parentType = firstType; | |
| - requestType = secondType; | |
| - } | |
| - | |
| - // Parse properties | |
| - PartialCacheConfig config = parseProperties(properties); | |
| - return new CacheSelector(parentType, requestType, config); | |
| - } | |
| - | |
| - /** | |
| - * Parses properties string into a PartialCacheConfig. | |
| - */ | |
| - private static PartialCacheConfig parseProperties(String properties) { | |
| - CacheRetention scope = null; | |
| - Cache.ReferenceType referenceType = null; | |
| - | |
| - Matcher propMatcher = PROPERTY_PATTERN.matcher(properties); | |
| - while (propMatcher.find()) { | |
| - String key = propMatcher.group(1); | |
| - String value = propMatcher.group(2); | |
| - | |
| - switch (key.toLowerCase(Locale.ENGLISH)) { | |
| - case "scope": | |
| - scope = parseScope(value); | |
| - break; | |
| - case "ref": | |
| - case "reference": | |
| - referenceType = parseReferenceType(value); | |
| - break; | |
| - default: | |
| - LOGGER.warn("Unknown cache configuration property: {}", key); | |
| - } | |
| - } | |
| - | |
| - // Return partial configuration (null values are allowed) | |
| - return new PartialCacheConfig(scope, referenceType); | |
| - } | |
| - | |
| - /** | |
| - * Parses a scope string into CacheRetention. | |
| - */ | |
| - private static CacheRetention parseScope(String value) { | |
| - return switch (value.toLowerCase(Locale.ENGLISH)) { | |
| - case "session" -> CacheRetention.SESSION_SCOPED; | |
| - case "request" -> CacheRetention.REQUEST_SCOPED; | |
| - case "persistent" -> CacheRetention.PERSISTENT; | |
| - case "disabled", "none" -> CacheRetention.DISABLED; | |
| - default -> { | |
| - LOGGER.warn("Unknown cache scope: {}, using default REQUEST_SCOPED", value); | |
| - yield CacheRetention.REQUEST_SCOPED; | |
| - } | |
| - }; | |
| - } | |
| - | |
| - /** | |
| - * Parses a reference type string into Cache.ReferenceType. | |
| - */ | |
| - private static Cache.ReferenceType parseReferenceType(String value) { | |
| - return switch (value.toLowerCase(Locale.ENGLISH)) { | |
| - case "soft" -> Cache.ReferenceType.SOFT; | |
| - case "hard" -> Cache.ReferenceType.HARD; | |
| - case "weak" -> Cache.ReferenceType.WEAK; | |
| - case "none" -> Cache.ReferenceType.NONE; | |
| - default -> { | |
| - LOGGER.warn("Unknown reference type: {}, using default SOFT", value); | |
| - yield Cache.ReferenceType.SOFT; | |
| - } | |
| - }; | |
| - } | |
| - | |
| - /** | |
| - * Compares specificity of two selectors. More specific selectors should be checked first. | |
| - * Specificity order: parent + request > request only > wildcard | |
| - */ | |
| - private static int compareSpecificity(CacheSelector a, CacheSelector b) { | |
| - int aScore = getSpecificityScore(a); | |
| - int bScore = getSpecificityScore(b); | |
| - return Integer.compare(aScore, bScore); | |
| - } | |
| - | |
| - private static int getSpecificityScore(CacheSelector selector) { | |
| - int score = 0; | |
| - | |
| - // Parent type specificity | |
| - if (selector.parentRequestType() != null) { | |
| - if (!"*".equals(selector.parentRequestType())) { | |
| - score += 100; // Specific parent type | |
| - } else { | |
| - score += 50; // Wildcard parent type | |
| - } | |
| - } | |
| - | |
| - // Request type specificity | |
| - if (!"*".equals(selector.requestType())) { | |
| - score += 10; // Specific request type | |
| - } else { | |
| - score += 1; // Wildcard request type | |
| - } | |
| - | |
| - return score; | |
| - } | |
| -} | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheStatistics.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheStatistics.java | |
| deleted file mode 100644 | |
| index d78536be9c..0000000000 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/CacheStatistics.java | |
| +++ /dev/null | |
| @@ -1,416 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.impl.cache; | |
| - | |
| -import java.util.Map; | |
| -import java.util.concurrent.ConcurrentHashMap; | |
| -import java.util.concurrent.atomic.AtomicLong; | |
| -import java.util.function.Supplier; | |
| - | |
| -import org.apache.maven.api.cache.CacheRetention; | |
| - | |
| -/** | |
| - * Cache statistics that tracks detailed metrics | |
| - * about cache performance and usage patterns. | |
| - * <p> | |
| - * This implementation integrates with the improved cache architecture and | |
| - * provides thread-safe statistics tracking with minimal performance overhead. | |
| - * </p> | |
| - */ | |
| -public class CacheStatistics { | |
| - | |
| - private final AtomicLong totalRequests = new AtomicLong(); | |
| - private final AtomicLong cacheHits = new AtomicLong(); | |
| - private final AtomicLong cacheMisses = new AtomicLong(); | |
| - private final AtomicLong cachedExceptions = new AtomicLong(); | |
| - | |
| - // Enhanced eviction tracking | |
| - private final AtomicLong keyEvictions = new AtomicLong(); | |
| - private final AtomicLong valueEvictions = new AtomicLong(); | |
| - private final AtomicLong totalEvictions = new AtomicLong(); | |
| - | |
| - private final Map<String, RequestTypeStatistics> requestTypeStats = new ConcurrentHashMap<>(); | |
| - private final Map<CacheRetention, RetentionStatistics> retentionStats = new ConcurrentHashMap<>(); | |
| - private final Map<CacheRetention, Supplier<Long>> cacheSizeSuppliers = new ConcurrentHashMap<>(); | |
| - | |
| - // Reference type statistics | |
| - private final Map<String, ReferenceTypeStatistics> referenceTypeStats = new ConcurrentHashMap<>(); | |
| - | |
| - public long getTotalRequests() { | |
| - return totalRequests.get(); | |
| - } | |
| - | |
| - public long getCacheHits() { | |
| - return cacheHits.get(); | |
| - } | |
| - | |
| - public long getCacheMisses() { | |
| - return cacheMisses.get(); | |
| - } | |
| - | |
| - public double getHitRatio() { | |
| - long total = getTotalRequests(); | |
| - return total == 0 ? 0.0 : (getCacheHits() * 100.0) / total; | |
| - } | |
| - | |
| - public double getMissRatio() { | |
| - long total = getTotalRequests(); | |
| - return total == 0 ? 0.0 : (getCacheMisses() * 100.0) / total; | |
| - } | |
| - | |
| - public Map<String, RequestTypeStatistics> getRequestTypeStatistics() { | |
| - return Map.copyOf(requestTypeStats); | |
| - } | |
| - | |
| - public Map<CacheRetention, RetentionStatistics> getRetentionStatistics() { | |
| - return Map.copyOf(retentionStats); | |
| - } | |
| - | |
| - public Map<String, ReferenceTypeStatistics> getReferenceTypeStatistics() { | |
| - return Map.copyOf(referenceTypeStats); | |
| - } | |
| - | |
| - public Map<CacheRetention, Long> getCacheSizes() { | |
| - Map<CacheRetention, Long> sizes = new ConcurrentHashMap<>(); | |
| - cacheSizeSuppliers.forEach((retention, supplier) -> sizes.put(retention, supplier.get())); | |
| - return sizes; | |
| - } | |
| - | |
| - public long getCachedExceptions() { | |
| - return cachedExceptions.get(); | |
| - } | |
| - | |
| - /** | |
| - * Returns the total number of key evictions across all caches. | |
| - */ | |
| - public long getKeyEvictions() { | |
| - return keyEvictions.get(); | |
| - } | |
| - | |
| - /** | |
| - * Returns the total number of value evictions across all caches. | |
| - */ | |
| - public long getValueEvictions() { | |
| - return valueEvictions.get(); | |
| - } | |
| - | |
| - /** | |
| - * Returns the total number of evictions (keys + values). | |
| - */ | |
| - public long getTotalEvictions() { | |
| - return totalEvictions.get(); | |
| - } | |
| - | |
| - /** | |
| - * Returns the ratio of key evictions to total evictions. | |
| - */ | |
| - public double getKeyEvictionRatio() { | |
| - long total = getTotalEvictions(); | |
| - return total == 0 ? 0.0 : (getKeyEvictions() * 100.0) / total; | |
| - } | |
| - | |
| - /** | |
| - * Returns the ratio of value evictions to total evictions. | |
| - */ | |
| - public double getValueEvictionRatio() { | |
| - long total = getTotalEvictions(); | |
| - return total == 0 ? 0.0 : (getValueEvictions() * 100.0) / total; | |
| - } | |
| - | |
| - /** | |
| - * Records a cache hit for the given request type and retention policy. | |
| - */ | |
| - public void recordHit(String requestType, CacheRetention retention) { | |
| - totalRequests.incrementAndGet(); | |
| - cacheHits.incrementAndGet(); | |
| - | |
| - requestTypeStats | |
| - .computeIfAbsent(requestType, RequestTypeStatistics::new) | |
| - .recordHit(); | |
| - retentionStats.computeIfAbsent(retention, RetentionStatistics::new).recordHit(); | |
| - } | |
| - | |
| - /** | |
| - * Records a cache miss for the given request type and retention policy. | |
| - */ | |
| - public void recordMiss(String requestType, CacheRetention retention) { | |
| - totalRequests.incrementAndGet(); | |
| - cacheMisses.incrementAndGet(); | |
| - | |
| - requestTypeStats | |
| - .computeIfAbsent(requestType, RequestTypeStatistics::new) | |
| - .recordMiss(); | |
| - retentionStats.computeIfAbsent(retention, RetentionStatistics::new).recordMiss(); | |
| - } | |
| - | |
| - /** | |
| - * Records a cached exception. | |
| - */ | |
| - public void recordCachedException() { | |
| - cachedExceptions.incrementAndGet(); | |
| - } | |
| - | |
| - /** | |
| - * Records a key eviction for the specified retention policy. | |
| - */ | |
| - public void recordKeyEviction(CacheRetention retention) { | |
| - keyEvictions.incrementAndGet(); | |
| - totalEvictions.incrementAndGet(); | |
| - retentionStats.computeIfAbsent(retention, RetentionStatistics::new).recordKeyEviction(); | |
| - } | |
| - | |
| - /** | |
| - * Records a value eviction for the specified retention policy. | |
| - */ | |
| - public void recordValueEviction(CacheRetention retention) { | |
| - valueEvictions.incrementAndGet(); | |
| - totalEvictions.incrementAndGet(); | |
| - retentionStats.computeIfAbsent(retention, RetentionStatistics::new).recordValueEviction(); | |
| - } | |
| - | |
| - /** | |
| - * Registers a cache size supplier for the given retention policy. | |
| - */ | |
| - public void registerCacheSizeSupplier(CacheRetention retention, Supplier<Long> sizeSupplier) { | |
| - cacheSizeSuppliers.put(retention, sizeSupplier); | |
| - retentionStats.computeIfAbsent(retention, RetentionStatistics::new).setSizeSupplier(sizeSupplier); | |
| - } | |
| - | |
| - /** | |
| - * Returns eviction statistics by retention policy. | |
| - */ | |
| - public Map<CacheRetention, Long> getKeyEvictionsByRetention() { | |
| - Map<CacheRetention, Long> evictions = new ConcurrentHashMap<>(); | |
| - retentionStats.forEach((retention, stats) -> evictions.put(retention, stats.getKeyEvictions())); | |
| - return evictions; | |
| - } | |
| - | |
| - /** | |
| - * Returns value eviction statistics by retention policy. | |
| - */ | |
| - public Map<CacheRetention, Long> getValueEvictionsByRetention() { | |
| - Map<CacheRetention, Long> evictions = new ConcurrentHashMap<>(); | |
| - retentionStats.forEach((retention, stats) -> evictions.put(retention, stats.getValueEvictions())); | |
| - return evictions; | |
| - } | |
| - | |
| - /** | |
| - * Records cache creation with specific reference types. | |
| - */ | |
| - public void recordCacheCreation(String keyRefType, String valueRefType, CacheRetention retention) { | |
| - String refTypeKey = keyRefType + "/" + valueRefType; | |
| - referenceTypeStats | |
| - .computeIfAbsent(refTypeKey, ReferenceTypeStatistics::new) | |
| - .recordCacheCreation(retention); | |
| - } | |
| - | |
| - /** | |
| - * Records cache access for specific reference types. | |
| - */ | |
| - public void recordCacheAccess(String keyRefType, String valueRefType, boolean hit) { | |
| - String refTypeKey = keyRefType + "/" + valueRefType; | |
| - ReferenceTypeStatistics stats = referenceTypeStats.computeIfAbsent(refTypeKey, ReferenceTypeStatistics::new); | |
| - if (hit) { | |
| - stats.recordHit(); | |
| - } else { | |
| - stats.recordMiss(); | |
| - } | |
| - } | |
| - | |
| - /** | |
| - * Default implementation of request type statistics. | |
| - */ | |
| - public static class RequestTypeStatistics { | |
| - private final String requestType; | |
| - private final AtomicLong hits = new AtomicLong(); | |
| - private final AtomicLong misses = new AtomicLong(); | |
| - | |
| - RequestTypeStatistics(String requestType) { | |
| - this.requestType = requestType; | |
| - } | |
| - | |
| - public String getRequestType() { | |
| - return requestType; | |
| - } | |
| - | |
| - public long getHits() { | |
| - return hits.get(); | |
| - } | |
| - | |
| - public long getMisses() { | |
| - return misses.get(); | |
| - } | |
| - | |
| - public long getTotal() { | |
| - return getHits() + getMisses(); | |
| - } | |
| - | |
| - public double getHitRatio() { | |
| - long total = getTotal(); | |
| - return total == 0 ? 0.0 : (getHits() * 100.0) / total; | |
| - } | |
| - | |
| - void recordHit() { | |
| - hits.incrementAndGet(); | |
| - } | |
| - | |
| - void recordMiss() { | |
| - misses.incrementAndGet(); | |
| - } | |
| - } | |
| - | |
| - /** | |
| - * Default implementation of retention statistics. | |
| - */ | |
| - public static class RetentionStatistics { | |
| - private final CacheRetention retention; | |
| - private final AtomicLong hits = new AtomicLong(); | |
| - private final AtomicLong misses = new AtomicLong(); | |
| - private final AtomicLong keyEvictions = new AtomicLong(); | |
| - private final AtomicLong valueEvictions = new AtomicLong(); | |
| - private volatile Supplier<Long> sizeSupplier = () -> 0L; | |
| - | |
| - RetentionStatistics(CacheRetention retention) { | |
| - this.retention = retention; | |
| - } | |
| - | |
| - public CacheRetention getRetention() { | |
| - return retention; | |
| - } | |
| - | |
| - public long getHits() { | |
| - return hits.get(); | |
| - } | |
| - | |
| - public long getMisses() { | |
| - return misses.get(); | |
| - } | |
| - | |
| - public long getTotal() { | |
| - return getHits() + getMisses(); | |
| - } | |
| - | |
| - public double getHitRatio() { | |
| - long total = getTotal(); | |
| - return total == 0 ? 0.0 : (getHits() * 100.0) / total; | |
| - } | |
| - | |
| - public long getCurrentSize() { | |
| - return sizeSupplier.get(); | |
| - } | |
| - | |
| - public long getKeyEvictions() { | |
| - return keyEvictions.get(); | |
| - } | |
| - | |
| - public long getValueEvictions() { | |
| - return valueEvictions.get(); | |
| - } | |
| - | |
| - public long getTotalEvictions() { | |
| - return getKeyEvictions() + getValueEvictions(); | |
| - } | |
| - | |
| - public double getKeyEvictionRatio() { | |
| - long total = getTotalEvictions(); | |
| - return total == 0 ? 0.0 : (getKeyEvictions() * 100.0) / total; | |
| - } | |
| - | |
| - void recordHit() { | |
| - hits.incrementAndGet(); | |
| - } | |
| - | |
| - void recordMiss() { | |
| - misses.incrementAndGet(); | |
| - } | |
| - | |
| - void recordKeyEviction() { | |
| - keyEvictions.incrementAndGet(); | |
| - } | |
| - | |
| - void recordValueEviction() { | |
| - valueEvictions.incrementAndGet(); | |
| - } | |
| - | |
| - void setSizeSupplier(Supplier<Long> sizeSupplier) { | |
| - this.sizeSupplier = sizeSupplier; | |
| - } | |
| - } | |
| - | |
| - /** | |
| - * Statistics for specific reference type combinations. | |
| - */ | |
| - public static class ReferenceTypeStatistics { | |
| - private final String referenceTypeKey; | |
| - private final AtomicLong hits = new AtomicLong(); | |
| - private final AtomicLong misses = new AtomicLong(); | |
| - private final AtomicLong cacheCreations = new AtomicLong(); | |
| - private final Map<CacheRetention, AtomicLong> creationsByRetention = new ConcurrentHashMap<>(); | |
| - | |
| - ReferenceTypeStatistics(String referenceTypeKey) { | |
| - this.referenceTypeKey = referenceTypeKey; | |
| - } | |
| - | |
| - public String getReferenceTypeKey() { | |
| - return referenceTypeKey; | |
| - } | |
| - | |
| - public long getHits() { | |
| - return hits.get(); | |
| - } | |
| - | |
| - public long getMisses() { | |
| - return misses.get(); | |
| - } | |
| - | |
| - public long getTotal() { | |
| - return getHits() + getMisses(); | |
| - } | |
| - | |
| - public double getHitRatio() { | |
| - long total = getTotal(); | |
| - return total == 0 ? 0.0 : (getHits() * 100.0) / total; | |
| - } | |
| - | |
| - public long getCacheCreations() { | |
| - return cacheCreations.get(); | |
| - } | |
| - | |
| - public Map<CacheRetention, Long> getCreationsByRetention() { | |
| - Map<CacheRetention, Long> result = new ConcurrentHashMap<>(); | |
| - creationsByRetention.forEach((retention, count) -> result.put(retention, count.get())); | |
| - return result; | |
| - } | |
| - | |
| - void recordHit() { | |
| - hits.incrementAndGet(); | |
| - } | |
| - | |
| - void recordMiss() { | |
| - misses.incrementAndGet(); | |
| - } | |
| - | |
| - void recordCacheCreation(CacheRetention retention) { | |
| - cacheCreations.incrementAndGet(); | |
| - creationsByRetention | |
| - .computeIfAbsent(retention, k -> new AtomicLong()) | |
| - .incrementAndGet(); | |
| - } | |
| - } | |
| -} | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/DefaultRequestCache.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/DefaultRequestCache.java | |
| index c42bef5a63..e525aa013a 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/DefaultRequestCache.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/DefaultRequestCache.java | |
| @@ -18,12 +18,12 @@ | |
| */ | |
| package org.apache.maven.impl.cache; | |
| -import java.util.ArrayList; | |
| -import java.util.List; | |
| -import java.util.Locale; | |
| +import java.util.Map; | |
| +import java.util.Objects; | |
| +import java.util.concurrent.ConcurrentHashMap; | |
| +import java.util.concurrent.ConcurrentMap; | |
| import java.util.function.Function; | |
| -import org.apache.maven.api.Constants; | |
| import org.apache.maven.api.Session; | |
| import org.apache.maven.api.SessionData; | |
| import org.apache.maven.api.cache.CacheMetadata; | |
| @@ -31,453 +31,45 @@ | |
| import org.apache.maven.api.services.Request; | |
| import org.apache.maven.api.services.RequestTrace; | |
| import org.apache.maven.api.services.Result; | |
| -import org.apache.maven.impl.InternalSession; | |
| -import org.slf4j.Logger; | |
| -import org.slf4j.LoggerFactory; | |
| public class DefaultRequestCache extends AbstractRequestCache { | |
| - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultRequestCache.class); | |
| - | |
| - protected static final SessionData.Key<Cache> KEY = SessionData.key(Cache.class, CacheMetadata.class); | |
| + protected static final SessionData.Key<ConcurrentMap> KEY = | |
| + SessionData.key(ConcurrentMap.class, CacheMetadata.class); | |
| protected static final Object ROOT = new Object(); | |
| - // Comprehensive cache statistics | |
| - private final CacheStatistics statistics = new CacheStatistics(); | |
| - | |
| - private static volatile boolean shutdownHookRegistered = false; | |
| - private static final List<CacheStatistics> ALL_STATISTICS = new ArrayList<CacheStatistics>(); | |
| - | |
| - // Synchronized method to ensure shutdown hook is registered only once | |
| - private static synchronized void ensureShutdownHookRegistered() { | |
| - if (!shutdownHookRegistered) { | |
| - Runtime.getRuntime() | |
| - .addShutdownHook(new Thread( | |
| - () -> { | |
| - // Check if cache stats should be displayed | |
| - for (CacheStatistics statistics : ALL_STATISTICS) { | |
| - if (statistics.getTotalRequests() > 0) { | |
| - System.err.println("[INFO] " + formatCacheStatistics(statistics)); | |
| - } | |
| - } | |
| - }, | |
| - "DefaultRequestCache-Statistics")); | |
| - shutdownHookRegistered = true; | |
| - } | |
| - } | |
| - | |
| - public DefaultRequestCache() { | |
| - // Register cache size suppliers for different retention policies | |
| - // Note: These provide approximate sizes since the improved cache architecture | |
| - // uses distributed caches across sessions | |
| - statistics.registerCacheSizeSupplier(CacheRetention.PERSISTENT, () -> 0L); | |
| - statistics.registerCacheSizeSupplier(CacheRetention.SESSION_SCOPED, () -> 0L); | |
| - statistics.registerCacheSizeSupplier(CacheRetention.REQUEST_SCOPED, () -> 0L); | |
| - | |
| - synchronized (ALL_STATISTICS) { | |
| - ALL_STATISTICS.add(statistics); | |
| - } | |
| - } | |
| - | |
| - /** | |
| - * Formats comprehensive cache statistics for display. | |
| - * | |
| - * @param stats the cache statistics to format | |
| - * @return a formatted string containing cache statistics | |
| - */ | |
| - static String formatCacheStatistics(CacheStatistics stats) { | |
| - StringBuilder sb = new StringBuilder(); | |
| - sb.append("Request Cache Statistics:\n"); | |
| - sb.append(" Total requests: ").append(stats.getTotalRequests()).append("\n"); | |
| - sb.append(" Cache hits: ").append(stats.getCacheHits()).append("\n"); | |
| - sb.append(" Cache misses: ").append(stats.getCacheMisses()).append("\n"); | |
| - sb.append(" Hit ratio: ") | |
| - .append(String.format(Locale.ENGLISH, "%.2f%%", stats.getHitRatio())) | |
| - .append("\n"); | |
| - | |
| - // Show eviction statistics | |
| - long totalEvictions = stats.getTotalEvictions(); | |
| - if (totalEvictions > 0) { | |
| - sb.append(" Evictions:\n"); | |
| - sb.append(" Key evictions: ") | |
| - .append(stats.getKeyEvictions()) | |
| - .append(" (") | |
| - .append(String.format(Locale.ENGLISH, "%.1f%%", stats.getKeyEvictionRatio())) | |
| - .append(")\n"); | |
| - sb.append(" Value evictions: ") | |
| - .append(stats.getValueEvictions()) | |
| - .append(" (") | |
| - .append(String.format(Locale.ENGLISH, "%.1f%%", stats.getValueEvictionRatio())) | |
| - .append(")\n"); | |
| - sb.append(" Total evictions: ").append(totalEvictions).append("\n"); | |
| - } | |
| - | |
| - // Show retention policy breakdown | |
| - var retentionStats = stats.getRetentionStatistics(); | |
| - if (!retentionStats.isEmpty()) { | |
| - sb.append(" By retention policy:\n"); | |
| - retentionStats.forEach((retention, retStats) -> { | |
| - sb.append(" ") | |
| - .append(retention) | |
| - .append(": ") | |
| - .append(retStats.getHits()) | |
| - .append(" hits, ") | |
| - .append(retStats.getMisses()) | |
| - .append(" misses (") | |
| - .append(String.format(Locale.ENGLISH, "%.1f%%", retStats.getHitRatio())) | |
| - .append(" hit ratio)"); | |
| - | |
| - // Add eviction info for this retention policy | |
| - long retKeyEvictions = retStats.getKeyEvictions(); | |
| - long retValueEvictions = retStats.getValueEvictions(); | |
| - if (retKeyEvictions > 0 || retValueEvictions > 0) { | |
| - sb.append(", ") | |
| - .append(retKeyEvictions) | |
| - .append(" key evictions, ") | |
| - .append(retValueEvictions) | |
| - .append(" value evictions"); | |
| - } | |
| - sb.append("\n"); | |
| - }); | |
| - } | |
| - | |
| - // Show reference type statistics | |
| - var refTypeStats = stats.getReferenceTypeStatistics(); | |
| - if (!refTypeStats.isEmpty()) { | |
| - sb.append(" Reference type usage:\n"); | |
| - refTypeStats.entrySet().stream() | |
| - .sorted((e1, e2) -> | |
| - Long.compare(e2.getValue().getTotal(), e1.getValue().getTotal())) | |
| - .forEach(entry -> { | |
| - var refStats = entry.getValue(); | |
| - sb.append(" ") | |
| - .append(entry.getKey()) | |
| - .append(": ") | |
| - .append(refStats.getCacheCreations()) | |
| - .append(" caches, ") | |
| - .append(refStats.getTotal()) | |
| - .append(" accesses (") | |
| - .append(String.format(Locale.ENGLISH, "%.1f%%", refStats.getHitRatio())) | |
| - .append(" hit ratio)\n"); | |
| - }); | |
| - } | |
| - | |
| - // Show top request types | |
| - var requestStats = stats.getRequestTypeStatistics(); | |
| - if (!requestStats.isEmpty()) { | |
| - sb.append(" Top request types:\n"); | |
| - requestStats.entrySet().stream() | |
| - .sorted((e1, e2) -> | |
| - Long.compare(e2.getValue().getTotal(), e1.getValue().getTotal())) | |
| - // .limit(5) | |
| - .forEach(entry -> { | |
| - var reqStats = entry.getValue(); | |
| - sb.append(" ") | |
| - .append(entry.getKey()) | |
| - .append(": ") | |
| - .append(reqStats.getTotal()) | |
| - .append(" requests (") | |
| - .append(String.format(Locale.ENGLISH, "%.1f%%", reqStats.getHitRatio())) | |
| - .append(" hit ratio)\n"); | |
| - }); | |
| - } | |
| - | |
| - return sb.toString(); | |
| - } | |
| - | |
| - public CacheStatistics getStatistics() { | |
| - return statistics; | |
| - } | |
| + protected final Map<Object, CachingSupplier<?, ?>> forever = new ConcurrentHashMap<>(); | |
| @Override | |
| - @SuppressWarnings({"unchecked", "checkstyle:MethodLength"}) | |
| + @SuppressWarnings("unchecked") | |
| protected <REQ extends Request<?>, REP extends Result<REQ>> CachingSupplier<REQ, REP> doCache( | |
| REQ req, Function<REQ, REP> supplier) { | |
| - // Early return for non-Session requests (e.g., ProtoSession) | |
| - if (!(req.getSession() instanceof Session session)) { | |
| - // Record as a miss since no caching is performed for non-Session requests | |
| - statistics.recordMiss(req.getClass().getSimpleName(), CacheRetention.DISABLED); | |
| - return new CachingSupplier<>(supplier); | |
| - } | |
| - | |
| - // Register shutdown hook for conditional statistics display | |
| - boolean cacheStatsEnabled = isCacheStatsEnabled(session); | |
| - if (cacheStatsEnabled) { | |
| - ensureShutdownHookRegistered(); | |
| - } | |
| - | |
| - CacheConfig config = getCacheConfig(req, session); | |
| - CacheRetention retention = config.scope(); | |
| - Cache.ReferenceType referenceType = config.referenceType(); | |
| - Cache.ReferenceType keyReferenceType = config.getEffectiveKeyReferenceType(); | |
| - Cache.ReferenceType valueReferenceType = config.getEffectiveValueReferenceType(); | |
| - | |
| - // Debug logging to verify reference types (disabled) | |
| - // System.err.println("DEBUG: Cache config for " + req.getClass().getSimpleName() + ": retention=" + retention | |
| - // + ", keyRef=" + keyReferenceType + ", valueRef=" + valueReferenceType); | |
| - if (LOGGER.isDebugEnabled()) { | |
| - LOGGER.debug( | |
| - "Cache config for {}: retention={}, keyRef={}, valueRef={}", | |
| - req.getClass().getSimpleName(), | |
| - retention, | |
| - keyReferenceType, | |
| - valueReferenceType); | |
| - } | |
| - | |
| - // Handle disabled caching | |
| - if (retention == CacheRetention.DISABLED | |
| - || keyReferenceType == Cache.ReferenceType.NONE | |
| - || valueReferenceType == Cache.ReferenceType.NONE) { | |
| - // Record as a miss since no caching is performed | |
| - statistics.recordMiss(req.getClass().getSimpleName(), retention); | |
| - return new CachingSupplier<>(supplier); | |
| - } | |
| - | |
| - Cache<Object, CachingSupplier<?, ?>> cache = null; | |
| - String cacheType = "NONE"; | |
| - | |
| - if (retention == CacheRetention.SESSION_SCOPED) { | |
| - Cache<Object, Cache<Object, CachingSupplier<?, ?>>> caches = session.getData() | |
| - .computeIfAbsent(KEY, () -> { | |
| - if (config.hasSeparateKeyValueReferenceTypes()) { | |
| - LOGGER.debug( | |
| - "Creating SESSION_SCOPED parent cache with key={}, value={}", | |
| - keyReferenceType, | |
| - valueReferenceType); | |
| - return Cache.newCache(keyReferenceType, valueReferenceType, "RequestCache-SESSION-Parent"); | |
| - } else { | |
| - return Cache.newCache(Cache.ReferenceType.SOFT, "RequestCache-SESSION-Parent"); | |
| - } | |
| - }); | |
| - | |
| - // Use separate key/value reference types if configured | |
| - if (config.hasSeparateKeyValueReferenceTypes()) { | |
| - cache = caches.computeIfAbsent(ROOT, k -> { | |
| - LOGGER.debug( | |
| - "Creating SESSION_SCOPED cache with key={}, value={}", | |
| - keyReferenceType, | |
| - valueReferenceType); | |
| - Cache<Object, CachingSupplier<?, ?>> newCache = | |
| - Cache.newCache(keyReferenceType, valueReferenceType, "RequestCache-SESSION"); | |
| - statistics.recordCacheCreation( | |
| - keyReferenceType.toString(), valueReferenceType.toString(), retention); | |
| - setupEvictionListenerIfNeeded(newCache, retention); | |
| - | |
| - // Debug logging to verify actual reference types (disabled) | |
| - // if (newCache instanceof Cache.RefConcurrentMap<?, ?> refMap) { | |
| - // System.err.println("DEBUG: Created cache '" + refMap.getName() + "' - requested key=" | |
| - // + keyReferenceType | |
| - // + ", value=" + valueReferenceType + ", actual key=" + refMap.getKeyReferenceType() | |
| - // + ", actual value=" + refMap.getValueReferenceType()); | |
| - // } | |
| - return newCache; | |
| - }); | |
| - } else { | |
| - cache = caches.computeIfAbsent(ROOT, k -> { | |
| - Cache<Object, CachingSupplier<?, ?>> newCache = | |
| - Cache.newCache(referenceType, "RequestCache-SESSION"); | |
| - statistics.recordCacheCreation(referenceType.toString(), referenceType.toString(), retention); | |
| - setupEvictionListenerIfNeeded(newCache, retention); | |
| - return newCache; | |
| - }); | |
| - } | |
| - cacheType = "SESSION_SCOPED"; | |
| - // Debug logging for cache sizes | |
| - if (LOGGER.isDebugEnabled()) { | |
| - LOGGER.debug( | |
| - "Cache access: type={}, request={}, cacheSize={}, totalCaches={}, key={}", | |
| - cacheType, | |
| - req.getClass().getSimpleName(), | |
| - cache.size(), | |
| - caches.size(), | |
| - ROOT); | |
| - } | |
| - } else if (retention == CacheRetention.REQUEST_SCOPED) { | |
| - Object key = doGetOuterRequest(req); | |
| - Cache<Object, Cache<Object, CachingSupplier<?, ?>>> caches = session.getData() | |
| - .computeIfAbsent(KEY, () -> { | |
| - if (config.hasSeparateKeyValueReferenceTypes()) { | |
| - LOGGER.debug( | |
| - "Creating REQUEST_SCOPED parent cache with key={}, value={}", | |
| - keyReferenceType, | |
| - valueReferenceType); | |
| - return Cache.newCache(keyReferenceType, valueReferenceType, "RequestCache-REQUEST-Parent"); | |
| - } else { | |
| - return Cache.newCache(Cache.ReferenceType.SOFT, "RequestCache-REQUEST-Parent"); | |
| - } | |
| - }); | |
| - | |
| - // Use separate key/value reference types if configured | |
| - if (config.hasSeparateKeyValueReferenceTypes()) { | |
| - cache = caches.computeIfAbsent(key, k -> { | |
| - LOGGER.debug( | |
| - "Creating REQUEST_SCOPED cache with key={}, value={}", | |
| - keyReferenceType, | |
| - valueReferenceType); | |
| - Cache<Object, CachingSupplier<?, ?>> newCache = | |
| - Cache.newCache(keyReferenceType, valueReferenceType, "RequestCache-REQUEST"); | |
| - statistics.recordCacheCreation( | |
| - keyReferenceType.toString(), valueReferenceType.toString(), retention); | |
| - setupEvictionListenerIfNeeded(newCache, retention); | |
| - return newCache; | |
| - }); | |
| - } else { | |
| - cache = caches.computeIfAbsent(key, k -> { | |
| - Cache<Object, CachingSupplier<?, ?>> newCache = | |
| - Cache.newCache(referenceType, "RequestCache-REQUEST"); | |
| - statistics.recordCacheCreation(referenceType.toString(), referenceType.toString(), retention); | |
| - setupEvictionListenerIfNeeded(newCache, retention); | |
| - return newCache; | |
| - }); | |
| - } | |
| - cacheType = "REQUEST_SCOPED"; | |
| - | |
| - // Debug logging for cache sizes | |
| - if (LOGGER.isDebugEnabled()) { | |
| - LOGGER.debug( | |
| - "Cache access: type={}, request={}, cacheSize={}, totalCaches={}, key={}", | |
| - cacheType, | |
| - req.getClass().getSimpleName(), | |
| - cache.size(), | |
| - caches.size(), | |
| - key.getClass().getSimpleName()); | |
| - } | |
| - | |
| + CacheRetention retention = Objects.requireNonNullElse( | |
| + req instanceof CacheMetadata metadata ? metadata.getCacheRetention() : null, | |
| + CacheRetention.SESSION_SCOPED); | |
| + | |
| + Map<Object, CachingSupplier<?, ?>> cache = null; | |
| + if ((retention == CacheRetention.REQUEST_SCOPED || retention == CacheRetention.SESSION_SCOPED) | |
| + && req.getSession() instanceof Session session) { | |
| + Object key = retention == CacheRetention.REQUEST_SCOPED ? doGetOuterRequest(req) : ROOT; | |
| + Map<Object, Map<Object, CachingSupplier<?, ?>>> caches = | |
| + session.getData().computeIfAbsent(KEY, ConcurrentHashMap::new); | |
| + cache = caches.computeIfAbsent(key, k -> new SoftIdentityMap<>()); | |
| } else if (retention == CacheRetention.PERSISTENT) { | |
| - Cache<Object, Cache<Object, CachingSupplier<?, ?>>> caches = session.getData() | |
| - .computeIfAbsent(KEY, () -> { | |
| - if (config.hasSeparateKeyValueReferenceTypes()) { | |
| - LOGGER.debug( | |
| - "Creating PERSISTENT parent cache with key={}, value={}", | |
| - keyReferenceType, | |
| - valueReferenceType); | |
| - return Cache.newCache( | |
| - keyReferenceType, valueReferenceType, "RequestCache-PERSISTENT-Parent"); | |
| - } else { | |
| - return Cache.newCache(Cache.ReferenceType.SOFT, "RequestCache-PERSISTENT-Parent"); | |
| - } | |
| - }); | |
| - | |
| - // Use separate key/value reference types if configured | |
| - if (config.hasSeparateKeyValueReferenceTypes()) { | |
| - cache = caches.computeIfAbsent(KEY, k -> { | |
| - LOGGER.debug( | |
| - "Creating PERSISTENT cache with key={}, value={}", keyReferenceType, valueReferenceType); | |
| - Cache<Object, CachingSupplier<?, ?>> newCache = | |
| - Cache.newCache(keyReferenceType, valueReferenceType, "RequestCache-PERSISTENT"); | |
| - statistics.recordCacheCreation( | |
| - keyReferenceType.toString(), valueReferenceType.toString(), retention); | |
| - setupEvictionListenerIfNeeded(newCache, retention); | |
| - return newCache; | |
| - }); | |
| - } else { | |
| - cache = caches.computeIfAbsent(KEY, k -> { | |
| - Cache<Object, CachingSupplier<?, ?>> newCache = | |
| - Cache.newCache(referenceType, "RequestCache-PERSISTENT"); | |
| - statistics.recordCacheCreation(referenceType.toString(), referenceType.toString(), retention); | |
| - setupEvictionListenerIfNeeded(newCache, retention); | |
| - return newCache; | |
| - }); | |
| - } | |
| - cacheType = "PERSISTENT"; | |
| - | |
| - if (LOGGER.isDebugEnabled()) { | |
| - LOGGER.debug( | |
| - "Cache access: type={}, request={}, cacheSize={}", | |
| - cacheType, | |
| - req.getClass().getSimpleName(), | |
| - cache.size()); | |
| - } | |
| + cache = forever; | |
| } | |
| - | |
| if (cache != null) { | |
| - // Set up eviction listener if this is a RefConcurrentMap | |
| - setupEvictionListenerIfNeeded(cache, retention); | |
| - | |
| - boolean isNewEntry = !cache.containsKey(req); | |
| - CachingSupplier<REQ, REP> result = (CachingSupplier<REQ, REP>) | |
| - cache.computeIfAbsent(req, r -> new CachingSupplier<>(supplier), referenceType); | |
| - | |
| - // Record statistics using the comprehensive system | |
| - String requestType = req.getClass().getSimpleName(); | |
| - | |
| - // Record reference type statistics | |
| - if (cache instanceof Cache.RefConcurrentMap<?, ?> refMap) { | |
| - statistics.recordCacheAccess( | |
| - refMap.getKeyReferenceType().toString(), | |
| - refMap.getValueReferenceType().toString(), | |
| - !isNewEntry); | |
| - } | |
| - | |
| - if (isNewEntry) { | |
| - statistics.recordMiss(requestType, retention); | |
| - if (LOGGER.isTraceEnabled()) { | |
| - LOGGER.trace( | |
| - "Cache MISS: type={}, request={}, newCacheSize={}", cacheType, requestType, cache.size()); | |
| - } | |
| - } else { | |
| - statistics.recordHit(requestType, retention); | |
| - if (LOGGER.isTraceEnabled()) { | |
| - LOGGER.trace("Cache HIT: type={}, request={}", cacheType, requestType); | |
| - } | |
| - } | |
| - return result; | |
| + return (CachingSupplier<REQ, REP>) cache.computeIfAbsent(req, r -> new CachingSupplier<>(supplier)); | |
| } else { | |
| - // Record as a miss since no cache was available | |
| - statistics.recordMiss(req.getClass().getSimpleName(), retention); | |
| - if (LOGGER.isTraceEnabled()) { | |
| - LOGGER.trace("No cache: request={}", req.getClass().getSimpleName()); | |
| - } | |
| return new CachingSupplier<>(supplier); | |
| } | |
| } | |
| - private static boolean isCacheStatsEnabled(Session session) { | |
| - String showStats = session.getUserProperties().get(Constants.MAVEN_CACHE_STATS); | |
| - return Boolean.parseBoolean(showStats); | |
| - } | |
| - | |
| - /** | |
| - * Sets up eviction listener for the cache if it's a RefConcurrentMap. | |
| - * This avoids memory leaks by having the cache push events to statistics | |
| - * instead of statistics holding references to caches. | |
| - */ | |
| - private void setupEvictionListenerIfNeeded(Cache<Object, CachingSupplier<?, ?>> cache, CacheRetention retention) { | |
| - if (cache instanceof Cache.RefConcurrentMap<?, ?> refMap) { | |
| - // Set up the eviction listener (it's safe to set multiple times) | |
| - refMap.setEvictionListener(new Cache.EvictionListener() { | |
| - @Override | |
| - public void onKeyEviction() { | |
| - statistics.recordKeyEviction(retention); | |
| - } | |
| - | |
| - @Override | |
| - public void onValueEviction() { | |
| - statistics.recordValueEviction(retention); | |
| - } | |
| - }); | |
| - } | |
| - } | |
| - | |
| private <REQ extends Request<?>> Object doGetOuterRequest(REQ req) { | |
| RequestTrace trace = req.getTrace(); | |
| - if (trace == null && req.getSession() instanceof Session session) { | |
| - trace = InternalSession.from(session).getCurrentTrace(); | |
| - } | |
| while (trace != null && trace.parent() != null) { | |
| trace = trace.parent(); | |
| } | |
| return trace != null && trace.data() != null ? trace.data() : req; | |
| } | |
| - | |
| - /** | |
| - * Gets the cache configuration for the given request and session. | |
| - * | |
| - * @param req the request to get configuration for | |
| - * @param session the session containing user properties | |
| - * @return the resolved cache configuration | |
| - */ | |
| - private <REQ extends Request<?>> CacheConfig getCacheConfig(REQ req, Session session) { | |
| - return CacheConfigurationResolver.resolveConfig(req, session); | |
| - } | |
| } | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/DefaultRequestCacheFactory.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/DefaultRequestCacheFactory.java | |
| index 667adb7b9a..fa268de59e 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/DefaultRequestCacheFactory.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/DefaultRequestCacheFactory.java | |
| @@ -27,10 +27,8 @@ | |
| @Singleton | |
| public class DefaultRequestCacheFactory implements RequestCacheFactory { | |
| - private static final RequestCache REQUEST_CACHE = new DefaultRequestCache(); | |
| - | |
| @Override | |
| public RequestCache createCache() { | |
| - return REQUEST_CACHE; | |
| + return new DefaultRequestCache(); | |
| } | |
| } | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/PartialCacheConfig.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/PartialCacheConfig.java | |
| deleted file mode 100644 | |
| index 49cb9e731b..0000000000 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/PartialCacheConfig.java | |
| +++ /dev/null | |
| @@ -1,96 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.impl.cache; | |
| - | |
| -import org.apache.maven.api.cache.CacheRetention; | |
| - | |
| -/** | |
| - * Partial cache configuration that allows specifying only scope or reference type. | |
| - * Used for merging configurations from multiple selectors. | |
| - * | |
| - * @param scope the cache retention scope (nullable) | |
| - * @param referenceType the reference type to use for cache entries (nullable) | |
| - */ | |
| -public record PartialCacheConfig(CacheRetention scope, Cache.ReferenceType referenceType) { | |
| - | |
| - /** | |
| - * Creates a partial configuration with only scope specified. | |
| - */ | |
| - public static PartialCacheConfig withScope(CacheRetention scope) { | |
| - return new PartialCacheConfig(scope, null); | |
| - } | |
| - | |
| - /** | |
| - * Creates a partial configuration with only reference type specified. | |
| - */ | |
| - public static PartialCacheConfig withReferenceType(Cache.ReferenceType referenceType) { | |
| - return new PartialCacheConfig(null, referenceType); | |
| - } | |
| - | |
| - /** | |
| - * Creates a complete partial configuration with both scope and reference type. | |
| - */ | |
| - public static PartialCacheConfig complete(CacheRetention scope, Cache.ReferenceType referenceType) { | |
| - return new PartialCacheConfig(scope, referenceType); | |
| - } | |
| - | |
| - /** | |
| - * Merges this configuration with another, with this configuration taking precedence | |
| - * for non-null values. | |
| - * | |
| - * @param other the other configuration to merge with | |
| - * @return a new merged configuration | |
| - */ | |
| - public PartialCacheConfig mergeWith(PartialCacheConfig other) { | |
| - if (other == null) { | |
| - return this; | |
| - } | |
| - | |
| - CacheRetention mergedScope = this.scope != null ? this.scope : other.scope; | |
| - Cache.ReferenceType mergedRefType = this.referenceType != null ? this.referenceType : other.referenceType; | |
| - | |
| - return new PartialCacheConfig(mergedScope, mergedRefType); | |
| - } | |
| - | |
| - /** | |
| - * Converts this partial configuration to a complete CacheConfig, using defaults for missing values. | |
| - * | |
| - * @return a complete CacheConfig | |
| - */ | |
| - public CacheConfig toComplete() { | |
| - CacheRetention finalScope = scope != null ? scope : CacheRetention.REQUEST_SCOPED; | |
| - Cache.ReferenceType finalRefType = referenceType != null ? referenceType : Cache.ReferenceType.SOFT; | |
| - | |
| - return new CacheConfig(finalScope, finalRefType); | |
| - } | |
| - | |
| - /** | |
| - * Checks if this configuration is empty (both values are null). | |
| - */ | |
| - public boolean isEmpty() { | |
| - return scope == null && referenceType == null; | |
| - } | |
| - | |
| - /** | |
| - * Checks if this configuration is complete (both values are non-null). | |
| - */ | |
| - public boolean isComplete() { | |
| - return scope != null && referenceType != null; | |
| - } | |
| -} | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/SoftIdentityMap.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/SoftIdentityMap.java | |
| new file mode 100644 | |
| index 0000000000..2c6c51b660 | |
| --- /dev/null | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/cache/SoftIdentityMap.java | |
| @@ -0,0 +1,239 @@ | |
| +/* | |
| + * Licensed to the Apache Software Foundation (ASF) under one | |
| + * or more contributor license agreements. See the NOTICE file | |
| + * distributed with this work for additional information | |
| + * regarding copyright ownership. The ASF licenses this file | |
| + * to you under the Apache License, Version 2.0 (the | |
| + * "License"); you may not use this file except in compliance | |
| + * with the License. You may obtain a copy of the License at | |
| + * | |
| + * http://www.apache.org/licenses/LICENSE-2.0 | |
| + * | |
| + * Unless required by applicable law or agreed to in writing, | |
| + * software distributed under the License is distributed on an | |
| + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| + * KIND, either express or implied. See the License for the | |
| + * specific language governing permissions and limitations | |
| + * under the License. | |
| + */ | |
| +package org.apache.maven.impl.cache; | |
| + | |
| +import java.lang.ref.Reference; | |
| +import java.lang.ref.ReferenceQueue; | |
| +import java.lang.ref.SoftReference; | |
| +import java.util.Collection; | |
| +import java.util.Map; | |
| +import java.util.Objects; | |
| +import java.util.Set; | |
| +import java.util.concurrent.ConcurrentHashMap; | |
| +import java.util.function.Function; | |
| + | |
| +/** | |
| + * A Map implementation that uses soft references for both keys and values, | |
| + * and compares keys using identity (==) rather than equals(). | |
| + * | |
| + * @param <K> the type of keys maintained by this map | |
| + * @param <V> the type of mapped values | |
| + */ | |
| +public class SoftIdentityMap<K, V> implements Map<K, V> { | |
| + | |
| + private final ReferenceQueue<K> keyQueue = new ReferenceQueue<>(); | |
| + private final ReferenceQueue<V> valueQueue = new ReferenceQueue<>(); | |
| + private final ConcurrentHashMap<SoftIdentityReference<K>, ComputeReference<V>> map = new ConcurrentHashMap<>(); | |
| + | |
| + private static class SoftIdentityReference<T> extends SoftReference<T> { | |
| + private final int hash; | |
| + | |
| + SoftIdentityReference(T referent, ReferenceQueue<T> queue) { | |
| + super(referent, queue); | |
| + this.hash = referent.hashCode(); | |
| + } | |
| + | |
| + @Override | |
| + public boolean equals(Object obj) { | |
| + if (this == obj) { | |
| + return true; | |
| + } | |
| + if (!(obj instanceof SoftIdentityReference<?> other)) { | |
| + return false; | |
| + } | |
| + T thisRef = this.get(); | |
| + Object otherRef = other.get(); | |
| + return thisRef != null && thisRef.equals(otherRef); | |
| + } | |
| + | |
| + @Override | |
| + public int hashCode() { | |
| + return hash; | |
| + } | |
| + } | |
| + | |
| + private static class ComputeReference<V> extends SoftReference<V> { | |
| + private final boolean computing; | |
| + | |
| + ComputeReference(V value, ReferenceQueue<V> queue) { | |
| + super(value, queue); | |
| + this.computing = false; | |
| + } | |
| + | |
| + private ComputeReference(ReferenceQueue<V> queue) { | |
| + super(null, queue); | |
| + this.computing = true; | |
| + } | |
| + | |
| + static <V> ComputeReference<V> computing(ReferenceQueue<V> queue) { | |
| + return new ComputeReference<>(queue); | |
| + } | |
| + } | |
| + | |
| + @Override | |
| + public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { | |
| + Objects.requireNonNull(key); | |
| + Objects.requireNonNull(mappingFunction); | |
| + | |
| + while (true) { | |
| + expungeStaleEntries(); | |
| + | |
| + SoftIdentityReference<K> softKey = new SoftIdentityReference<>(key, keyQueue); | |
| + | |
| + // Try to get existing value | |
| + ComputeReference<V> valueRef = map.get(softKey); | |
| + if (valueRef != null && !valueRef.computing) { | |
| + V value = valueRef.get(); | |
| + if (value != null) { | |
| + return value; | |
| + } | |
| + // Value was GC'd, remove it | |
| + map.remove(softKey, valueRef); | |
| + } | |
| + | |
| + // Try to claim computation | |
| + ComputeReference<V> computingRef = ComputeReference.computing(valueQueue); | |
| + valueRef = map.putIfAbsent(softKey, computingRef); | |
| + | |
| + if (valueRef == null) { | |
| + // We claimed the computation | |
| + try { | |
| + V newValue = mappingFunction.apply(key); | |
| + if (newValue == null) { | |
| + map.remove(softKey, computingRef); | |
| + return null; | |
| + } | |
| + | |
| + ComputeReference<V> newValueRef = new ComputeReference<>(newValue, valueQueue); | |
| + map.replace(softKey, computingRef, newValueRef); | |
| + return newValue; | |
| + } catch (Throwable t) { | |
| + map.remove(softKey, computingRef); | |
| + throw t; | |
| + } | |
| + } else if (!valueRef.computing) { | |
| + // Another thread has a value | |
| + V value = valueRef.get(); | |
| + if (value != null) { | |
| + return value; | |
| + } | |
| + // Value was GC'd | |
| + if (map.remove(softKey, valueRef)) { | |
| + continue; | |
| + } | |
| + } | |
| + // Another thread is computing or the reference changed, try again | |
| + } | |
| + } | |
| + | |
| + private void expungeStaleEntries() { | |
| + Reference<?> ref; | |
| + while ((ref = keyQueue.poll()) != null) { | |
| + map.remove(ref); | |
| + } | |
| + while ((ref = valueQueue.poll()) != null) { | |
| + map.values().remove(ref); | |
| + } | |
| + } | |
| + | |
| + @Override | |
| + public int size() { | |
| + expungeStaleEntries(); | |
| + return map.size(); | |
| + } | |
| + | |
| + @Override | |
| + public boolean isEmpty() { | |
| + expungeStaleEntries(); | |
| + return map.isEmpty(); | |
| + } | |
| + | |
| + @Override | |
| + public boolean containsKey(Object key) { | |
| + expungeStaleEntries(); | |
| + return map.containsKey(new SoftIdentityReference<>((K) key, null)); | |
| + } | |
| + | |
| + @Override | |
| + public boolean containsValue(Object value) { | |
| + expungeStaleEntries(); | |
| + for (Reference<V> ref : map.values()) { | |
| + V v = ref.get(); | |
| + if (v != null && v == value) { | |
| + return true; | |
| + } | |
| + } | |
| + return false; | |
| + } | |
| + | |
| + @Override | |
| + public V get(Object key) { | |
| + expungeStaleEntries(); | |
| + Reference<V> ref = map.get(new SoftIdentityReference<>((K) key, null)); | |
| + return ref != null ? ref.get() : null; | |
| + } | |
| + | |
| + @Override | |
| + public V put(K key, V value) { | |
| + Objects.requireNonNull(key); | |
| + Objects.requireNonNull(value); | |
| + expungeStaleEntries(); | |
| + | |
| + Reference<V> oldValueRef = | |
| + map.put(new SoftIdentityReference<>(key, keyQueue), new ComputeReference<>(value, valueQueue)); | |
| + | |
| + return oldValueRef != null ? oldValueRef.get() : null; | |
| + } | |
| + | |
| + @Override | |
| + public V remove(Object key) { | |
| + expungeStaleEntries(); | |
| + Reference<V> valueRef = map.remove(new SoftIdentityReference<>((K) key, null)); | |
| + return valueRef != null ? valueRef.get() : null; | |
| + } | |
| + | |
| + @Override | |
| + public void putAll(Map<? extends K, ? extends V> m) { | |
| + Objects.requireNonNull(m); | |
| + for (Entry<? extends K, ? extends V> e : m.entrySet()) { | |
| + put(e.getKey(), e.getValue()); | |
| + } | |
| + } | |
| + | |
| + @Override | |
| + public void clear() { | |
| + map.clear(); | |
| + expungeStaleEntries(); | |
| + } | |
| + | |
| + @Override | |
| + public Set<K> keySet() { | |
| + throw new UnsupportedOperationException("keySet not supported"); | |
| + } | |
| + | |
| + @Override | |
| + public Collection<V> values() { | |
| + throw new UnsupportedOperationException("values not supported"); | |
| + } | |
| + | |
| + @Override | |
| + public Set<Entry<K, V>> entrySet() { | |
| + throw new UnsupportedOperationException("entrySet not supported"); | |
| + } | |
| +} | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/di/SessionScope.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/di/SessionScope.java | |
| index cb8e818ea0..b47c5acde8 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/di/SessionScope.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/di/SessionScope.java | |
| @@ -119,32 +119,32 @@ protected <T> Object dispatch(Key<T> key, Supplier<T> unscoped, Method method, O | |
| protected Class<?>[] getInterfaces(Class<?> superType) { | |
| if (superType.isInterface()) { | |
| return new Class<?>[] {superType}; | |
| - } | |
| - for (Annotation a : superType.getAnnotations()) { | |
| - Class<? extends Annotation> annotationType = a.annotationType(); | |
| - if (isTypeAnnotation(annotationType)) { | |
| - try { | |
| - Class<?>[] value = | |
| - (Class<?>[]) annotationType.getMethod("value").invoke(a); | |
| - if (value.length == 0) { | |
| - // Only direct interfaces implemented by the class | |
| - value = superType.getInterfaces(); | |
| - } | |
| - List<Class<?>> nonInterfaces = | |
| - Stream.of(value).filter(c -> !c.isInterface()).toList(); | |
| - if (!nonInterfaces.isEmpty()) { | |
| - throw new IllegalArgumentException( | |
| - "The Typed annotation must contain only interfaces but the following types are not: " | |
| - + nonInterfaces); | |
| + } else { | |
| + for (Annotation a : superType.getAnnotations()) { | |
| + Class<? extends Annotation> annotationType = a.annotationType(); | |
| + if (isTypeAnnotation(annotationType)) { | |
| + try { | |
| + Class<?>[] value = | |
| + (Class<?>[]) annotationType.getMethod("value").invoke(a); | |
| + if (value.length == 0) { | |
| + value = superType.getInterfaces(); | |
| + } | |
| + List<Class<?>> nonInterfaces = | |
| + Stream.of(value).filter(c -> !c.isInterface()).toList(); | |
| + if (!nonInterfaces.isEmpty()) { | |
| + throw new IllegalArgumentException( | |
| + "The Typed annotation must contain only interfaces but the following types are not: " | |
| + + nonInterfaces); | |
| + } | |
| + return value; | |
| + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { | |
| + throw new IllegalStateException(e); | |
| } | |
| - return value; | |
| - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { | |
| - throw new IllegalStateException(e); | |
| } | |
| } | |
| + throw new IllegalArgumentException("The use of session scoped proxies require " | |
| + + "a org.eclipse.sisu.Typed or javax.enterprise.inject.Typed annotation"); | |
| } | |
| - throw new IllegalArgumentException( | |
| - "The use of session scoped proxies require a org.apache.maven.api.di.Typed, org.eclipse.sisu.Typed or javax.enterprise.inject.Typed annotation"); | |
| } | |
| protected boolean isTypeAnnotation(Class<? extends Annotation> annotationType) { | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultDependencyManagementImporter.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultDependencyManagementImporter.java | |
| index 45de07f83a..19ed567329 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultDependencyManagementImporter.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultDependencyManagementImporter.java | |
| @@ -185,6 +185,8 @@ static Dependency updateWithImportedFrom(Dependency dependency, DependencyManage | |
| // We modify the input location that is used for the whole file. | |
| // This is likely correct because the POM hierarchy applies to the whole POM, not just one dependency. | |
| - return Dependency.newBuilder(dependency, true).importedFrom(bomLocation).build(); | |
| + return Dependency.newBuilder(dependency, true) | |
| + .importedFrom(new InputLocation(bomLocation)) | |
| + .build(); | |
| } | |
| } | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultInheritanceAssembler.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultInheritanceAssembler.java | |
| index aeacef7b53..f9c4a9883a 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultInheritanceAssembler.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultInheritanceAssembler.java | |
| @@ -194,16 +194,6 @@ private void concatPath(StringBuilder url, String path) { | |
| } | |
| } | |
| - @Override | |
| - protected void mergeModel_Mixins( | |
| - Model.Builder builder, | |
| - Model target, | |
| - Model source, | |
| - boolean sourceDominant, | |
| - Map<Object, Object> context) { | |
| - // do not merge | |
| - } | |
| - | |
| @Override | |
| protected void mergeModelBase_Properties( | |
| ModelBase.Builder builder, | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java | |
| index 1ac6aff664..e3091e3b6d 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java | |
| @@ -21,6 +21,7 @@ | |
| import java.io.File; | |
| import java.io.IOException; | |
| import java.io.InputStream; | |
| +import java.lang.reflect.Field; | |
| import java.nio.file.Files; | |
| import java.nio.file.Path; | |
| import java.nio.file.Paths; | |
| @@ -41,7 +42,6 @@ | |
| import java.util.concurrent.Executor; | |
| import java.util.concurrent.Executors; | |
| import java.util.concurrent.atomic.AtomicReference; | |
| -import java.util.function.BiFunction; | |
| import java.util.function.Supplier; | |
| import java.util.function.UnaryOperator; | |
| import java.util.stream.Collectors; | |
| @@ -50,7 +50,6 @@ | |
| import org.apache.maven.api.Constants; | |
| import org.apache.maven.api.RemoteRepository; | |
| import org.apache.maven.api.Session; | |
| -import org.apache.maven.api.SessionData; | |
| import org.apache.maven.api.Type; | |
| import org.apache.maven.api.VersionRange; | |
| import org.apache.maven.api.annotations.Nonnull; | |
| @@ -64,15 +63,12 @@ | |
| import org.apache.maven.api.model.Activation; | |
| import org.apache.maven.api.model.Dependency; | |
| import org.apache.maven.api.model.DependencyManagement; | |
| -import org.apache.maven.api.model.DeploymentRepository; | |
| -import org.apache.maven.api.model.DistributionManagement; | |
| import org.apache.maven.api.model.Exclusion; | |
| import org.apache.maven.api.model.InputLocation; | |
| -import org.apache.maven.api.model.Mixin; | |
| +import org.apache.maven.api.model.InputSource; | |
| import org.apache.maven.api.model.Model; | |
| import org.apache.maven.api.model.Parent; | |
| import org.apache.maven.api.model.Profile; | |
| -import org.apache.maven.api.model.Repository; | |
| import org.apache.maven.api.services.BuilderProblem; | |
| import org.apache.maven.api.services.BuilderProblem.Severity; | |
| import org.apache.maven.api.services.Interpolator; | |
| @@ -118,7 +114,6 @@ | |
| import org.apache.maven.api.spi.ModelTransformer; | |
| import org.apache.maven.impl.InternalSession; | |
| import org.apache.maven.impl.RequestTraceHelper; | |
| -import org.apache.maven.impl.cache.Cache; | |
| import org.apache.maven.impl.util.PhasingExecutor; | |
| import org.slf4j.Logger; | |
| import org.slf4j.LoggerFactory; | |
| @@ -247,16 +242,6 @@ public ModelBuilderResult build(ModelBuilderRequest request) throws ModelBuilder | |
| } | |
| return session.result; | |
| } finally { | |
| - // Clean up REQUEST_SCOPED cache entries to prevent memory leaks | |
| - // This is especially important for BUILD_PROJECT requests which are top-level requests | |
| - if (request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_PROJECT) { | |
| - try { | |
| - clearRequestScopedCache(request); | |
| - } catch (Exception e) { | |
| - // Log but don't fail the build due to cache cleanup issues | |
| - logger.debug("Failed to clear REQUEST_SCOPED cache for request: {}", request, e); | |
| - } | |
| - } | |
| RequestTraceHelper.exit(trace); | |
| } | |
| } | |
| @@ -277,10 +262,6 @@ protected class ModelBuilderSessionState implements ModelProblemCollector { | |
| List<RemoteRepository> externalRepositories; | |
| List<RemoteRepository> repositories; | |
| - // Cycle detection chain shared across all derived sessions | |
| - // Contains both GAV coordinates (groupId:artifactId:version) and file paths | |
| - final Set<String> parentChain; | |
| - | |
| ModelBuilderSessionState(ModelBuilderRequest request) { | |
| this( | |
| request.getSession(), | |
| @@ -290,8 +271,7 @@ protected class ModelBuilderSessionState implements ModelProblemCollector { | |
| new ConcurrentHashMap<>(64), | |
| List.of(), | |
| repos(request), | |
| - repos(request), | |
| - new LinkedHashSet<>()); | |
| + repos(request)); | |
| } | |
| static List<RemoteRepository> repos(ModelBuilderRequest request) { | |
| @@ -310,8 +290,7 @@ private ModelBuilderSessionState( | |
| Map<GAKey, Set<ModelSource>> mappedSources, | |
| List<RemoteRepository> pomRepositories, | |
| List<RemoteRepository> externalRepositories, | |
| - List<RemoteRepository> repositories, | |
| - Set<String> parentChain) { | |
| + List<RemoteRepository> repositories) { | |
| this.session = session; | |
| this.request = request; | |
| this.result = result; | |
| @@ -320,7 +299,6 @@ private ModelBuilderSessionState( | |
| this.pomRepositories = pomRepositories; | |
| this.externalRepositories = externalRepositories; | |
| this.repositories = repositories; | |
| - this.parentChain = parentChain; | |
| this.result.setSource(this.request.getSource()); | |
| } | |
| @@ -343,18 +321,8 @@ ModelBuilderSessionState derive(ModelBuilderRequest request, DefaultModelBuilder | |
| if (session != request.getSession()) { | |
| throw new IllegalArgumentException("Session mismatch"); | |
| } | |
| - // Create a new parentChain for each derived session to prevent cycle detection issues | |
| - // The parentChain now contains both GAV coordinates and file paths | |
| return new ModelBuilderSessionState( | |
| - session, | |
| - request, | |
| - result, | |
| - dag, | |
| - mappedSources, | |
| - pomRepositories, | |
| - externalRepositories, | |
| - repositories, | |
| - new LinkedHashSet<>()); | |
| + session, request, result, dag, mappedSources, pomRepositories, externalRepositories, repositories); | |
| } | |
| @Override | |
| @@ -591,12 +559,6 @@ Model transformFileToRaw(Model model) { | |
| if (newDep != null) { | |
| changed = true; | |
| } | |
| - } else if (dep.getGroupId() == null) { | |
| - // Handle missing groupId when version is present | |
| - newDep = inferDependencyGroupId(model, dep); | |
| - if (newDep != null) { | |
| - changed = true; | |
| - } | |
| } | |
| newDeps.add(newDep == null ? dep : newDep); | |
| } | |
| @@ -628,113 +590,10 @@ private Dependency inferDependencyVersion(Model model, Dependency dep) { | |
| return depBuilder.build(); | |
| } | |
| - private Dependency inferDependencyGroupId(Model model, Dependency dep) { | |
| - Model depModel = getRawModel(model.getPomFile(), dep.getGroupId(), dep.getArtifactId()); | |
| - if (depModel == null) { | |
| - return null; | |
| - } | |
| - Dependency.Builder depBuilder = Dependency.newBuilder(dep); | |
| - String depGroupId = depModel.getGroupId(); | |
| - InputLocation groupIdLocation = depModel.getLocation("groupId"); | |
| - if (depGroupId == null && depModel.getParent() != null) { | |
| - depGroupId = depModel.getParent().getGroupId(); | |
| - groupIdLocation = depModel.getParent().getLocation("groupId"); | |
| - } | |
| - depBuilder.groupId(depGroupId).location("groupId", groupIdLocation); | |
| - return depBuilder.build(); | |
| - } | |
| - | |
| String replaceCiFriendlyVersion(Map<String, String> properties, String version) { | |
| return version != null ? interpolator.interpolate(version, properties::get) : null; | |
| } | |
| - /** | |
| - * Get enhanced properties that include profile-aware property resolution. | |
| - * This method activates profiles to ensure that properties defined in profiles | |
| - * are available for CI-friendly version processing and repository URL interpolation. | |
| - * It also includes directory-related properties that may be needed during profile activation. | |
| - */ | |
| - private Map<String, String> getEnhancedProperties(Model model, Path rootDirectory) { | |
| - Map<String, String> properties = new HashMap<>(); | |
| - | |
| - // Add directory-specific properties first, as they may be needed for profile activation | |
| - if (model.getProjectDirectory() != null) { | |
| - String basedir = model.getProjectDirectory().toString(); | |
| - String basedirUri = model.getProjectDirectory().toUri().toString(); | |
| - properties.put("basedir", basedir); | |
| - properties.put("project.basedir", basedir); | |
| - properties.put("project.basedir.uri", basedirUri); | |
| - } | |
| - try { | |
| - String root = rootDirectory.toString(); | |
| - String rootUri = rootDirectory.toUri().toString(); | |
| - properties.put("project.rootDirectory", root); | |
| - properties.put("project.rootDirectory.uri", rootUri); | |
| - } catch (IllegalStateException e) { | |
| - // Root directory not available, continue without it | |
| - } | |
| - | |
| - // Handle root vs non-root project properties with profile activation | |
| - if (!Objects.equals(rootDirectory, model.getProjectDirectory())) { | |
| - Path rootModelPath = modelProcessor.locateExistingPom(rootDirectory); | |
| - if (rootModelPath != null) { | |
| - Model rootModel = derive(Sources.buildSource(rootModelPath)).readFileModel(); | |
| - properties.putAll(getPropertiesWithProfiles(rootModel, properties)); | |
| - } | |
| - } else { | |
| - properties.putAll(getPropertiesWithProfiles(model, properties)); | |
| - } | |
| - | |
| - return properties; | |
| - } | |
| - | |
| - /** | |
| - * Get properties from a model including properties from activated profiles. | |
| - * This performs lightweight profile activation to merge profile properties. | |
| - * | |
| - * @param model the model to get properties from | |
| - * @param baseProperties base properties (including directory properties) to include in profile activation context | |
| - */ | |
| - private Map<String, String> getPropertiesWithProfiles(Model model, Map<String, String> baseProperties) { | |
| - Map<String, String> properties = new HashMap<>(); | |
| - | |
| - // Start with base properties (including directory properties) | |
| - properties.putAll(baseProperties); | |
| - | |
| - // Add model properties | |
| - properties.putAll(model.getProperties()); | |
| - | |
| - try { | |
| - // Create a profile activation context for this model with base properties available | |
| - DefaultProfileActivationContext profileContext = getProfileActivationContext(request, model); | |
| - | |
| - // Activate profiles and merge their properties | |
| - List<Profile> activeProfiles = getActiveProfiles(model.getProfiles(), profileContext); | |
| - | |
| - for (Profile profile : activeProfiles) { | |
| - properties.putAll(profile.getProperties()); | |
| - } | |
| - } catch (Exception e) { | |
| - // If profile activation fails, log a warning but continue with base properties | |
| - // This ensures that CI-friendly versions still work even if profile activation has issues | |
| - logger.warn("Failed to activate profiles for CI-friendly version processing: {}", e.getMessage()); | |
| - logger.debug("Profile activation failure details", e); | |
| - } | |
| - | |
| - // User properties override everything | |
| - properties.putAll(session.getEffectiveProperties()); | |
| - | |
| - return properties; | |
| - } | |
| - | |
| - /** | |
| - * Convenience method for getting properties with profiles without additional base properties. | |
| - * This is a backward compatibility method that provides an empty base properties map. | |
| - */ | |
| - private Map<String, String> getPropertiesWithProfiles(Model model) { | |
| - return getPropertiesWithProfiles(model, new HashMap<>()); | |
| - } | |
| - | |
| private void buildBuildPom() throws ModelBuilderException { | |
| // Retrieve and normalize the source path, ensuring it's non-null and in absolute form | |
| Path top = request.getSource().getPath(); | |
| @@ -782,13 +641,6 @@ private void buildBuildPom() throws ModelBuilderException { | |
| mbs.buildEffectiveModel(new LinkedHashSet<>()); | |
| } catch (ModelBuilderException e) { | |
| // gathered with problem collector | |
| - // Propagate problems from child session to parent session | |
| - for (var problem : e.getResult() | |
| - .getProblemCollector() | |
| - .problems() | |
| - .toList()) { | |
| - getProblemCollector().reportProblem(problem); | |
| - } | |
| } catch (RuntimeException t) { | |
| exceptions.add(t); | |
| } finally { | |
| @@ -987,48 +839,22 @@ void buildEffectiveModel(Collection<String> importIds) throws ModelBuilderExcept | |
| } | |
| } | |
| - Model readParent( | |
| - Model childModel, | |
| - Parent parent, | |
| - DefaultProfileActivationContext profileActivationContext, | |
| - Set<String> parentChain) { | |
| + Model readParent(Model childModel, DefaultProfileActivationContext profileActivationContext) { | |
| Model parentModel; | |
| + Parent parent = childModel.getParent(); | |
| if (parent != null) { | |
| - // Check for circular parent resolution using model IDs | |
| - String parentId = parent.getGroupId() + ":" + parent.getArtifactId() + ":" + parent.getVersion(); | |
| - if (!parentChain.add(parentId)) { | |
| - StringBuilder message = new StringBuilder("The parents form a cycle: "); | |
| - for (String id : parentChain) { | |
| - message.append(id).append(" -> "); | |
| - } | |
| - message.append(parentId); | |
| - | |
| - add(Severity.FATAL, Version.BASE, message.toString()); | |
| - throw newModelBuilderException(); | |
| - } | |
| - | |
| - try { | |
| - parentModel = resolveParent(childModel, parent, profileActivationContext, parentChain); | |
| + parentModel = resolveParent(childModel, profileActivationContext); | |
| - if (!"pom".equals(parentModel.getPackaging())) { | |
| - add( | |
| - Severity.ERROR, | |
| - Version.BASE, | |
| - "Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint(parentModel) | |
| - + ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"", | |
| - parentModel.getLocation("packaging")); | |
| - } | |
| - result.setParentModel(parentModel); | |
| - | |
| - // Recursively read the parent's parent | |
| - if (parentModel.getParent() != null) { | |
| - readParent(parentModel, parentModel.getParent(), profileActivationContext, parentChain); | |
| - } | |
| - } finally { | |
| - // Remove from chain when done processing this parent | |
| - parentChain.remove(parentId); | |
| + if (!"pom".equals(parentModel.getPackaging())) { | |
| + add( | |
| + Severity.ERROR, | |
| + Version.BASE, | |
| + "Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint(parentModel) | |
| + + ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"", | |
| + parentModel.getLocation("packaging")); | |
| } | |
| + result.setParentModel(parentModel); | |
| } else { | |
| String superModelVersion = childModel.getModelVersion(); | |
| if (superModelVersion == null || !KNOWN_MODEL_VERSIONS.contains(superModelVersion)) { | |
| @@ -1043,32 +869,23 @@ Model readParent( | |
| return parentModel; | |
| } | |
| - private Model resolveParent( | |
| - Model childModel, | |
| - Parent parent, | |
| - DefaultProfileActivationContext profileActivationContext, | |
| - Set<String> parentChain) | |
| + private Model resolveParent(Model childModel, DefaultProfileActivationContext profileActivationContext) | |
| throws ModelBuilderException { | |
| Model parentModel = null; | |
| if (isBuildRequest()) { | |
| - parentModel = readParentLocally(childModel, parent, profileActivationContext, parentChain); | |
| + parentModel = readParentLocally(childModel, profileActivationContext); | |
| } | |
| if (parentModel == null) { | |
| - parentModel = resolveAndReadParentExternally(childModel, parent, profileActivationContext, parentChain); | |
| + parentModel = resolveAndReadParentExternally(childModel, profileActivationContext); | |
| } | |
| return parentModel; | |
| } | |
| - private Model readParentLocally( | |
| - Model childModel, | |
| - Parent parent, | |
| - DefaultProfileActivationContext profileActivationContext, | |
| - Set<String> parentChain) | |
| + private Model readParentLocally(Model childModel, DefaultProfileActivationContext profileActivationContext) | |
| throws ModelBuilderException { | |
| ModelSource candidateSource; | |
| - boolean isParentOrSimpleMixin = !(parent instanceof Mixin) | |
| - || (((Mixin) parent).getClassifier() == null && ((Mixin) parent).getExtension() == null); | |
| + Parent parent = childModel.getParent(); | |
| String parentPath = parent.getRelativePath(); | |
| if (request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_PROJECT) { | |
| if (parentPath != null && !parentPath.isEmpty()) { | |
| @@ -1077,16 +894,14 @@ private Model readParentLocally( | |
| wrongParentRelativePath(childModel); | |
| return null; | |
| } | |
| - } else if (isParentOrSimpleMixin) { | |
| + } else { | |
| candidateSource = | |
| resolveReactorModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion()); | |
| if (candidateSource == null && parentPath == null) { | |
| candidateSource = request.getSource().resolve(modelProcessor::locateExistingPom, ".."); | |
| } | |
| - } else { | |
| - candidateSource = null; | |
| } | |
| - } else if (isParentOrSimpleMixin) { | |
| + } else { | |
| candidateSource = resolveReactorModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion()); | |
| if (candidateSource == null) { | |
| if (parentPath == null) { | |
| @@ -1096,87 +911,66 @@ private Model readParentLocally( | |
| candidateSource = request.getSource().resolve(modelProcessor::locateExistingPom, parentPath); | |
| } | |
| } | |
| - } else { | |
| - candidateSource = null; | |
| } | |
| if (candidateSource == null) { | |
| return null; | |
| } | |
| - // Check for circular parent resolution using source locations (file paths) | |
| - // This must be done BEFORE calling derive() to prevent StackOverflowError | |
| - String sourceLocation = candidateSource.getLocation(); | |
| + ModelBuilderSessionState derived = derive(candidateSource); | |
| + Model candidateModel = derived.readAsParentModel(profileActivationContext); | |
| + addActivePomProfiles(derived.result.getActivePomProfiles()); | |
| - if (!parentChain.add(sourceLocation)) { | |
| - StringBuilder message = new StringBuilder("The parents form a cycle: "); | |
| - for (String location : parentChain) { | |
| - message.append(location).append(" -> "); | |
| - } | |
| - message.append(sourceLocation); | |
| + String groupId = getGroupId(candidateModel); | |
| + String artifactId = candidateModel.getArtifactId(); | |
| + String version = getVersion(candidateModel); | |
| - add(Severity.FATAL, Version.BASE, message.toString()); | |
| - throw newModelBuilderException(); | |
| + // Ensure that relative path and GA match, if both are provided | |
| + if (groupId == null | |
| + || !groupId.equals(parent.getGroupId()) | |
| + || artifactId == null | |
| + || !artifactId.equals(parent.getArtifactId())) { | |
| + mismatchRelativePathAndGA(childModel, groupId, artifactId); | |
| + return null; | |
| } | |
| - try { | |
| - ModelBuilderSessionState derived = derive(candidateSource); | |
| - Model candidateModel = derived.readAsParentModel(profileActivationContext, parentChain); | |
| - addActivePomProfiles(derived.result.getActivePomProfiles()); | |
| - | |
| - String groupId = getGroupId(candidateModel); | |
| - String artifactId = candidateModel.getArtifactId(); | |
| - String version = getVersion(candidateModel); | |
| - | |
| - // Ensure that relative path and GA match, if both are provided | |
| - if (parent.getGroupId() != null && (groupId == null || !groupId.equals(parent.getGroupId())) | |
| - || parent.getArtifactId() != null | |
| - && (artifactId == null || !artifactId.equals(parent.getArtifactId()))) { | |
| - mismatchRelativePathAndGA(childModel, parent, groupId, artifactId); | |
| - return null; | |
| - } | |
| + if (version != null && parent.getVersion() != null && !version.equals(parent.getVersion())) { | |
| + try { | |
| + VersionRange parentRange = versionParser.parseVersionRange(parent.getVersion()); | |
| + if (!parentRange.contains(versionParser.parseVersion(version))) { | |
| + // version skew drop back to resolution from the repository | |
| + return null; | |
| + } | |
| - if (version != null && parent.getVersion() != null && !version.equals(parent.getVersion())) { | |
| - try { | |
| - VersionRange parentRange = versionParser.parseVersionRange(parent.getVersion()); | |
| - if (!parentRange.contains(versionParser.parseVersion(version))) { | |
| - // version skew drop back to resolution from the repository | |
| - return null; | |
| - } | |
| + // Validate versions aren't inherited when using parent ranges the same way as when read externally. | |
| + String rawChildModelVersion = childModel.getVersion(); | |
| - // Validate versions aren't inherited when using parent ranges the same way as when read | |
| - // externally. | |
| - String rawChildModelVersion = childModel.getVersion(); | |
| + if (rawChildModelVersion == null) { | |
| + // Message below is checked for in the MNG-2199 core IT. | |
| + add(Severity.FATAL, Version.V31, "Version must be a constant", childModel.getLocation("")); | |
| - if (rawChildModelVersion == null) { | |
| + } else { | |
| + if (rawChildVersionReferencesParent(rawChildModelVersion)) { | |
| // Message below is checked for in the MNG-2199 core IT. | |
| - add(Severity.FATAL, Version.V31, "Version must be a constant", childModel.getLocation("")); | |
| - | |
| - } else { | |
| - if (rawChildVersionReferencesParent(rawChildModelVersion)) { | |
| - // Message below is checked for in the MNG-2199 core IT. | |
| - add( | |
| - Severity.FATAL, | |
| - Version.V31, | |
| - "Version must be a constant", | |
| - childModel.getLocation("version")); | |
| - } | |
| + add( | |
| + Severity.FATAL, | |
| + Version.V31, | |
| + "Version must be a constant", | |
| + childModel.getLocation("version")); | |
| } | |
| - | |
| - // MNG-2199: What else to check here ? | |
| - } catch (VersionParserException e) { | |
| - // invalid version range, so drop back to resolution from the repository | |
| - return null; | |
| } | |
| + | |
| + // MNG-2199: What else to check here ? | |
| + } catch (VersionParserException e) { | |
| + // invalid version range, so drop back to resolution from the repository | |
| + return null; | |
| } | |
| - return candidateModel; | |
| - } finally { | |
| - // Remove the source location from the chain when we're done processing this parent | |
| - parentChain.remove(sourceLocation); | |
| } | |
| + return candidateModel; | |
| } | |
| - private void mismatchRelativePathAndGA(Model childModel, Parent parent, String groupId, String artifactId) { | |
| + private void mismatchRelativePathAndGA(Model childModel, String groupId, String artifactId) { | |
| + Parent parent = childModel.getParent(); | |
| StringBuilder buffer = new StringBuilder(256); | |
| buffer.append("'parent.relativePath'"); | |
| if (childModel != getRootModel()) { | |
| @@ -1207,20 +1001,16 @@ private void wrongParentRelativePath(Model childModel) { | |
| add(Severity.FATAL, Version.BASE, buffer.toString(), parent.getLocation("")); | |
| } | |
| - Model resolveAndReadParentExternally( | |
| - Model childModel, | |
| - Parent parent, | |
| - DefaultProfileActivationContext profileActivationContext, | |
| - Set<String> parentChain) | |
| + Model resolveAndReadParentExternally(Model childModel, DefaultProfileActivationContext profileActivationContext) | |
| throws ModelBuilderException { | |
| ModelBuilderRequest request = this.request; | |
| setSource(childModel); | |
| + Parent parent = childModel.getParent(); | |
| + | |
| String groupId = parent.getGroupId(); | |
| String artifactId = parent.getArtifactId(); | |
| String version = parent.getVersion(); | |
| - String classifier = parent instanceof Mixin ? ((Mixin) parent).getClassifier() : null; | |
| - String extension = parent instanceof Mixin ? ((Mixin) parent).getExtension() : null; | |
| // add repositories specified by the current model so that we can resolve the parent | |
| if (!childModel.getRepositories().isEmpty()) { | |
| @@ -1238,23 +1028,12 @@ Model resolveAndReadParentExternally( | |
| ModelSource modelSource; | |
| try { | |
| - modelSource = classifier == null && extension == null | |
| - ? resolveReactorModel(groupId, artifactId, version) | |
| - : null; | |
| + modelSource = resolveReactorModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion()); | |
| if (modelSource == null) { | |
| - ModelResolver.ModelResolverRequest req = new ModelResolver.ModelResolverRequest( | |
| - request.getSession(), | |
| - null, | |
| - repositories, | |
| - groupId, | |
| - artifactId, | |
| - version, | |
| - classifier, | |
| - extension != null ? extension : "pom"); | |
| - ModelResolver.ModelResolverResult result = modelResolver.resolveModel(req); | |
| - modelSource = result.source(); | |
| - if (result.version() != null) { | |
| - parent = parent.withVersion(result.version()); | |
| + AtomicReference<Parent> modified = new AtomicReference<>(); | |
| + modelSource = modelResolver.resolveModel(request.getSession(), repositories, parent, modified); | |
| + if (modified.get() != null) { | |
| + parent = modified.get(); | |
| } | |
| } | |
| } catch (ModelResolverException e) { | |
| @@ -1281,7 +1060,7 @@ Model resolveAndReadParentExternally( | |
| .source(modelSource) | |
| .build(); | |
| - Model parentModel = derive(lenientRequest).readAsParentModel(profileActivationContext, parentChain); | |
| + Model parentModel = derive(lenientRequest).readAsParentModel(profileActivationContext); | |
| if (!parent.getVersion().equals(version)) { | |
| String rawChildModelVersion = childModel.getVersion(); | |
| @@ -1370,8 +1149,7 @@ private Model readEffectiveModel() throws ModelBuilderException { | |
| profileActivationContext.setUserProperties(profileProps); | |
| } | |
| - Model parentModel = readParent( | |
| - activatedFileModel, activatedFileModel.getParent(), profileActivationContext, parentChain); | |
| + Model parentModel = readParent(activatedFileModel, profileActivationContext); | |
| // Now that we have read the parent, we can set the relative | |
| // path correctly if it was not set in the input model | |
| @@ -1393,15 +1171,6 @@ private Model readEffectiveModel() throws ModelBuilderException { | |
| Model model = inheritanceAssembler.assembleModelInheritance(inputModel, parentModel, request, this); | |
| - // Mixins | |
| - for (Mixin mixin : model.getMixins()) { | |
| - Model parent = resolveParent(model, mixin, profileActivationContext, parentChain); | |
| - model = inheritanceAssembler.assembleModelInheritance(model, parent, request, this); | |
| - } | |
| - | |
| - // model normalization | |
| - model = modelNormalizer.mergeDuplicates(model, request, this); | |
| - | |
| // profile activation | |
| profileActivationContext.setModel(model); | |
| @@ -1484,7 +1253,6 @@ Model doReadFileModel() throws ModelBuilderException { | |
| model = modelProcessor.read(XmlReaderRequest.builder() | |
| .strict(strict) | |
| .location(modelSource.getLocation()) | |
| - .modelId(modelSource.getModelId()) | |
| .path(modelSource.getPath()) | |
| .rootDirectory(rootDirectory) | |
| .inputStream(is) | |
| @@ -1498,7 +1266,6 @@ Model doReadFileModel() throws ModelBuilderException { | |
| model = modelProcessor.read(XmlReaderRequest.builder() | |
| .strict(false) | |
| .location(modelSource.getLocation()) | |
| - .modelId(modelSource.getModelId()) | |
| .path(modelSource.getPath()) | |
| .rootDirectory(rootDirectory) | |
| .inputStream(is) | |
| @@ -1515,6 +1282,19 @@ Model doReadFileModel() throws ModelBuilderException { | |
| "Malformed POM " + modelSource.getLocation() + ": " + e.getMessage(), | |
| e); | |
| } | |
| + | |
| + InputLocation loc = model.getLocation(""); | |
| + InputSource v4src = loc != null ? loc.getSource() : null; | |
| + if (v4src != null) { | |
| + try { | |
| + Field field = InputSource.class.getDeclaredField("modelId"); | |
| + field.setAccessible(true); | |
| + field.set(v4src, ModelProblemUtils.toId(model)); | |
| + } catch (Throwable t) { | |
| + // TODO: use a lazy source ? | |
| + throw new IllegalStateException("Unable to set modelId on InputSource", t); | |
| + } | |
| + } | |
| } catch (XmlReaderException e) { | |
| add( | |
| Severity.FATAL, | |
| @@ -1575,7 +1355,7 @@ Model doReadFileModel() throws ModelBuilderException { | |
| .version(parentVersion) | |
| .build()); | |
| } else { | |
| - mismatchRelativePathAndGA(model, parent, parentGroupId, parentArtifactId); | |
| + mismatchRelativePathAndGA(model, parentGroupId, parentArtifactId); | |
| } | |
| } else { | |
| if (!MODEL_VERSION_4_0_0.equals(model.getModelVersion()) && path != null) { | |
| @@ -1586,7 +1366,7 @@ Model doReadFileModel() throws ModelBuilderException { | |
| } | |
| // subprojects discovery | |
| - if (!hasSubprojectsDefined(model) | |
| + if (getSubprojects(model).isEmpty() | |
| // only discover subprojects if POM > 4.0.0 | |
| && !MODEL_VERSION_4_0_0.equals(model.getModelVersion()) | |
| // and if packaging is POM (we check type, but the session is not yet available, | |
| @@ -1610,11 +1390,21 @@ Model doReadFileModel() throws ModelBuilderException { | |
| } | |
| } | |
| - // Enhanced property resolution with profile activation for CI-friendly versions and repository URLs | |
| - // This includes directory properties, profile properties, and user properties | |
| - Map<String, String> properties = getEnhancedProperties(model, rootDirectory); | |
| - | |
| - // CI friendly version processing with profile-aware properties | |
| + // CI friendly version | |
| + // All expressions are interpolated using user properties and properties | |
| + // defined on the root project. | |
| + Map<String, String> properties = new HashMap<>(); | |
| + if (!Objects.equals(rootDirectory, model.getProjectDirectory())) { | |
| + Path rootModelPath = modelProcessor.locateExistingPom(rootDirectory); | |
| + if (rootModelPath != null) { | |
| + Model rootModel = | |
| + derive(Sources.buildSource(rootModelPath)).readFileModel(); | |
| + properties.putAll(rootModel.getProperties()); | |
| + } | |
| + } else { | |
| + properties.putAll(model.getProperties()); | |
| + } | |
| + properties.putAll(session.getEffectiveProperties()); | |
| model = model.with() | |
| .version(replaceCiFriendlyVersion(properties, model.getVersion())) | |
| .parent( | |
| @@ -1625,15 +1415,6 @@ Model doReadFileModel() throws ModelBuilderException { | |
| model.getParent().getVersion())) | |
| : null) | |
| .build(); | |
| - | |
| - // Repository URL interpolation with the same profile-aware properties | |
| - UnaryOperator<String> callback = properties::get; | |
| - model = model.with() | |
| - .repositories(interpolateRepository(model.getRepositories(), callback)) | |
| - .pluginRepositories(interpolateRepository(model.getPluginRepositories(), callback)) | |
| - .profiles(map(model.getProfiles(), this::interpolateRepository, callback)) | |
| - .distributionManagement(interpolateRepository(model.getDistributionManagement(), callback)) | |
| - .build(); | |
| // Override model properties with user properties | |
| Map<String, String> newProps = merge(model.getProperties(), session.getUserProperties()); | |
| if (newProps != null) { | |
| @@ -1664,42 +1445,6 @@ Model doReadFileModel() throws ModelBuilderException { | |
| return model; | |
| } | |
| - private DistributionManagement interpolateRepository( | |
| - DistributionManagement distributionManagement, UnaryOperator<String> callback) { | |
| - return distributionManagement == null | |
| - ? null | |
| - : distributionManagement | |
| - .with() | |
| - .repository((DeploymentRepository) | |
| - interpolateRepository(distributionManagement.getRepository(), callback)) | |
| - .snapshotRepository((DeploymentRepository) | |
| - interpolateRepository(distributionManagement.getSnapshotRepository(), callback)) | |
| - .build(); | |
| - } | |
| - | |
| - private Profile interpolateRepository(Profile profile, UnaryOperator<String> callback) { | |
| - return profile == null | |
| - ? null | |
| - : profile.with() | |
| - .repositories(interpolateRepository(profile.getRepositories(), callback)) | |
| - .pluginRepositories(interpolateRepository(profile.getPluginRepositories(), callback)) | |
| - .build(); | |
| - } | |
| - | |
| - private List<Repository> interpolateRepository(List<Repository> repositories, UnaryOperator<String> callback) { | |
| - return map(repositories, this::interpolateRepository, callback); | |
| - } | |
| - | |
| - private Repository interpolateRepository(Repository repository, UnaryOperator<String> callback) { | |
| - return repository == null | |
| - ? null | |
| - : repository | |
| - .with() | |
| - .id(interpolator.interpolate(repository.getId(), callback)) | |
| - .url(interpolator.interpolate(repository.getUrl(), callback)) | |
| - .build(); | |
| - } | |
| - | |
| /** | |
| * Merges a list of model profiles with user-defined properties. | |
| * For each property defined in both the model and user properties, the user property value | |
| @@ -1790,10 +1535,9 @@ private Model doReadRawModel() throws ModelBuilderException { | |
| private record ParentModelWithProfiles(Model model, List<Profile> activatedProfiles) {} | |
| /** | |
| - * Reads the request source's parent with cycle detection. | |
| + * Reads the request source's parent. | |
| */ | |
| - Model readAsParentModel(DefaultProfileActivationContext profileActivationContext, Set<String> parentChain) | |
| - throws ModelBuilderException { | |
| + Model readAsParentModel(DefaultProfileActivationContext profileActivationContext) throws ModelBuilderException { | |
| Map<DefaultProfileActivationContext.Record, ParentModelWithProfiles> parentsPerContext = | |
| cache(request.getSource(), PARENT, ConcurrentHashMap::new); | |
| @@ -1820,7 +1564,7 @@ Model readAsParentModel(DefaultProfileActivationContext profileActivationContext | |
| // into the parent recording context to maintain clean cache keys and avoid | |
| // over-recording during parent model processing. | |
| DefaultProfileActivationContext ctx = profileActivationContext.start(); | |
| - ParentModelWithProfiles modelWithProfiles = doReadAsParentModel(ctx, parentChain); | |
| + ParentModelWithProfiles modelWithProfiles = doReadAsParentModel(ctx); | |
| DefaultProfileActivationContext.Record record = ctx.stop(); | |
| replayRecordIntoContext(record, profileActivationContext); | |
| @@ -1830,12 +1574,10 @@ Model readAsParentModel(DefaultProfileActivationContext profileActivationContext | |
| } | |
| private ParentModelWithProfiles doReadAsParentModel( | |
| - DefaultProfileActivationContext childProfileActivationContext, Set<String> parentChain) | |
| - throws ModelBuilderException { | |
| + DefaultProfileActivationContext childProfileActivationContext) throws ModelBuilderException { | |
| Model raw = readRawModel(); | |
| - Model parentData = readParent(raw, raw.getParent(), childProfileActivationContext, parentChain); | |
| - DefaultInheritanceAssembler defaultInheritanceAssembler = | |
| - new DefaultInheritanceAssembler(new DefaultInheritanceAssembler.InheritanceModelMerger() { | |
| + Model parentData = readParent(raw, childProfileActivationContext); | |
| + Model parent = new DefaultInheritanceAssembler(new DefaultInheritanceAssembler.InheritanceModelMerger() { | |
| @Override | |
| protected void mergeModel_Modules( | |
| Model.Builder builder, | |
| @@ -1851,12 +1593,8 @@ protected void mergeModel_Subprojects( | |
| Model source, | |
| boolean sourceDominant, | |
| Map<Object, Object> context) {} | |
| - }); | |
| - Model parent = defaultInheritanceAssembler.assembleModelInheritance(raw, parentData, request, this); | |
| - for (Mixin mixin : parent.getMixins()) { | |
| - Model parentModel = resolveParent(parent, mixin, childProfileActivationContext, parentChain); | |
| - parent = defaultInheritanceAssembler.assembleModelInheritance(parent, parentModel, request, this); | |
| - } | |
| + }) | |
| + .assembleModelInheritance(raw, parentData, request, this); | |
| // Profile injection SHOULD be performed on parent models to ensure | |
| // that profile content becomes part of the parent model before inheritance. | |
| @@ -2164,20 +1902,6 @@ private static List<String> getSubprojects(Model activated) { | |
| return subprojects; | |
| } | |
| - /** | |
| - * Checks if subprojects are explicitly defined in the main model. | |
| - * This method distinguishes between: | |
| - * 1. No subprojects/modules element present - returns false (should auto-discover) | |
| - * 2. Empty subprojects/modules element present - returns true (should NOT auto-discover) | |
| - * 3. Non-empty subprojects/modules - returns true (should NOT auto-discover) | |
| - */ | |
| - @SuppressWarnings("deprecation") | |
| - private static boolean hasSubprojectsDefined(Model model) { | |
| - // Only consider the main model: profiles do not influence auto-discovery | |
| - // Inline the check for explicit elements using location tracking | |
| - return model.getLocation("subprojects") != null || model.getLocation("modules") != null; | |
| - } | |
| - | |
| @Override | |
| public Model buildRawModel(ModelBuilderRequest request) throws ModelBuilderException { | |
| RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(request.getSession(), request); | |
| @@ -2189,13 +1913,6 @@ public Model buildRawModel(ModelBuilderRequest request) throws ModelBuilderExcep | |
| } | |
| return model; | |
| } finally { | |
| - // Clean up REQUEST_SCOPED cache entries for raw model building as well | |
| - try { | |
| - clearRequestScopedCache(request); | |
| - } catch (Exception e) { | |
| - // Log but don't fail the build due to cache cleanup issues | |
| - logger.debug("Failed to clear REQUEST_SCOPED cache for raw model request: {}", request, e); | |
| - } | |
| RequestTraceHelper.exit(trace); | |
| } | |
| } | |
| @@ -2391,9 +2108,7 @@ public RequestTrace getTrace() { | |
| @Override | |
| public CacheRetention getCacheRetention() { | |
| - return source instanceof CacheMetadata cacheMetadata | |
| - ? cacheMetadata.getCacheRetention() | |
| - : CacheRetention.REQUEST_SCOPED; | |
| + return source instanceof CacheMetadata cacheMetadata ? cacheMetadata.getCacheRetention() : null; | |
| } | |
| @Override | |
| @@ -2521,71 +2236,4 @@ Set<String> getContexts() { | |
| return contexts; | |
| } | |
| } | |
| - | |
| - /** | |
| - * Clears REQUEST_SCOPED cache entries for a specific request. | |
| - * <p> | |
| - * The method identifies the outer request and removes the corresponding cache entry from the session data. | |
| - * | |
| - * @param req the request whose REQUEST_SCOPED cache should be cleared | |
| - * @param <REQ> the request type | |
| - */ | |
| - private <REQ extends Request<?>> void clearRequestScopedCache(REQ req) { | |
| - if (req.getSession() instanceof Session session) { | |
| - // Use the same key as DefaultRequestCache | |
| - SessionData.Key<Cache> key = SessionData.key(Cache.class, CacheMetadata.class); | |
| - | |
| - // Get the outer request key using the same logic as DefaultRequestCache | |
| - Object outerRequestKey = getOuterRequest(req); | |
| - | |
| - Cache<Object, Object> caches = session.getData().get(key); | |
| - if (caches != null) { | |
| - Object removedCache = caches.get(outerRequestKey); | |
| - if (removedCache instanceof Cache<?, ?> map) { | |
| - int beforeSize = map.size(); | |
| - map.removeIf((k, v) -> !(k instanceof RgavCacheKey) && !(k instanceof SourceCacheKey)); | |
| - int afterSize = map.size(); | |
| - if (logger.isDebugEnabled()) { | |
| - logger.debug( | |
| - "Cleared REQUEST_SCOPED cache for request: {}, removed {} entries, remaining entries: {}", | |
| - outerRequestKey.getClass().getSimpleName(), | |
| - afterSize - beforeSize, | |
| - afterSize); | |
| - } | |
| - } | |
| - } | |
| - } | |
| - } | |
| - | |
| - /** | |
| - * Gets the outer request for cache key purposes. | |
| - * This replicates the logic from DefaultRequestCache.doGetOuterRequest(). | |
| - */ | |
| - private Object getOuterRequest(Request<?> req) { | |
| - RequestTrace trace = req.getTrace(); | |
| - if (trace != null) { | |
| - RequestTrace parent = trace.parent(); | |
| - if (parent != null && parent.data() instanceof Request<?> parentRequest) { | |
| - return getOuterRequest(parentRequest); | |
| - } | |
| - } | |
| - return req; | |
| - } | |
| - | |
| - private static <T, A> List<T> map(List<T> resources, BiFunction<T, A, T> mapper, A argument) { | |
| - List<T> newResources = null; | |
| - if (resources != null) { | |
| - for (int i = 0; i < resources.size(); i++) { | |
| - T resource = resources.get(i); | |
| - T newResource = mapper.apply(resource, argument); | |
| - if (newResource != resource) { | |
| - if (newResources == null) { | |
| - newResources = new ArrayList<>(resources); | |
| - } | |
| - newResources.set(i, newResource); | |
| - } | |
| - } | |
| - } | |
| - return newResources; | |
| - } | |
| } | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelObjectPool.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelObjectPool.java | |
| deleted file mode 100644 | |
| index bec34fe0fa..0000000000 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelObjectPool.java | |
| +++ /dev/null | |
| @@ -1,349 +0,0 @@ | |
| -/* | |
| - * Licensed to the Apache Software Foundation (ASF) under one | |
| - * or more contributor license agreements. See the NOTICE file | |
| - * distributed with this work for additional information | |
| - * regarding copyright ownership. The ASF licenses this file | |
| - * to you under the Apache License, Version 2.0 (the | |
| - * "License"); you may not use this file except in compliance | |
| - * with the License. You may obtain a copy of the License at | |
| - * | |
| - * http://www.apache.org/licenses/LICENSE-2.0 | |
| - * | |
| - * Unless required by applicable law or agreed to in writing, | |
| - * software distributed under the License is distributed on an | |
| - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| - * KIND, either express or implied. See the License for the | |
| - * specific language governing permissions and limitations | |
| - * under the License. | |
| - */ | |
| -package org.apache.maven.impl.model; | |
| - | |
| -import java.util.Arrays; | |
| -import java.util.Map; | |
| -import java.util.Objects; | |
| -import java.util.Set; | |
| -import java.util.concurrent.ConcurrentHashMap; | |
| -import java.util.concurrent.atomic.AtomicLong; | |
| -import java.util.stream.Collectors; | |
| - | |
| -import org.apache.maven.api.Constants; | |
| -import org.apache.maven.api.model.Dependency; | |
| -import org.apache.maven.api.model.ModelObjectProcessor; | |
| -import org.apache.maven.impl.cache.Cache; | |
| -import org.slf4j.Logger; | |
| -import org.slf4j.LoggerFactory; | |
| - | |
| -/** | |
| - * Default implementation of ModelObjectProcessor that provides memory optimization | |
| - * through object pooling and interning. | |
| - * | |
| - * <p>This implementation can pool any model object type based on configuration. | |
| - * By default, it pools {@link Dependency} objects, which are frequently duplicated | |
| - * in large Maven projects. Other model objects are passed through unchanged unless | |
| - * explicitly configured for pooling.</p> | |
| - * | |
| - * <p>The pool uses configurable reference types and provides thread-safe access | |
| - * through ConcurrentHashMap-based caches.</p> | |
| - * | |
| - * @since 4.0.0 | |
| - */ | |
| -public class DefaultModelObjectPool implements ModelObjectProcessor { | |
| - | |
| - // Cache for each pooled object type | |
| - private static final Map<Class<?>, Cache<PoolKey, Object>> OBJECT_POOLS = new ConcurrentHashMap<>(); | |
| - | |
| - // Statistics tracking | |
| - private static final Map<Class<?>, AtomicLong> TOTAL_CALLS = new ConcurrentHashMap<>(); | |
| - private static final Map<Class<?>, AtomicLong> CACHE_HITS = new ConcurrentHashMap<>(); | |
| - private static final Map<Class<?>, AtomicLong> CACHE_MISSES = new ConcurrentHashMap<>(); | |
| - | |
| - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultModelObjectPool.class); | |
| - | |
| - private final Map<?, ?> properties; | |
| - | |
| - public DefaultModelObjectPool() { | |
| - this(System.getProperties()); | |
| - } | |
| - | |
| - DefaultModelObjectPool(Map<?, ?> properties) { | |
| - this.properties = properties; | |
| - } | |
| - | |
| - @Override | |
| - @SuppressWarnings("unchecked") | |
| - public <T> T process(T object) { | |
| - if (object == null) { | |
| - return null; | |
| - } | |
| - | |
| - Class<?> objectType = object.getClass(); | |
| - String simpleClassName = objectType.getSimpleName(); | |
| - | |
| - // Check if this object type should be pooled (read configuration dynamically) | |
| - if (!getPooledTypes(properties).contains(simpleClassName)) { | |
| - return object; | |
| - } | |
| - | |
| - // Get or create cache for this object type | |
| - Cache<PoolKey, Object> cache = OBJECT_POOLS.computeIfAbsent(objectType, this::createCacheForType); | |
| - | |
| - return (T) internObject(object, cache, objectType); | |
| - } | |
| - | |
| - private String getProperty(String name, String defaultValue) { | |
| - Object value = properties.get(name); | |
| - return value instanceof String str ? str : defaultValue; | |
| - } | |
| - | |
| - /** | |
| - * Gets the set of object types that should be pooled. | |
| - */ | |
| - private Set<String> getPooledTypes(Map<?, ?> properties) { | |
| - String pooledTypesProperty = getProperty(Constants.MAVEN_MODEL_PROCESSOR_POOLED_TYPES, "Dependency"); | |
| - return Arrays.stream(pooledTypesProperty.split(",")) | |
| - .map(String::trim) | |
| - .filter(s -> !s.isEmpty()) | |
| - .collect(Collectors.toSet()); | |
| - } | |
| - | |
| - /** | |
| - * Creates a cache for the specified object type with the appropriate reference type. | |
| - */ | |
| - private Cache<PoolKey, Object> createCacheForType(Class<?> objectType) { | |
| - Cache.ReferenceType referenceType = getReferenceTypeForClass(objectType); | |
| - return Cache.newCache(referenceType); | |
| - } | |
| - | |
| - /** | |
| - * Gets the reference type to use for a specific object type. | |
| - * Checks for per-type configuration first, then falls back to default. | |
| - */ | |
| - private Cache.ReferenceType getReferenceTypeForClass(Class<?> objectType) { | |
| - String className = objectType.getSimpleName(); | |
| - | |
| - // Check for per-type configuration first | |
| - String perTypeProperty = Constants.MAVEN_MODEL_PROCESSOR_REFERENCE_TYPE_PREFIX + className; | |
| - String perTypeValue = getProperty(perTypeProperty, null); | |
| - | |
| - if (perTypeValue != null) { | |
| - try { | |
| - return Cache.ReferenceType.valueOf(perTypeValue.toUpperCase()); | |
| - } catch (IllegalArgumentException e) { | |
| - LOGGER.warn("Unknown reference type for " + className + ": " + perTypeValue + ", using default"); | |
| - } | |
| - } | |
| - | |
| - // Fall back to default reference type | |
| - return getDefaultReferenceType(); | |
| - } | |
| - | |
| - /** | |
| - * Gets the default reference type from system properties. | |
| - */ | |
| - private Cache.ReferenceType getDefaultReferenceType() { | |
| - try { | |
| - String referenceTypeProperty = | |
| - getProperty(Constants.MAVEN_MODEL_PROCESSOR_REFERENCE_TYPE, Cache.ReferenceType.HARD.name()); | |
| - return Cache.ReferenceType.valueOf(referenceTypeProperty.toUpperCase()); | |
| - } catch (IllegalArgumentException e) { | |
| - LOGGER.warn("Unknown default reference type, using HARD"); | |
| - return Cache.ReferenceType.HARD; | |
| - } | |
| - } | |
| - | |
| - /** | |
| - * Interns an object in the appropriate pool. | |
| - */ | |
| - private Object internObject(Object object, Cache<PoolKey, Object> cache, Class<?> objectType) { | |
| - // Update statistics | |
| - TOTAL_CALLS.computeIfAbsent(objectType, k -> new AtomicLong(0)).incrementAndGet(); | |
| - | |
| - PoolKey key = new PoolKey(object); | |
| - Object existing = cache.get(key); | |
| - if (existing != null) { | |
| - CACHE_HITS.computeIfAbsent(objectType, k -> new AtomicLong(0)).incrementAndGet(); | |
| - return existing; | |
| - } | |
| - | |
| - // Use computeIfAbsent to handle concurrent access | |
| - existing = cache.computeIfAbsent(key, k -> object); | |
| - if (existing == object) { | |
| - // We added the object to the cache | |
| - CACHE_MISSES.computeIfAbsent(objectType, k -> new AtomicLong(0)).incrementAndGet(); | |
| - } else { | |
| - // Another thread added it first | |
| - CACHE_HITS.computeIfAbsent(objectType, k -> new AtomicLong(0)).incrementAndGet(); | |
| - } | |
| - | |
| - return existing; | |
| - } | |
| - | |
| - /** | |
| - * Key class for pooling any model object based on their content. | |
| - * Uses custom equality strategies for different object types. | |
| - */ | |
| - private static class PoolKey { | |
| - private final Object object; | |
| - private final int hashCode; | |
| - | |
| - PoolKey(Object object) { | |
| - this.object = object; | |
| - this.hashCode = computeHashCode(object); | |
| - } | |
| - | |
| - @Override | |
| - public boolean equals(Object obj) { | |
| - if (this == obj) { | |
| - return true; | |
| - } | |
| - if (!(obj instanceof PoolKey other)) { | |
| - return false; | |
| - } | |
| - | |
| - return objectsEqual(object, other.object); | |
| - } | |
| - | |
| - @Override | |
| - public int hashCode() { | |
| - return hashCode; | |
| - } | |
| - | |
| - /** | |
| - * Custom equality check for different object types. | |
| - */ | |
| - private static boolean objectsEqual(Object obj1, Object obj2) { | |
| - if (obj1 == obj2) { | |
| - return true; | |
| - } | |
| - if (obj1 == null || obj2 == null) { | |
| - return false; | |
| - } | |
| - if (obj1.getClass() != obj2.getClass()) { | |
| - return false; | |
| - } | |
| - | |
| - // Custom equality for Dependency objects | |
| - if (obj1 instanceof org.apache.maven.api.model.Dependency) { | |
| - return dependenciesEqual( | |
| - (org.apache.maven.api.model.Dependency) obj1, (org.apache.maven.api.model.Dependency) obj2); | |
| - } | |
| - | |
| - // For other objects, use default equals | |
| - return obj1.equals(obj2); | |
| - } | |
| - | |
| - /** | |
| - * Custom equality check for Dependency objects based on all fields. | |
| - */ | |
| - private static boolean dependenciesEqual( | |
| - org.apache.maven.api.model.Dependency dep1, org.apache.maven.api.model.Dependency dep2) { | |
| - return Objects.equals(dep1.getGroupId(), dep2.getGroupId()) | |
| - && Objects.equals(dep1.getArtifactId(), dep2.getArtifactId()) | |
| - && Objects.equals(dep1.getVersion(), dep2.getVersion()) | |
| - && Objects.equals(dep1.getType(), dep2.getType()) | |
| - && Objects.equals(dep1.getClassifier(), dep2.getClassifier()) | |
| - && Objects.equals(dep1.getScope(), dep2.getScope()) | |
| - && Objects.equals(dep1.getSystemPath(), dep2.getSystemPath()) | |
| - && Objects.equals(dep1.getExclusions(), dep2.getExclusions()) | |
| - && Objects.equals(dep1.getOptional(), dep2.getOptional()) | |
| - && Objects.equals(dep1.getLocationKeys(), dep2.getLocationKeys()) | |
| - && locationsEqual(dep1, dep2) | |
| - && Objects.equals(dep1.getImportedFrom(), dep2.getImportedFrom()); | |
| - } | |
| - | |
| - /** | |
| - * Compare locations maps for two dependencies. | |
| - */ | |
| - private static boolean locationsEqual( | |
| - org.apache.maven.api.model.Dependency dep1, org.apache.maven.api.model.Dependency dep2) { | |
| - var keys1 = dep1.getLocationKeys(); | |
| - var keys2 = dep2.getLocationKeys(); | |
| - | |
| - if (!Objects.equals(keys1, keys2)) { | |
| - return false; | |
| - } | |
| - | |
| - for (Object key : keys1) { | |
| - if (!Objects.equals(dep1.getLocation(key), dep2.getLocation(key))) { | |
| - return false; | |
| - } | |
| - } | |
| - return true; | |
| - } | |
| - | |
| - /** | |
| - * Custom hash code computation for different object types. | |
| - */ | |
| - private static int computeHashCode(Object obj) { | |
| - if (obj instanceof org.apache.maven.api.model.Dependency) { | |
| - return dependencyHashCode((org.apache.maven.api.model.Dependency) obj); | |
| - } | |
| - return obj.hashCode(); | |
| - } | |
| - | |
| - /** | |
| - * Custom hash code for Dependency objects based on all fields. | |
| - */ | |
| - private static int dependencyHashCode(org.apache.maven.api.model.Dependency dep) { | |
| - return Objects.hash( | |
| - dep.getGroupId(), | |
| - dep.getArtifactId(), | |
| - dep.getVersion(), | |
| - dep.getType(), | |
| - dep.getClassifier(), | |
| - dep.getScope(), | |
| - dep.getSystemPath(), | |
| - dep.getExclusions(), | |
| - dep.getOptional(), | |
| - dep.getLocationKeys(), | |
| - locationsHashCode(dep), | |
| - dep.getImportedFrom()); | |
| - } | |
| - | |
| - /** | |
| - * Compute hash code for locations map. | |
| - */ | |
| - private static int locationsHashCode(org.apache.maven.api.model.Dependency dep) { | |
| - int hash = 1; | |
| - for (Object key : dep.getLocationKeys()) { | |
| - hash = 31 * hash + Objects.hashCode(key); | |
| - hash = 31 * hash + Objects.hashCode(dep.getLocation(key)); | |
| - } | |
| - return hash; | |
| - } | |
| - } | |
| - | |
| - /** | |
| - * Get statistics for a specific object type. | |
| - * Useful for monitoring and debugging. | |
| - */ | |
| - public static String getStatistics(Class<?> objectType) { | |
| - AtomicLong totalCalls = TOTAL_CALLS.get(objectType); | |
| - AtomicLong hits = CACHE_HITS.get(objectType); | |
| - AtomicLong misses = CACHE_MISSES.get(objectType); | |
| - | |
| - if (totalCalls == null) { | |
| - return objectType.getSimpleName() + ": No statistics available"; | |
| - } | |
| - | |
| - long total = totalCalls.get(); | |
| - long hitCount = hits != null ? hits.get() : 0; | |
| - long missCount = misses != null ? misses.get() : 0; | |
| - double hitRatio = total > 0 ? (double) hitCount / total : 0.0; | |
| - | |
| - return String.format( | |
| - "%s: Total=%d, Hits=%d, Misses=%d, Hit Ratio=%.2f%%", | |
| - objectType.getSimpleName(), total, hitCount, missCount, hitRatio * 100); | |
| - } | |
| - | |
| - /** | |
| - * Get statistics for all pooled object types. | |
| - */ | |
| - public static String getAllStatistics() { | |
| - StringBuilder sb = new StringBuilder("ModelObjectPool Statistics:\n"); | |
| - for (Class<?> type : OBJECT_POOLS.keySet()) { | |
| - sb.append(" ").append(getStatistics(type)).append("\n"); | |
| - } | |
| - return sb.toString(); | |
| - } | |
| -} | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java | |
| index c3bc8e7320..576ef1bf23 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelValidator.java | |
| @@ -39,7 +39,6 @@ | |
| import java.util.stream.Collectors; | |
| import java.util.stream.StreamSupport; | |
| -import org.apache.maven.api.DependencyScope; | |
| import org.apache.maven.api.Session; | |
| import org.apache.maven.api.annotations.Nullable; | |
| import org.apache.maven.api.di.Inject; | |
| @@ -78,6 +77,7 @@ | |
| import org.apache.maven.impl.InternalSession; | |
| import org.apache.maven.model.v4.MavenModelVersion; | |
| import org.apache.maven.model.v4.MavenTransformer; | |
| +import org.eclipse.aether.scope.DependencyScope; | |
| import org.eclipse.aether.scope.ScopeManager; | |
| /** | |
| @@ -302,9 +302,9 @@ public DefaultModelValidator() {} | |
| @Override | |
| @SuppressWarnings("checkstyle:MethodLength") | |
| - public void validateFileModel(Session session, Model model, int validationLevel, ModelProblemCollector problems) { | |
| + public void validateFileModel(Session s, Model m, int validationLevel, ModelProblemCollector problems) { | |
| - Parent parent = model.getParent(); | |
| + Parent parent = m.getParent(); | |
| if (parent != null) { | |
| validateStringNotEmpty( | |
| "parent.groupId", problems, Severity.FATAL, Version.BASE, parent.getGroupId(), parent); | |
| @@ -312,8 +312,7 @@ public void validateFileModel(Session session, Model model, int validationLevel, | |
| validateStringNotEmpty( | |
| "parent.artifactId", problems, Severity.FATAL, Version.BASE, parent.getArtifactId(), parent); | |
| - if (equals(parent.getGroupId(), model.getGroupId()) | |
| - && equals(parent.getArtifactId(), model.getArtifactId())) { | |
| + if (equals(parent.getGroupId(), m.getGroupId()) && equals(parent.getArtifactId(), m.getArtifactId())) { | |
| addViolation( | |
| problems, | |
| Severity.FATAL, | |
| @@ -342,8 +341,8 @@ && equals(parent.getArtifactId(), model.getArtifactId())) { | |
| || parent.getArtifactId() != null | |
| && !parent.getArtifactId().isEmpty()) | |
| && validationLevel >= ModelValidator.VALIDATION_LEVEL_MAVEN_4_0 | |
| - && ModelBuilder.KNOWN_MODEL_VERSIONS.contains(model.getModelVersion()) | |
| - && !Objects.equals(model.getModelVersion(), ModelBuilder.MODEL_VERSION_4_0_0)) { | |
| + && ModelBuilder.KNOWN_MODEL_VERSIONS.contains(m.getModelVersion()) | |
| + && !Objects.equals(m.getModelVersion(), ModelBuilder.MODEL_VERSION_4_0_0)) { | |
| addViolation( | |
| problems, | |
| Severity.WARNING, | |
| @@ -355,47 +354,10 @@ && equals(parent.getArtifactId(), model.getArtifactId())) { | |
| } | |
| } | |
| - // Validate mixins | |
| - if (!model.getMixins().isEmpty()) { | |
| - // Ensure model version is at least 4.2.0 when using mixins | |
| - if (compareModelVersions("4.2.0", model.getModelVersion()) < 0) { | |
| - addViolation( | |
| - problems, | |
| - Severity.ERROR, | |
| - Version.V40, | |
| - "mixins", | |
| - null, | |
| - "Mixins are only supported in modelVersion 4.2.0 or higher, but found '" | |
| - + model.getModelVersion() + "'.", | |
| - model); | |
| - } | |
| - | |
| - // Validate each mixin | |
| - for (Parent mixin : model.getMixins()) { | |
| - if (mixin.getRelativePath() != null | |
| - && !mixin.getRelativePath().isEmpty() | |
| - && (mixin.getGroupId() != null && !mixin.getGroupId().isEmpty() | |
| - || mixin.getArtifactId() != null | |
| - && !mixin.getArtifactId().isEmpty()) | |
| - && validationLevel >= ModelValidator.VALIDATION_LEVEL_MAVEN_4_0 | |
| - && ModelBuilder.KNOWN_MODEL_VERSIONS.contains(model.getModelVersion()) | |
| - && !Objects.equals(model.getModelVersion(), ModelBuilder.MODEL_VERSION_4_0_0)) { | |
| - addViolation( | |
| - problems, | |
| - Severity.WARNING, | |
| - Version.BASE, | |
| - "mixins.mixin.relativePath", | |
| - null, | |
| - "only specify relativePath or groupId/artifactId for mixin", | |
| - mixin); | |
| - } | |
| - } | |
| - } | |
| - | |
| if (validationLevel == ModelValidator.VALIDATION_LEVEL_MINIMAL) { | |
| // profiles: they are essential for proper model building (may contribute profiles, dependencies...) | |
| HashSet<String> minProfileIds = new HashSet<>(); | |
| - for (Profile profile : model.getProfiles()) { | |
| + for (Profile profile : m.getProfiles()) { | |
| if (!minProfileIds.add(profile.getId())) { | |
| addViolation( | |
| problems, | |
| @@ -408,28 +370,27 @@ && equals(parent.getArtifactId(), model.getArtifactId())) { | |
| } | |
| } | |
| } else if (validationLevel >= ModelValidator.VALIDATION_LEVEL_MAVEN_2_0) { | |
| - validateStringNotEmpty( | |
| - "modelVersion", problems, Severity.ERROR, Version.V20, model.getModelVersion(), model); | |
| + validateStringNotEmpty("modelVersion", problems, Severity.ERROR, Version.V20, m.getModelVersion(), m); | |
| - validateModelVersion(session, problems, model.getModelVersion(), model, ModelBuilder.KNOWN_MODEL_VERSIONS); | |
| + validateModelVersion(problems, m.getModelVersion(), m, ModelBuilder.KNOWN_MODEL_VERSIONS); | |
| Set<String> modules = new HashSet<>(); | |
| - for (int index = 0, size = model.getModules().size(); index < size; index++) { | |
| - String module = model.getModules().get(index); | |
| + for (int i = 0, n = m.getModules().size(); i < n; i++) { | |
| + String module = m.getModules().get(i); | |
| if (!modules.add(module)) { | |
| addViolation( | |
| problems, | |
| Severity.ERROR, | |
| Version.V20, | |
| - "modules.module[" + index + "]", | |
| + "modules.module[" + i + "]", | |
| null, | |
| "specifies duplicate child module " + module, | |
| - model.getLocation("modules")); | |
| + m.getLocation("modules")); | |
| } | |
| } | |
| - String modelVersion = model.getModelVersion(); | |
| + String modelVersion = m.getModelVersion(); | |
| if (Objects.equals(modelVersion, ModelBuilder.MODEL_VERSION_4_0_0)) { | |
| - if (!model.getSubprojects().isEmpty()) { | |
| + if (!m.getSubprojects().isEmpty()) { | |
| addViolation( | |
| problems, | |
| Severity.ERROR, | |
| @@ -437,21 +398,21 @@ && equals(parent.getArtifactId(), model.getArtifactId())) { | |
| "subprojects", | |
| null, | |
| "unexpected subprojects element", | |
| - model.getLocation("subprojects")); | |
| + m.getLocation("subprojects")); | |
| } | |
| } else { | |
| Set<String> subprojects = new HashSet<>(); | |
| - for (int index = 0, size = model.getSubprojects().size(); index < size; index++) { | |
| - String subproject = model.getSubprojects().get(index); | |
| + for (int i = 0, n = m.getSubprojects().size(); i < n; i++) { | |
| + String subproject = m.getSubprojects().get(i); | |
| if (!subprojects.add(subproject)) { | |
| addViolation( | |
| problems, | |
| Severity.ERROR, | |
| Version.V41, | |
| - "subprojects.subproject[" + index + "]", | |
| + "subprojects.subproject[" + i + "]", | |
| null, | |
| "specifies duplicate subproject " + subproject, | |
| - model.getLocation("subprojects")); | |
| + m.getLocation("subprojects")); | |
| } | |
| } | |
| if (!modules.isEmpty()) { | |
| @@ -463,7 +424,7 @@ && equals(parent.getArtifactId(), model.getArtifactId())) { | |
| "modules", | |
| null, | |
| "deprecated modules element, use subprojects instead", | |
| - model.getLocation("modules")); | |
| + m.getLocation("modules")); | |
| } else { | |
| addViolation( | |
| problems, | |
| @@ -472,77 +433,77 @@ && equals(parent.getArtifactId(), model.getArtifactId())) { | |
| "modules", | |
| null, | |
| "cannot use both modules and subprojects element", | |
| - model.getLocation("modules")); | |
| + m.getLocation("modules")); | |
| } | |
| } | |
| } | |
| Severity errOn30 = getSeverity(validationLevel, ModelValidator.VALIDATION_LEVEL_MAVEN_3_0); | |
| - boolean isModelVersion41OrMore = !Objects.equals(ModelBuilder.MODEL_VERSION_4_0_0, model.getModelVersion()); | |
| + boolean isModelVersion41OrMore = !Objects.equals(ModelBuilder.MODEL_VERSION_4_0_0, m.getModelVersion()); | |
| if (isModelVersion41OrMore) { | |
| - validateStringNoExpression("groupId", problems, Severity.FATAL, Version.V41, model.getGroupId(), model); | |
| + validateStringNoExpression("groupId", problems, Severity.FATAL, Version.V41, m.getGroupId(), m); | |
| - validateStringNotEmpty( | |
| - "artifactId", problems, Severity.FATAL, Version.V20, model.getArtifactId(), model); | |
| - validateStringNoExpression( | |
| - "artifactId", problems, Severity.FATAL, Version.V20, model.getArtifactId(), model); | |
| + validateStringNotEmpty("artifactId", problems, Severity.FATAL, Version.V20, m.getArtifactId(), m); | |
| + validateStringNoExpression("artifactId", problems, Severity.FATAL, Version.V20, m.getArtifactId(), m); | |
| - validateVersionNoExpression( | |
| - "version", problems, Severity.FATAL, Version.V41, model.getVersion(), model); | |
| + validateVersionNoExpression("version", problems, Severity.FATAL, Version.V41, m.getVersion(), m); | |
| if (parent != null) { | |
| validateStringNoExpression( | |
| - "groupId", problems, Severity.FATAL, Version.V41, parent.getGroupId(), model); | |
| + "groupId", problems, Severity.FATAL, Version.V41, parent.getGroupId(), m); | |
| validateStringNoExpression( | |
| - "artifactId", problems, Severity.FATAL, Version.V41, parent.getArtifactId(), model); | |
| + "artifactId", problems, Severity.FATAL, Version.V41, parent.getArtifactId(), m); | |
| validateVersionNoExpression( | |
| - "version", problems, Severity.FATAL, Version.V41, parent.getVersion(), model); | |
| + "version", problems, Severity.FATAL, Version.V41, parent.getVersion(), m); | |
| } | |
| } else { | |
| - validateStringNoExpression( | |
| - "groupId", problems, Severity.WARNING, Version.V20, model.getGroupId(), model); | |
| + validateStringNoExpression("groupId", problems, Severity.WARNING, Version.V20, m.getGroupId(), m); | |
| if (parent == null) { | |
| - validateStringNotEmpty("groupId", problems, Severity.FATAL, Version.V20, model.getGroupId(), model); | |
| + validateStringNotEmpty("groupId", problems, Severity.FATAL, Version.V20, m.getGroupId(), m); | |
| } | |
| - validateStringNoExpression( | |
| - "artifactId", problems, Severity.WARNING, Version.V20, model.getArtifactId(), model); | |
| - validateStringNotEmpty( | |
| - "artifactId", problems, Severity.FATAL, Version.V20, model.getArtifactId(), model); | |
| + validateStringNoExpression("artifactId", problems, Severity.WARNING, Version.V20, m.getArtifactId(), m); | |
| + validateStringNotEmpty("artifactId", problems, Severity.FATAL, Version.V20, m.getArtifactId(), m); | |
| - validateVersionNoExpression( | |
| - "version", problems, Severity.WARNING, Version.V20, model.getVersion(), model); | |
| + validateVersionNoExpression("version", problems, Severity.WARNING, Version.V20, m.getVersion(), m); | |
| if (parent == null) { | |
| - validateStringNotEmpty("version", problems, Severity.FATAL, Version.V20, model.getVersion(), model); | |
| + validateStringNotEmpty("version", problems, Severity.FATAL, Version.V20, m.getVersion(), m); | |
| } | |
| } | |
| - validateStringNoExpression( | |
| - "packaging", problems, Severity.WARNING, Version.V20, model.getPackaging(), model); | |
| + validateStringNoExpression("packaging", problems, Severity.WARNING, Version.V20, m.getPackaging(), m); | |
| validate20RawDependencies( | |
| problems, | |
| - model.getDependencies(), | |
| + m.getDependencies(), | |
| "dependencies.dependency.", | |
| EMPTY, | |
| isModelVersion41OrMore, | |
| validationLevel); | |
| - validate20RawDependenciesSelfReferencing( | |
| - problems, model, model.getDependencies(), "dependencies.dependency"); | |
| + validate20RawDependenciesSelfReferencing(problems, m, m.getDependencies(), "dependencies.dependency"); | |
| - if (model.getDependencyManagement() != null) { | |
| + if (m.getDependencyManagement() != null) { | |
| validate20RawDependencies( | |
| problems, | |
| - model.getDependencyManagement().getDependencies(), | |
| + m.getDependencyManagement().getDependencies(), | |
| "dependencyManagement.dependencies.dependency.", | |
| EMPTY, | |
| isModelVersion41OrMore, | |
| validationLevel); | |
| } | |
| - Build build = model.getBuild(); | |
| + validateRawRepositories(problems, m.getRepositories(), "repositories.repository.", EMPTY, validationLevel); | |
| + | |
| + validateRawRepositories( | |
| + problems, | |
| + m.getPluginRepositories(), | |
| + "pluginRepositories.pluginRepository.", | |
| + EMPTY, | |
| + validationLevel); | |
| + | |
| + Build build = m.getBuild(); | |
| if (build != null) { | |
| validate20RawPlugins(problems, build.getPlugins(), "build.plugins.plugin.", EMPTY, validationLevel); | |
| @@ -559,10 +520,10 @@ && equals(parent.getArtifactId(), model.getArtifactId())) { | |
| Set<String> profileIds = new HashSet<>(); | |
| - for (Profile profile : model.getProfiles()) { | |
| + for (Profile profile : m.getProfiles()) { | |
| String prefix = "profiles.profile[" + profile.getId() + "]."; | |
| - validateProfileId(prefix, "id", problems, Severity.ERROR, Version.V40, profile.getId(), null, model); | |
| + validateProfileId(prefix, "id", problems, Severity.ERROR, Version.V40, profile.getId(), null, m); | |
| if (!profileIds.add(profile.getId())) { | |
| addViolation( | |
| @@ -595,6 +556,16 @@ && equals(parent.getArtifactId(), model.getArtifactId())) { | |
| validationLevel); | |
| } | |
| + validateRawRepositories( | |
| + problems, profile.getRepositories(), prefix, "repositories.repository.", validationLevel); | |
| + | |
| + validateRawRepositories( | |
| + problems, | |
| + profile.getPluginRepositories(), | |
| + prefix, | |
| + "pluginRepositories.pluginRepository.", | |
| + validationLevel); | |
| + | |
| BuildBase buildBase = profile.getBuild(); | |
| if (buildBase != null) { | |
| validate20RawPlugins(problems, buildBase.getPlugins(), prefix, "plugins.plugin.", validationLevel); | |
| @@ -614,11 +585,11 @@ && equals(parent.getArtifactId(), model.getArtifactId())) { | |
| } | |
| @Override | |
| - public void validateRawModel(Session session, Model model, int validationLevel, ModelProblemCollector problems) { | |
| + public void validateRawModel(Session s, Model m, int validationLevel, ModelProblemCollector problems) { | |
| // Check that the model version is correctly set wrt the model definition, i.e., that the | |
| // user does not use an attribute or element that is not available in the modelVersion used. | |
| - String minVersion = new MavenModelVersion().getModelVersion(model); | |
| - if (model.getModelVersion() != null && compareModelVersions(minVersion, model.getModelVersion()) > 0) { | |
| + String minVersion = new MavenModelVersion().getModelVersion(m); | |
| + if (m.getModelVersion() != null && compareModelVersions(minVersion, m.getModelVersion()) > 0) { | |
| addViolation( | |
| problems, | |
| Severity.FATAL, | |
| @@ -626,10 +597,10 @@ public void validateRawModel(Session session, Model model, int validationLevel, | |
| "model", | |
| null, | |
| "the model contains elements that require a model version of " + minVersion, | |
| - model); | |
| + m); | |
| } | |
| - Parent parent = model.getParent(); | |
| + Parent parent = m.getParent(); | |
| if (parent != null) { | |
| validateStringNotEmpty( | |
| @@ -641,8 +612,7 @@ public void validateRawModel(Session session, Model model, int validationLevel, | |
| validateStringNotEmpty( | |
| "parent.version", problems, Severity.FATAL, Version.BASE, parent.getVersion(), parent); | |
| - if (equals(parent.getGroupId(), model.getGroupId()) | |
| - && equals(parent.getArtifactId(), model.getArtifactId())) { | |
| + if (equals(parent.getGroupId(), m.getGroupId()) && equals(parent.getArtifactId(), m.getArtifactId())) { | |
| addViolation( | |
| problems, | |
| Severity.FATAL, | |
| @@ -665,44 +635,6 @@ && equals(parent.getArtifactId(), model.getArtifactId())) { | |
| parent); | |
| } | |
| } | |
| - | |
| - if (validationLevel > VALIDATION_LEVEL_MINIMAL) { | |
| - validateRawRepositories( | |
| - problems, model.getRepositories(), "repositories.repository.", EMPTY, validationLevel); | |
| - | |
| - validateRawRepositories( | |
| - problems, | |
| - model.getPluginRepositories(), | |
| - "pluginRepositories.pluginRepository.", | |
| - EMPTY, | |
| - validationLevel); | |
| - | |
| - for (Profile profile : model.getProfiles()) { | |
| - String prefix = "profiles.profile[" + profile.getId() + "]."; | |
| - | |
| - validateRawRepositories( | |
| - problems, profile.getRepositories(), prefix, "repositories.repository.", validationLevel); | |
| - | |
| - validateRawRepositories( | |
| - problems, | |
| - profile.getPluginRepositories(), | |
| - prefix, | |
| - "pluginRepositories.pluginRepository.", | |
| - validationLevel); | |
| - } | |
| - | |
| - DistributionManagement distMgmt = model.getDistributionManagement(); | |
| - if (distMgmt != null) { | |
| - validateRawRepository( | |
| - problems, distMgmt.getRepository(), "distributionManagement.repository.", "", true); | |
| - validateRawRepository( | |
| - problems, | |
| - distMgmt.getSnapshotRepository(), | |
| - "distributionManagement.snapshotRepository.", | |
| - "", | |
| - true); | |
| - } | |
| - } | |
| } | |
| private void validate30RawProfileActivation(ModelProblemCollector problems, Activation activation, String prefix) { | |
| @@ -722,19 +654,17 @@ private void validate30RawProfileActivation(ModelProblemCollector problems, Acti | |
| if (stk.size() < 2) { | |
| return null; | |
| } | |
| - Iterator<ActivationFrame> frameIterator = stk.iterator(); | |
| + Iterator<ActivationFrame> f = stk.iterator(); | |
| - String location = frameIterator.next().location; | |
| - ActivationFrame parent = frameIterator.next(); | |
| + String location = f.next().location; | |
| + ActivationFrame parent = f.next(); | |
| - return parent.parent | |
| - .map(parentTracker -> parentTracker.getLocation(location)) | |
| - .orElse(null); | |
| + return parent.parent.map(p -> p.getLocation(location)).orElse(null); | |
| }; | |
| - final UnaryOperator<String> transformer = stringValue -> { | |
| - if (hasProjectExpression(stringValue)) { | |
| + final UnaryOperator<String> transformer = s -> { | |
| + if (hasProjectExpression(s)) { | |
| String path = pathSupplier.get(); | |
| - Matcher matcher = EXPRESSION_PROJECT_NAME_PATTERN.matcher(stringValue); | |
| + Matcher matcher = EXPRESSION_PROJECT_NAME_PATTERN.matcher(s); | |
| while (matcher.find()) { | |
| String propertyName = matcher.group(0); | |
| @@ -747,12 +677,12 @@ private void validate30RawProfileActivation(ModelProblemCollector problems, Acti | |
| Version.V30, | |
| prefix + path, | |
| null, | |
| - "Failed to interpolate profile activation property " + stringValue + ": " + propertyName | |
| + "Failed to interpolate profile activation property " + s + ": " + propertyName | |
| + " expressions are not supported during profile activation.", | |
| locationSupplier.get()); | |
| } | |
| } | |
| - return stringValue; | |
| + return s; | |
| }; | |
| new ActivationWalker(stk, transformer).transformActivation(activation); | |
| } | |
| @@ -900,36 +830,35 @@ private void validateXmlNode( | |
| @Override | |
| @SuppressWarnings("checkstyle:MethodLength") | |
| - public void validateEffectiveModel( | |
| - Session session, Model model, int validationLevel, ModelProblemCollector problems) { | |
| - validateStringNotEmpty("modelVersion", problems, Severity.ERROR, Version.BASE, model.getModelVersion(), model); | |
| + public void validateEffectiveModel(Session s, Model m, int validationLevel, ModelProblemCollector problems) { | |
| + validateStringNotEmpty("modelVersion", problems, Severity.ERROR, Version.BASE, m.getModelVersion(), m); | |
| - validateCoordinatesId("groupId", problems, model.getGroupId(), model); | |
| + validateCoordinatesId("groupId", problems, m.getGroupId(), m); | |
| - validateCoordinatesId("artifactId", problems, model.getArtifactId(), model); | |
| + validateCoordinatesId("artifactId", problems, m.getArtifactId(), m); | |
| - validateStringNotEmpty("packaging", problems, Severity.ERROR, Version.BASE, model.getPackaging(), model); | |
| + validateStringNotEmpty("packaging", problems, Severity.ERROR, Version.BASE, m.getPackaging(), m); | |
| - if (!model.getModules().isEmpty()) { | |
| - if (!"pom".equals(model.getPackaging())) { | |
| + if (!m.getModules().isEmpty()) { | |
| + if (!"pom".equals(m.getPackaging())) { | |
| addViolation( | |
| problems, | |
| Severity.ERROR, | |
| Version.BASE, | |
| "packaging", | |
| null, | |
| - "with value '" + model.getPackaging() + "' is invalid. Aggregator projects " | |
| + "with value '" + m.getPackaging() + "' is invalid. Aggregator projects " | |
| + "require 'pom' as packaging.", | |
| - model); | |
| + m); | |
| } | |
| - for (int index = 0, size = model.getModules().size(); index < size; index++) { | |
| - String module = model.getModules().get(index); | |
| + for (int i = 0, n = m.getModules().size(); i < n; i++) { | |
| + String module = m.getModules().get(i); | |
| boolean isBlankModule = true; | |
| if (module != null) { | |
| - for (int charIndex = 0; charIndex < module.length(); charIndex++) { | |
| - if (!Character.isWhitespace(module.charAt(charIndex))) { | |
| + for (int j = 0; j < module.length(); j++) { | |
| + if (!Character.isWhitespace(module.charAt(j))) { | |
| isBlankModule = false; | |
| } | |
| } | |
| @@ -940,44 +869,36 @@ public void validateEffectiveModel( | |
| problems, | |
| Severity.ERROR, | |
| Version.BASE, | |
| - "modules.module[" + index + "]", | |
| + "modules.module[" + i + "]", | |
| null, | |
| "has been specified without a path to the project directory.", | |
| - model.getLocation("modules")); | |
| + m.getLocation("modules")); | |
| } | |
| } | |
| } | |
| - validateStringNotEmpty("version", problems, Severity.ERROR, Version.BASE, model.getVersion(), model); | |
| + validateStringNotEmpty("version", problems, Severity.ERROR, Version.BASE, m.getVersion(), m); | |
| Severity errOn30 = getSeverity(validationLevel, ModelValidator.VALIDATION_LEVEL_MAVEN_3_0); | |
| - validateEffectiveDependencies(session, problems, model, model.getDependencies(), false, validationLevel); | |
| + validateEffectiveDependencies(s, problems, m, m.getDependencies(), false, validationLevel); | |
| - DependencyManagement mgmt = model.getDependencyManagement(); | |
| + DependencyManagement mgmt = m.getDependencyManagement(); | |
| if (mgmt != null) { | |
| - validateEffectiveDependencies(session, problems, model, mgmt.getDependencies(), true, validationLevel); | |
| + validateEffectiveDependencies(s, problems, m, mgmt.getDependencies(), true, validationLevel); | |
| } | |
| if (validationLevel >= ModelValidator.VALIDATION_LEVEL_MAVEN_2_0) { | |
| Severity errOn31 = getSeverity(validationLevel, ModelValidator.VALIDATION_LEVEL_MAVEN_3_1); | |
| validateBannedCharacters( | |
| - EMPTY, | |
| - "version", | |
| - problems, | |
| - errOn31, | |
| - Version.V20, | |
| - model.getVersion(), | |
| - null, | |
| - model, | |
| - ILLEGAL_VERSION_CHARS); | |
| - validate20ProperSnapshotVersion("version", problems, errOn31, Version.V20, model.getVersion(), null, model); | |
| - if (hasExpression(model.getVersion())) { | |
| + EMPTY, "version", problems, errOn31, Version.V20, m.getVersion(), null, m, ILLEGAL_VERSION_CHARS); | |
| + validate20ProperSnapshotVersion("version", problems, errOn31, Version.V20, m.getVersion(), null, m); | |
| + if (hasExpression(m.getVersion())) { | |
| Severity versionExpressionSeverity = Severity.ERROR; | |
| - if (model.getProperties() != null | |
| + if (m.getProperties() != null | |
| && Boolean.parseBoolean( | |
| - model.getProperties().get(BUILD_ALLOW_EXPRESSION_IN_EFFECTIVE_PROJECT_VERSION))) { | |
| + m.getProperties().get(BUILD_ALLOW_EXPRESSION_IN_EFFECTIVE_PROJECT_VERSION))) { | |
| versionExpressionSeverity = Severity.WARNING; | |
| } | |
| addViolation( | |
| @@ -986,35 +907,30 @@ public void validateEffectiveModel( | |
| Version.V20, | |
| "version", | |
| null, | |
| - "must be a constant version but is '" + model.getVersion() + "'.", | |
| - model); | |
| + "must be a constant version but is '" + m.getVersion() + "'.", | |
| + m); | |
| } | |
| - Build build = model.getBuild(); | |
| + Build build = m.getBuild(); | |
| if (build != null) { | |
| - for (Plugin plugin : build.getPlugins()) { | |
| + for (Plugin p : build.getPlugins()) { | |
| validateStringNotEmpty( | |
| "build.plugins.plugin.artifactId", | |
| problems, | |
| Severity.ERROR, | |
| Version.V20, | |
| - plugin.getArtifactId(), | |
| - plugin); | |
| + p.getArtifactId(), | |
| + p); | |
| validateStringNotEmpty( | |
| - "build.plugins.plugin.groupId", | |
| - problems, | |
| - Severity.ERROR, | |
| - Version.V20, | |
| - plugin.getGroupId(), | |
| - plugin); | |
| + "build.plugins.plugin.groupId", problems, Severity.ERROR, Version.V20, p.getGroupId(), p); | |
| validate20PluginVersion( | |
| "build.plugins.plugin.version", | |
| problems, | |
| - plugin.getVersion(), | |
| - SourceHint.pluginKey(plugin), | |
| - plugin, | |
| + p.getVersion(), | |
| + SourceHint.pluginKey(p), | |
| + p, | |
| validationLevel); | |
| validateBoolean( | |
| @@ -1023,9 +939,9 @@ public void validateEffectiveModel( | |
| problems, | |
| errOn30, | |
| Version.V20, | |
| - plugin.getInherited(), | |
| - SourceHint.pluginKey(plugin), | |
| - plugin); | |
| + p.getInherited(), | |
| + SourceHint.pluginKey(p), | |
| + p); | |
| validateBoolean( | |
| "build.plugins.plugin.extensions", | |
| @@ -1033,11 +949,11 @@ public void validateEffectiveModel( | |
| problems, | |
| errOn30, | |
| Version.V20, | |
| - plugin.getExtensions(), | |
| - SourceHint.pluginKey(plugin), | |
| - plugin); | |
| + p.getExtensions(), | |
| + SourceHint.pluginKey(p), | |
| + p); | |
| - validate20EffectivePluginDependencies(problems, plugin, validationLevel); | |
| + validate20EffectivePluginDependencies(problems, p, validationLevel); | |
| } | |
| validate20RawResources(problems, build.getResources(), "build.resources.resource.", validationLevel); | |
| @@ -1046,37 +962,37 @@ public void validateEffectiveModel( | |
| problems, build.getTestResources(), "build.testResources.testResource.", validationLevel); | |
| } | |
| - Reporting reporting = model.getReporting(); | |
| + Reporting reporting = m.getReporting(); | |
| if (reporting != null) { | |
| - for (ReportPlugin reportPlugin : reporting.getPlugins()) { | |
| + for (ReportPlugin p : reporting.getPlugins()) { | |
| validateStringNotEmpty( | |
| "reporting.plugins.plugin.artifactId", | |
| problems, | |
| Severity.ERROR, | |
| Version.V20, | |
| - reportPlugin.getArtifactId(), | |
| - reportPlugin); | |
| + p.getArtifactId(), | |
| + p); | |
| validateStringNotEmpty( | |
| "reporting.plugins.plugin.groupId", | |
| problems, | |
| Severity.ERROR, | |
| Version.V20, | |
| - reportPlugin.getGroupId(), | |
| - reportPlugin); | |
| + p.getGroupId(), | |
| + p); | |
| } | |
| } | |
| - for (Repository repository : model.getRepositories()) { | |
| + for (Repository repository : m.getRepositories()) { | |
| validate20EffectiveRepository(problems, repository, "repositories.repository.", validationLevel); | |
| } | |
| - for (Repository repository : model.getPluginRepositories()) { | |
| + for (Repository repository : m.getPluginRepositories()) { | |
| validate20EffectiveRepository( | |
| problems, repository, "pluginRepositories.pluginRepository.", validationLevel); | |
| } | |
| - DistributionManagement distMgmt = model.getDistributionManagement(); | |
| + DistributionManagement distMgmt = m.getDistributionManagement(); | |
| if (distMgmt != null) { | |
| if (distMgmt.getStatus() != null) { | |
| addViolation( | |
| @@ -1175,25 +1091,6 @@ private void validate20RawDependencies( | |
| } | |
| } | |
| - // MNG-8750: New dependency scopes are only supported starting with modelVersion 4.1.0 | |
| - // When using modelVersion 4.0.0, fail validation if one of the new scopes is present | |
| - if (!is41OrBeyond) { | |
| - String scope = dependency.getScope(); | |
| - if (DependencyScope.COMPILE_ONLY.id().equals(scope) | |
| - || DependencyScope.TEST_ONLY.id().equals(scope) | |
| - || DependencyScope.TEST_RUNTIME.id().equals(scope)) { | |
| - addViolation( | |
| - problems, | |
| - Severity.ERROR, | |
| - Version.V20, | |
| - prefix + prefix2 + "scope", | |
| - SourceHint.dependencyManagementKey(dependency), | |
| - "scope '" + scope + "' is not supported with modelVersion 4.0.0; " | |
| - + "use modelVersion 4.1.0 or remove this scope.", | |
| - dependency); | |
| - } | |
| - } | |
| - | |
| if (equals("LATEST", dependency.getVersion()) || equals("RELEASE", dependency.getVersion())) { | |
| addViolation( | |
| problems, | |
| @@ -1231,7 +1128,7 @@ private void validate20RawDependencies( | |
| } | |
| private void validate20RawDependenciesSelfReferencing( | |
| - ModelProblemCollector problems, Model model, List<Dependency> dependencies, String prefix) { | |
| + ModelProblemCollector problems, Model m, List<Dependency> dependencies, String prefix) { | |
| // We only check for groupId/artifactId/version/classifier cause if there is another | |
| // module with the same groupId/artifactId/version/classifier this will fail the build | |
| // earlier like "Project '...' is duplicated in the reactor. | |
| @@ -1240,8 +1137,8 @@ private void validate20RawDependenciesSelfReferencing( | |
| for (Dependency dependency : dependencies) { | |
| String key = dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" + dependency.getVersion() | |
| + (dependency.getClassifier() != null ? ":" + dependency.getClassifier() : EMPTY); | |
| - String modelKey = model.getGroupId() + ":" + model.getArtifactId() + ":" + model.getVersion(); | |
| - if (key.equals(modelKey)) { | |
| + String mKey = m.getGroupId() + ":" + m.getArtifactId() + ":" + m.getVersion(); | |
| + if (key.equals(mKey)) { | |
| // This means a module which is build has a dependency which has the same | |
| // groupId, artifactId, version and classifier coordinates. This is in consequence | |
| // a self reference or in other words a circular reference which can not being resolved. | |
| @@ -1258,9 +1155,9 @@ private void validate20RawDependenciesSelfReferencing( | |
| } | |
| private void validateEffectiveDependencies( | |
| - Session session, | |
| + Session s, | |
| ModelProblemCollector problems, | |
| - Model model, | |
| + Model m, | |
| List<Dependency> dependencies, | |
| boolean management, | |
| int validationLevel) { | |
| @@ -1268,8 +1165,8 @@ private void validateEffectiveDependencies( | |
| String prefix = management ? "dependencyManagement.dependencies.dependency." : "dependencies.dependency."; | |
| - for (Dependency dependency : dependencies) { | |
| - validateEffectiveDependency(problems, dependency, management, prefix, validationLevel); | |
| + for (Dependency d : dependencies) { | |
| + validateEffectiveDependency(problems, d, management, prefix, validationLevel); | |
| if (validationLevel >= ModelValidator.VALIDATION_LEVEL_MAVEN_2_0) { | |
| validateBoolean( | |
| @@ -1278,9 +1175,9 @@ private void validateEffectiveDependencies( | |
| problems, | |
| errOn30, | |
| Version.V20, | |
| - dependency.getOptional(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| - dependency); | |
| + d.getOptional(), | |
| + SourceHint.dependencyManagementKey(d), | |
| + d); | |
| if (!management) { | |
| validateVersion( | |
| @@ -1289,61 +1186,59 @@ private void validateEffectiveDependencies( | |
| problems, | |
| errOn30, | |
| Version.V20, | |
| - dependency.getVersion(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| - dependency); | |
| + d.getVersion(), | |
| + SourceHint.dependencyManagementKey(d), | |
| + d); | |
| /* | |
| - * Extensions like Flex Mojos use custom scopes like "merged", "internal", "external", etc. In | |
| - * order to not break backward-compat with those, only warn but don't error out. | |
| + * TODO Extensions like Flex Mojos use custom scopes like "merged", "internal", "external", etc. In | |
| + * order to don't break backward-compat with those, only warn but don't error out. | |
| */ | |
| ScopeManager scopeManager = | |
| - InternalSession.from(session).getSession().getScopeManager(); | |
| - validateDependencyScope( | |
| + InternalSession.from(s).getSession().getScopeManager(); | |
| + validateEnum( | |
| prefix, | |
| "scope", | |
| problems, | |
| Severity.WARNING, | |
| Version.V20, | |
| - dependency.getScope(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| - dependency, | |
| + d.getScope(), | |
| + SourceHint.dependencyManagementKey(d), | |
| + d, | |
| scopeManager.getDependencyScopeUniverse().stream() | |
| - .map(org.eclipse.aether.scope.DependencyScope::getId) | |
| + .map(DependencyScope::getId) | |
| .distinct() | |
| - .toArray(String[]::new), | |
| - false); | |
| + .toArray(String[]::new)); | |
| - validateEffectiveModelAgainstDependency(prefix, problems, model, dependency); | |
| + validateEffectiveModelAgainstDependency(prefix, problems, m, d); | |
| } else { | |
| ScopeManager scopeManager = | |
| - InternalSession.from(session).getSession().getScopeManager(); | |
| + InternalSession.from(s).getSession().getScopeManager(); | |
| Set<String> scopes = scopeManager.getDependencyScopeUniverse().stream() | |
| - .map(org.eclipse.aether.scope.DependencyScope::getId) | |
| + .map(DependencyScope::getId) | |
| .collect(Collectors.toCollection(HashSet::new)); | |
| scopes.add("import"); | |
| - validateDependencyScope( | |
| + validateEnum( | |
| prefix, | |
| "scope", | |
| problems, | |
| Severity.WARNING, | |
| Version.V20, | |
| - dependency.getScope(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| - dependency, | |
| - scopes.toArray(new String[0]), | |
| - true); | |
| + d.getScope(), | |
| + SourceHint.dependencyManagementKey(d), | |
| + d, | |
| + scopes.toArray(new String[0])); | |
| } | |
| } | |
| } | |
| } | |
| private void validateEffectiveModelAgainstDependency( | |
| - String prefix, ModelProblemCollector problems, Model model, Dependency dependency) { | |
| - String key = dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" + dependency.getVersion() | |
| - + (dependency.getClassifier() != null ? ":" + dependency.getClassifier() : EMPTY); | |
| - String modelKey = model.getGroupId() + ":" + model.getArtifactId() + ":" + model.getVersion(); | |
| - if (key.equals(modelKey)) { | |
| + String prefix, ModelProblemCollector problems, Model m, Dependency d) { | |
| + String key = d.getGroupId() + ":" + d.getArtifactId() + ":" + d.getVersion() | |
| + + (d.getClassifier() != null ? ":" + d.getClassifier() : EMPTY); | |
| + String mKey = m.getGroupId() + ":" + m.getArtifactId() + ":" + m.getVersion(); | |
| + if (key.equals(mKey)) { | |
| // This means a module which is build has a dependency which has the same | |
| // groupId, artifactId, version and classifier coordinates. This is in consequence | |
| // a self reference or in other words a circular reference which can not being resolved. | |
| @@ -1354,7 +1249,7 @@ private void validateEffectiveModelAgainstDependency( | |
| prefix + "[" + key + "]", | |
| SourceHint.gav(key), | |
| "is referencing itself.", | |
| - dependency); | |
| + d); | |
| } | |
| } | |
| @@ -1367,8 +1262,8 @@ private void validate20EffectivePluginDependencies( | |
| Severity errOn30 = getSeverity(validationLevel, ModelValidator.VALIDATION_LEVEL_MAVEN_3_0); | |
| - for (Dependency dependency : dependencies) { | |
| - validateEffectiveDependency(problems, dependency, false, prefix, validationLevel); | |
| + for (Dependency d : dependencies) { | |
| + validateEffectiveDependency(problems, d, false, prefix, validationLevel); | |
| validateVersion( | |
| prefix, | |
| @@ -1376,9 +1271,9 @@ private void validate20EffectivePluginDependencies( | |
| problems, | |
| errOn30, | |
| Version.BASE, | |
| - dependency.getVersion(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| - dependency); | |
| + d.getVersion(), | |
| + SourceHint.dependencyManagementKey(d), | |
| + d); | |
| validateEnum( | |
| prefix, | |
| @@ -1386,9 +1281,9 @@ private void validate20EffectivePluginDependencies( | |
| problems, | |
| errOn30, | |
| Version.BASE, | |
| - dependency.getScope(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| - dependency, | |
| + d.getScope(), | |
| + SourceHint.dependencyManagementKey(d), | |
| + d, | |
| "compile", | |
| "runtime", | |
| "system"); | |
| @@ -1397,20 +1292,16 @@ private void validate20EffectivePluginDependencies( | |
| } | |
| private void validateEffectiveDependency( | |
| - ModelProblemCollector problems, | |
| - Dependency dependency, | |
| - boolean management, | |
| - String prefix, | |
| - int validationLevel) { | |
| + ModelProblemCollector problems, Dependency d, boolean management, String prefix, int validationLevel) { | |
| validateCoordinatesId( | |
| prefix, | |
| "artifactId", | |
| problems, | |
| Severity.ERROR, | |
| Version.BASE, | |
| - dependency.getArtifactId(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| - dependency); | |
| + d.getArtifactId(), | |
| + SourceHint.dependencyManagementKey(d), | |
| + d); | |
| validateCoordinatesId( | |
| prefix, | |
| @@ -1418,9 +1309,9 @@ private void validateEffectiveDependency( | |
| problems, | |
| Severity.ERROR, | |
| Version.BASE, | |
| - dependency.getGroupId(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| - dependency); | |
| + d.getGroupId(), | |
| + SourceHint.dependencyManagementKey(d), | |
| + d); | |
| if (!management) { | |
| validateStringNotEmpty( | |
| @@ -1429,15 +1320,15 @@ private void validateEffectiveDependency( | |
| problems, | |
| Severity.ERROR, | |
| Version.BASE, | |
| - dependency.getType(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| - dependency); | |
| + d.getType(), | |
| + SourceHint.dependencyManagementKey(d), | |
| + d); | |
| - validateDependencyVersion(problems, dependency, prefix); | |
| + validateDependencyVersion(problems, d, prefix); | |
| } | |
| - if ("system".equals(dependency.getScope())) { | |
| - String systemPath = dependency.getSystemPath(); | |
| + if ("system".equals(d.getScope())) { | |
| + String systemPath = d.getSystemPath(); | |
| if (systemPath == null || systemPath.isEmpty()) { | |
| addViolation( | |
| @@ -1445,9 +1336,9 @@ private void validateEffectiveDependency( | |
| Severity.ERROR, | |
| Version.BASE, | |
| prefix + "systemPath", | |
| - SourceHint.dependencyManagementKey(dependency), | |
| + SourceHint.dependencyManagementKey(d), | |
| "is missing.", | |
| - dependency); | |
| + d); | |
| } else { | |
| File sysFile = new File(systemPath); | |
| if (!sysFile.isAbsolute()) { | |
| @@ -1456,9 +1347,9 @@ private void validateEffectiveDependency( | |
| Severity.ERROR, | |
| Version.BASE, | |
| prefix + "systemPath", | |
| - SourceHint.dependencyManagementKey(dependency), | |
| + SourceHint.dependencyManagementKey(d), | |
| "must specify an absolute path but is " + systemPath, | |
| - dependency); | |
| + d); | |
| } else if (!sysFile.isFile()) { | |
| String msg = "refers to a non-existing file " + sysFile.getAbsolutePath() + "."; | |
| addViolation( | |
| @@ -1466,25 +1357,24 @@ private void validateEffectiveDependency( | |
| Severity.WARNING, | |
| Version.BASE, | |
| prefix + "systemPath", | |
| - SourceHint.dependencyManagementKey(dependency), | |
| + SourceHint.dependencyManagementKey(d), | |
| msg, | |
| - dependency); | |
| + d); | |
| } | |
| } | |
| - } else if (dependency.getSystemPath() != null | |
| - && !dependency.getSystemPath().isEmpty()) { | |
| + } else if (d.getSystemPath() != null && !d.getSystemPath().isEmpty()) { | |
| addViolation( | |
| problems, | |
| Severity.ERROR, | |
| Version.BASE, | |
| prefix + "systemPath", | |
| - SourceHint.dependencyManagementKey(dependency), | |
| + SourceHint.dependencyManagementKey(d), | |
| "must be omitted. This field may only be specified for a dependency with system scope.", | |
| - dependency); | |
| + d); | |
| } | |
| if (validationLevel >= ModelValidator.VALIDATION_LEVEL_MAVEN_2_0) { | |
| - for (Exclusion exclusion : dependency.getExclusions()) { | |
| + for (Exclusion exclusion : d.getExclusions()) { | |
| if (validationLevel < ModelValidator.VALIDATION_LEVEL_MAVEN_3_0) { | |
| validateCoordinatesId( | |
| prefix, | |
| @@ -1493,7 +1383,7 @@ private void validateEffectiveDependency( | |
| Severity.WARNING, | |
| Version.V20, | |
| exclusion.getGroupId(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| + SourceHint.dependencyManagementKey(d), | |
| exclusion); | |
| validateCoordinatesId( | |
| @@ -1503,7 +1393,7 @@ private void validateEffectiveDependency( | |
| Severity.WARNING, | |
| Version.V20, | |
| exclusion.getArtifactId(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| + SourceHint.dependencyManagementKey(d), | |
| exclusion); | |
| } else { | |
| validateCoordinatesIdWithWildcards( | |
| @@ -1513,7 +1403,7 @@ private void validateEffectiveDependency( | |
| Severity.WARNING, | |
| Version.V30, | |
| exclusion.getGroupId(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| + SourceHint.dependencyManagementKey(d), | |
| exclusion); | |
| validateCoordinatesIdWithWildcards( | |
| @@ -1523,7 +1413,7 @@ private void validateEffectiveDependency( | |
| Severity.WARNING, | |
| Version.V30, | |
| exclusion.getArtifactId(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| + SourceHint.dependencyManagementKey(d), | |
| exclusion); | |
| } | |
| } | |
| @@ -1533,16 +1423,16 @@ private void validateEffectiveDependency( | |
| /** | |
| * @since 3.2.4 | |
| */ | |
| - protected void validateDependencyVersion(ModelProblemCollector problems, Dependency dependency, String prefix) { | |
| + protected void validateDependencyVersion(ModelProblemCollector problems, Dependency d, String prefix) { | |
| validateStringNotEmpty( | |
| prefix, | |
| "version", | |
| problems, | |
| Severity.ERROR, | |
| Version.BASE, | |
| - dependency.getVersion(), | |
| - SourceHint.dependencyManagementKey(dependency), | |
| - dependency); | |
| + d.getVersion(), | |
| + SourceHint.dependencyManagementKey(d), | |
| + d); | |
| } | |
| private void validateRawRepositories( | |
| @@ -1554,7 +1444,40 @@ private void validateRawRepositories( | |
| Map<String, Repository> index = new HashMap<>(); | |
| for (Repository repository : repositories) { | |
| - validateRawRepository(problems, repository, prefix, prefix2, false); | |
| + validateStringNotEmpty( | |
| + prefix, prefix2, "id", problems, Severity.ERROR, Version.V20, repository.getId(), null, repository); | |
| + | |
| + if (validateStringNotEmpty( | |
| + prefix, | |
| + prefix2, | |
| + "[" + repository.getId() + "].url", | |
| + problems, | |
| + Severity.ERROR, | |
| + Version.V20, | |
| + repository.getUrl(), | |
| + null, | |
| + repository)) { | |
| + // only allow ${basedir} and ${project.basedir} | |
| + Matcher m = EXPRESSION_NAME_PATTERN.matcher(repository.getUrl()); | |
| + while (m.find()) { | |
| + String expr = m.group(1); | |
| + if (!("basedir".equals(expr) | |
| + || "project.basedir".equals(expr) | |
| + || expr.startsWith("project.basedir.") | |
| + || "project.rootDirectory".equals(expr) | |
| + || expr.startsWith("project.rootDirectory."))) { | |
| + addViolation( | |
| + problems, | |
| + Severity.ERROR, | |
| + Version.V40, | |
| + prefix + prefix2 + "[" + repository.getId() + "].url", | |
| + null, | |
| + "contains an unsupported expression (only expressions starting with 'project.basedir' or 'project.rootDirectory' are supported).", | |
| + repository); | |
| + break; | |
| + } | |
| + } | |
| + } | |
| String key = repository.getId(); | |
| @@ -1578,57 +1501,6 @@ private void validateRawRepositories( | |
| } | |
| } | |
| - private void validateRawRepository( | |
| - ModelProblemCollector problems, | |
| - Repository repository, | |
| - String prefix, | |
| - String prefix2, | |
| - boolean allowEmptyUrl) { | |
| - if (repository == null) { | |
| - return; | |
| - } | |
| - if (validateStringNotEmpty( | |
| - prefix, prefix2, "id", problems, Severity.ERROR, Version.V20, repository.getId(), null, repository)) { | |
| - // Check for uninterpolated expressions in ID - these should have been interpolated by now | |
| - Matcher matcher = EXPRESSION_NAME_PATTERN.matcher(repository.getId()); | |
| - if (matcher.find()) { | |
| - addViolation( | |
| - problems, | |
| - Severity.ERROR, | |
| - Version.V40, | |
| - prefix + prefix2 + "[" + repository.getId() + "].id", | |
| - null, | |
| - "contains an uninterpolated expression.", | |
| - repository); | |
| - } | |
| - } | |
| - | |
| - if (!allowEmptyUrl | |
| - && validateStringNotEmpty( | |
| - prefix, | |
| - prefix2, | |
| - "[" + repository.getId() + "].url", | |
| - problems, | |
| - Severity.ERROR, | |
| - Version.V20, | |
| - repository.getUrl(), | |
| - null, | |
| - repository)) { | |
| - // Check for uninterpolated expressions in URL - these should have been interpolated by now | |
| - Matcher matcher = EXPRESSION_NAME_PATTERN.matcher(repository.getUrl()); | |
| - if (matcher.find()) { | |
| - addViolation( | |
| - problems, | |
| - Severity.ERROR, | |
| - Version.V40, | |
| - prefix + prefix2 + "[" + repository.getId() + "].url", | |
| - null, | |
| - "contains an uninterpolated expression.", | |
| - repository); | |
| - } | |
| - } | |
| - } | |
| - | |
| private void validate20EffectiveRepository( | |
| ModelProblemCollector problems, Repository repository, String prefix, int validationLevel) { | |
| if (repository != null) { | |
| @@ -1739,22 +1611,17 @@ private boolean validateCoordinatesId( | |
| } | |
| private boolean isValidCoordinatesId(String id) { | |
| - for (int index = 0; index < id.length(); index++) { | |
| - char character = id.charAt(index); | |
| - if (!isValidCoordinatesIdCharacter(character)) { | |
| + for (int i = 0; i < id.length(); i++) { | |
| + char c = id.charAt(i); | |
| + if (!isValidCoordinatesIdCharacter(c)) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| - private boolean isValidCoordinatesIdCharacter(char character) { | |
| - return character >= 'a' && character <= 'z' | |
| - || character >= 'A' && character <= 'Z' | |
| - || character >= '0' && character <= '9' | |
| - || character == '-' | |
| - || character == '_' | |
| - || character == '.'; | |
| + private boolean isValidCoordinatesIdCharacter(char c) { | |
| + return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '-' || c == '_' || c == '.'; | |
| } | |
| @SuppressWarnings("checkstyle:parameternumber") | |
| @@ -1828,17 +1695,17 @@ private boolean validateCoordinatesIdWithWildcards( | |
| } | |
| private boolean isValidCoordinatesIdWithWildCards(String id) { | |
| - for (int index = 0; index < id.length(); index++) { | |
| - char character = id.charAt(index); | |
| - if (!isValidCoordinatesIdWithWildCardCharacter(character)) { | |
| + for (int i = 0; i < id.length(); i++) { | |
| + char c = id.charAt(i); | |
| + if (!isValidCoordinatesIdWithWildCardCharacter(c)) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| - private boolean isValidCoordinatesIdWithWildCardCharacter(char character) { | |
| - return isValidCoordinatesIdCharacter(character) || character == '?' || character == '*'; | |
| + private boolean isValidCoordinatesIdWithWildCardCharacter(char c) { | |
| + return isValidCoordinatesIdCharacter(c) || c == '?' || c == '*'; | |
| } | |
| private boolean validateStringNoExpression( | |
| @@ -1875,8 +1742,8 @@ private boolean validateVersionNoExpression( | |
| return true; | |
| } | |
| - Matcher matcher = EXPRESSION_NAME_PATTERN.matcher(string.trim()); | |
| - if (matcher.find()) { | |
| + Matcher m = EXPRESSION_NAME_PATTERN.matcher(string.trim()); | |
| + if (m.find()) { | |
| addViolation( | |
| problems, | |
| severity, | |
| @@ -2087,71 +1954,21 @@ private boolean validateEnum( | |
| return false; | |
| } | |
| - @SuppressWarnings("checkstyle:parameternumber") | |
| - private boolean validateDependencyScope( | |
| - String prefix, | |
| - String fieldName, | |
| - ModelProblemCollector problems, | |
| - Severity severity, | |
| - Version version, | |
| - String scope, | |
| - @Nullable SourceHint sourceHint, | |
| - InputLocationTracker tracker, | |
| - String[] validScopes, | |
| - boolean isDependencyManagement) { | |
| - if (scope == null || scope.isEmpty()) { | |
| - return true; | |
| - } | |
| - | |
| - List<String> values = Arrays.asList(validScopes); | |
| - | |
| - if (values.contains(scope)) { | |
| - return true; | |
| - } | |
| - | |
| - // Provide a more helpful error message for the 'import' scope | |
| - if ("import".equals(scope) && !isDependencyManagement) { | |
| - addViolation( | |
| - problems, | |
| - severity, | |
| - version, | |
| - prefix + fieldName, | |
| - sourceHint, | |
| - "has scope 'import'. The 'import' scope is only valid in <dependencyManagement> sections.", | |
| - tracker); | |
| - } else { | |
| - addViolation( | |
| - problems, | |
| - severity, | |
| - version, | |
| - prefix + fieldName, | |
| - sourceHint, | |
| - "must be one of " + values + " but is '" + scope + "'.", | |
| - tracker); | |
| - } | |
| - | |
| - return false; | |
| - } | |
| - | |
| @SuppressWarnings("checkstyle:parameternumber") | |
| private boolean validateModelVersion( | |
| - Session session, | |
| - ModelProblemCollector problems, | |
| - String requestedModel, | |
| - InputLocationTracker tracker, | |
| - List<String> validVersions) { | |
| - if (requestedModel == null || requestedModel.isEmpty()) { | |
| + ModelProblemCollector problems, String string, InputLocationTracker tracker, List<String> validVersions) { | |
| + if (string == null || string.isEmpty()) { | |
| return true; | |
| } | |
| - if (validVersions.contains(requestedModel)) { | |
| + if (validVersions.contains(string)) { | |
| return true; | |
| } | |
| boolean newerThanAll = true; | |
| boolean olderThanAll = true; | |
| for (String validValue : validVersions) { | |
| - final int comparison = compareModelVersions(validValue, requestedModel); | |
| + final int comparison = compareModelVersions(validValue, string); | |
| newerThanAll = newerThanAll && comparison < 0; | |
| olderThanAll = olderThanAll && comparison > 0; | |
| } | |
| @@ -2163,10 +1980,8 @@ private boolean validateModelVersion( | |
| Version.V20, | |
| "modelVersion", | |
| null, | |
| - requestedModel + "' is not supported by this Maven version (" | |
| - + getMavenVersionString(session) | |
| - + "). Supported modelVersions are: " + validVersions | |
| - + ". Building this project requires a newer version of Maven.", | |
| + "of '" + string + "' is newer than the versions supported by this version of Maven: " | |
| + + validVersions + ". Building this project requires a newer version of Maven.", | |
| tracker); | |
| } else if (olderThanAll) { | |
| @@ -2177,10 +1992,8 @@ private boolean validateModelVersion( | |
| Version.V20, | |
| "modelVersion", | |
| null, | |
| - requestedModel + "' is not supported by this Maven version (" | |
| - + getMavenVersionString(session) | |
| - + "). Supported modelVersions are: " + validVersions | |
| - + ". Building this project requires an older version of Maven.", | |
| + "of '" + string + "' is older than the versions supported by this version of Maven: " | |
| + + validVersions + ". Building this project requires an older version of Maven.", | |
| tracker); | |
| } else { | |
| @@ -2190,22 +2003,13 @@ private boolean validateModelVersion( | |
| Version.V20, | |
| "modelVersion", | |
| null, | |
| - "must be one of " + validVersions + " but is '" + requestedModel + "'.", | |
| + "must be one of " + validVersions + " but is '" + string + "'.", | |
| tracker); | |
| } | |
| return false; | |
| } | |
| - private String getMavenVersionString(Session session) { | |
| - try { | |
| - return session.getMavenVersion().toString(); | |
| - } catch (Exception exception) { | |
| - // Fallback for test contexts where RuntimeInformation might not be available | |
| - return "unknown"; | |
| - } | |
| - } | |
| - | |
| /** | |
| * Compares two model versions. | |
| * | |
| @@ -2218,8 +2022,8 @@ private static int compareModelVersions(String first, String second) { | |
| // we use a dedicated comparator because we control our model version scheme. | |
| String[] firstSegments = first.split("\\."); | |
| String[] secondSegments = second.split("\\."); | |
| - for (int index = 0; index < Math.max(firstSegments.length, secondSegments.length); index++) { | |
| - int result = asLong(index, firstSegments).compareTo(asLong(index, secondSegments)); | |
| + for (int i = 0; i < Math.max(firstSegments.length, secondSegments.length); i++) { | |
| + int result = asLong(i, firstSegments).compareTo(asLong(i, secondSegments)); | |
| if (result != 0) { | |
| return result; | |
| } | |
| @@ -2230,7 +2034,7 @@ private static int compareModelVersions(String first, String second) { | |
| private static Long asLong(int index, String[] segments) { | |
| try { | |
| return Long.valueOf(index < segments.length ? segments[index] : "0"); | |
| - } catch (NumberFormatException exception) { | |
| + } catch (NumberFormatException e) { | |
| return 0L; | |
| } | |
| } | |
| @@ -2247,15 +2051,15 @@ private boolean validateBannedCharacters( | |
| InputLocationTracker tracker, | |
| String banned) { | |
| if (string != null) { | |
| - for (int index = string.length() - 1; index >= 0; index--) { | |
| - if (banned.indexOf(string.charAt(index)) >= 0) { | |
| + for (int i = string.length() - 1; i >= 0; i--) { | |
| + if (banned.indexOf(string.charAt(i)) >= 0) { | |
| addViolation( | |
| problems, | |
| severity, | |
| version, | |
| prefix + fieldName, | |
| sourceHint, | |
| - "must not contain any of these characters " + banned + " but found " + string.charAt(index), | |
| + "must not contain any of these characters " + banned + " but found " + string.charAt(i), | |
| tracker); | |
| return false; | |
| } | |
| @@ -2402,7 +2206,7 @@ private static InputLocation getLocation(String fieldName, InputLocationTracker | |
| key = fieldName.substring(fieldName.lastIndexOf('[') + 1, fieldName.length() - 1); | |
| try { | |
| key = Integer.valueOf(key.toString()); | |
| - } catch (NumberFormatException exception) { | |
| + } catch (NumberFormatException e) { | |
| // use key as is | |
| } | |
| } | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/FileToRawModelMerger.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/FileToRawModelMerger.java | |
| new file mode 100644 | |
| index 0000000000..b98d057b30 | |
| --- /dev/null | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/FileToRawModelMerger.java | |
| @@ -0,0 +1,216 @@ | |
| +/* | |
| + * Licensed to the Apache Software Foundation (ASF) under one | |
| + * or more contributor license agreements. See the NOTICE file | |
| + * distributed with this work for additional information | |
| + * regarding copyright ownership. The ASF licenses this file | |
| + * to you under the Apache License, Version 2.0 (the | |
| + * "License"); you may not use this file except in compliance | |
| + * with the License. You may obtain a copy of the License at | |
| + * | |
| + * http://www.apache.org/licenses/LICENSE-2.0 | |
| + * | |
| + * Unless required by applicable law or agreed to in writing, | |
| + * software distributed under the License is distributed on an | |
| + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| + * KIND, either express or implied. See the License for the | |
| + * specific language governing permissions and limitations | |
| + * under the License. | |
| + */ | |
| +package org.apache.maven.impl.model; | |
| + | |
| +import java.util.Iterator; | |
| +import java.util.Map; | |
| +import java.util.stream.Collectors; | |
| + | |
| +import org.apache.maven.api.model.Build; | |
| +import org.apache.maven.api.model.BuildBase; | |
| +import org.apache.maven.api.model.CiManagement; | |
| +import org.apache.maven.api.model.Dependency; | |
| +import org.apache.maven.api.model.DependencyManagement; | |
| +import org.apache.maven.api.model.Model; | |
| +import org.apache.maven.api.model.ModelBase; | |
| +import org.apache.maven.api.model.Plugin; | |
| +import org.apache.maven.api.model.PluginContainer; | |
| +import org.apache.maven.api.model.Profile; | |
| +import org.apache.maven.api.model.ReportPlugin; | |
| +import org.apache.maven.api.model.Reporting; | |
| +import org.apache.maven.model.v4.MavenMerger; | |
| + | |
| +/** | |
| + * As long as Maven controls the BuildPomXMLFilter, the entities that need merging are known. | |
| + * All others can simply be copied from source to target to restore the locationTracker | |
| + * | |
| + * @since 4.0.0 | |
| + */ | |
| +class FileToRawModelMerger extends MavenMerger { | |
| + | |
| + @Override | |
| + protected void mergeBuild_Extensions( | |
| + Build.Builder builder, Build target, Build source, boolean sourceDominant, Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeBuildBase_Resources( | |
| + BuildBase.Builder builder, | |
| + BuildBase target, | |
| + BuildBase source, | |
| + boolean sourceDominant, | |
| + Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeBuildBase_TestResources( | |
| + BuildBase.Builder builder, | |
| + BuildBase target, | |
| + BuildBase source, | |
| + boolean sourceDominant, | |
| + Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeCiManagement_Notifiers( | |
| + CiManagement.Builder builder, | |
| + CiManagement target, | |
| + CiManagement source, | |
| + boolean sourceDominant, | |
| + Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeDependencyManagement_Dependencies( | |
| + DependencyManagement.Builder builder, | |
| + DependencyManagement target, | |
| + DependencyManagement source, | |
| + boolean sourceDominant, | |
| + Map<Object, Object> context) { | |
| + Iterator<Dependency> sourceIterator = source.getDependencies().iterator(); | |
| + builder.dependencies(target.getDependencies().stream() | |
| + .map(d -> mergeDependency(d, sourceIterator.next(), sourceDominant, context)) | |
| + .collect(Collectors.toList())); | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeDependency_Exclusions( | |
| + Dependency.Builder builder, | |
| + Dependency target, | |
| + Dependency source, | |
| + boolean sourceDominant, | |
| + Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeModel_Contributors( | |
| + Model.Builder builder, Model target, Model source, boolean sourceDominant, Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeModel_Developers( | |
| + Model.Builder builder, Model target, Model source, boolean sourceDominant, Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeModel_Licenses( | |
| + Model.Builder builder, Model target, Model source, boolean sourceDominant, Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeModel_MailingLists( | |
| + Model.Builder builder, Model target, Model source, boolean sourceDominant, Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeModel_Profiles( | |
| + Model.Builder builder, Model target, Model source, boolean sourceDominant, Map<Object, Object> context) { | |
| + Iterator<Profile> sourceIterator = source.getProfiles().iterator(); | |
| + builder.profiles(target.getProfiles().stream() | |
| + .map(d -> mergeProfile(d, sourceIterator.next(), sourceDominant, context)) | |
| + .collect(Collectors.toList())); | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeModelBase_Dependencies( | |
| + ModelBase.Builder builder, | |
| + ModelBase target, | |
| + ModelBase source, | |
| + boolean sourceDominant, | |
| + Map<Object, Object> context) { | |
| + Iterator<Dependency> sourceIterator = source.getDependencies().iterator(); | |
| + builder.dependencies(target.getDependencies().stream() | |
| + .map(d -> mergeDependency(d, sourceIterator.next(), sourceDominant, context)) | |
| + .collect(Collectors.toList())); | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeModelBase_PluginRepositories( | |
| + ModelBase.Builder builder, | |
| + ModelBase target, | |
| + ModelBase source, | |
| + boolean sourceDominant, | |
| + Map<Object, Object> context) { | |
| + builder.pluginRepositories(source.getPluginRepositories()); | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeModelBase_Repositories( | |
| + ModelBase.Builder builder, | |
| + ModelBase target, | |
| + ModelBase source, | |
| + boolean sourceDominant, | |
| + Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergePlugin_Dependencies( | |
| + Plugin.Builder builder, Plugin target, Plugin source, boolean sourceDominant, Map<Object, Object> context) { | |
| + Iterator<Dependency> sourceIterator = source.getDependencies().iterator(); | |
| + builder.dependencies(target.getDependencies().stream() | |
| + .map(d -> mergeDependency(d, sourceIterator.next(), sourceDominant, context)) | |
| + .collect(Collectors.toList())); | |
| + } | |
| + | |
| + @Override | |
| + protected void mergePlugin_Executions( | |
| + Plugin.Builder builder, Plugin target, Plugin source, boolean sourceDominant, Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeReporting_Plugins( | |
| + Reporting.Builder builder, | |
| + Reporting target, | |
| + Reporting source, | |
| + boolean sourceDominant, | |
| + Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergeReportPlugin_ReportSets( | |
| + ReportPlugin.Builder builder, | |
| + ReportPlugin target, | |
| + ReportPlugin source, | |
| + boolean sourceDominant, | |
| + Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| + | |
| + @Override | |
| + protected void mergePluginContainer_Plugins( | |
| + PluginContainer.Builder builder, | |
| + PluginContainer target, | |
| + PluginContainer source, | |
| + boolean sourceDominant, | |
| + Map<Object, Object> context) { | |
| + // don't merge | |
| + } | |
| +} | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/reflection/IntrospectionException.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/reflection/IntrospectionException.java | |
| index 726646e702..bfe5e06119 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/reflection/IntrospectionException.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/reflection/IntrospectionException.java | |
| @@ -18,8 +18,16 @@ | |
| */ | |
| package org.apache.maven.impl.model.reflection; | |
| +import java.io.Serial; | |
| + | |
| public class IntrospectionException extends Exception { | |
| + /** | |
| + * | |
| + */ | |
| + @Serial | |
| + private static final long serialVersionUID = -6090771282553728784L; | |
| + | |
| IntrospectionException(String message) { | |
| super(message); | |
| } | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/reflection/MethodMap.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/reflection/MethodMap.java | |
| index d13343bf70..5071b86d39 100644 | |
| --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/reflection/MethodMap.java | |
| +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/reflection/MethodMap.java | |
| @@ -18,6 +18,7 @@ | |
| */ | |
| package org.apache.maven.impl.model.reflection; | |
| +import java.io.Serial; | |
| import java.lang.reflect.Method; | |
| import java.util.ArrayList; | |
| import java.util.Hashtable; | |
| @@ -116,7 +117,11 @@ Method find(String methodName, Object... args) throws AmbiguousException { | |
| * simple distinguishable exception, used when | |
| * we run across ambiguous overloading | |
| */ | |
| - static class AmbiguousException extends Exception {} | |
| + static class AmbiguousException extends Exception { | |
| + | |
| + @Serial | |
| + private static final long serialVersionUID = 751688436639650618L; | |
| + } | |
| private static Method getMostSpecific(List<Method> methods, Class<?>... classes) throws AmbiguousException { | |
| LinkedList<Method> applicables = getApplicables(methods, classes); | |
| diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/ArtifactDescriptorReaderDelegate.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/ArtifactDescriptorRead |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment