Skip to content

Instantly share code, notes, and snippets.

@gnodet
Created October 10, 2025 09:21
Show Gist options
  • Select an option

  • Save gnodet/5f3a2fec143e9e0270bfa238172dabe9 to your computer and use it in GitHub Desktop.

Select an option

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.
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