You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/05/19 15:10:19 UTC

(maven) branch backport/maven-4.0.x/pr-12105 updated (dc30cbfef5 -> b57809c1f8)

This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a change to branch backport/maven-4.0.x/pr-12105
in repository https://gitbox.apache.org/repos/asf/maven.git


    from dc30cbfef5 [maven-4.0.x] Fix mvnup to replace deprecated ${basedir} in repository URLs (#12105)
     add 904bb60ea3 [maven-4.0.x] fix: propagate addResource() to model Build for Maven 3 compat (#12093)
     add be7d73b2c5 fix: restore buildConfiguration() callback in deprecated build() methods (#12094)
     add aa3b4d33f1 Fix #12075: skip expression validation for distributionManagement repository IDs (#12077)
     add 1b53468bfe Fix #12074: prevent false parent cycle with shade plugin's dependency-reduced-pom.xml (#12079)
     add b8a0ae05a8 [maven-4.0.x] Backport bug fixes from master to maven-4.0.x (#12091)
     add f52d3cae6a Fix #12085: add regression tests for version inheritance from remote parent (#12101)
     add 16c00a84f2 Fix #12081: mvnup: use domtrip XML API on 4.0.x branch to align with master (#12082)
     add 0a792e8a8a Use maven-api Version for mvnup plugin version comparison (#12073)
     new b57809c1f8 Merge remote-tracking branch 'origin/maven-4.0.x' into backport/maven-4.0.x/pr-12105

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../main/appended-resources/META-INF/LICENSE.vm    |   3 +-
 .../model/validation/DefaultModelValidator.java    |  73 ++-
 .../validation/DefaultModelValidatorTest.java      |   4 +
 .../java/org/apache/maven/model/ModelTest.java     |  13 +
 .../plugin/descriptor/PluginDescriptorBuilder.java |  38 +-
 impl/maven-cli/pom.xml                             |   9 +-
 .../maven/cling/invoker/mvnup/UpgradeContext.java  |   2 +-
 .../invoker/mvnup/goals/AbstractUpgradeGoal.java   |  45 +-
 .../mvnup/goals/AbstractUpgradeStrategy.java       |  94 ++-
 .../mvnup/goals/CompatibilityFixStrategy.java      | 490 ++++++--------
 .../maven/cling/invoker/mvnup/goals/DomUtils.java  | 211 ++++++
 .../maven/cling/invoker/mvnup/goals/GAV.java       |  49 --
 .../maven/cling/invoker/mvnup/goals/GAVUtils.java  | 132 ----
 .../invoker/mvnup/goals/InferenceStrategy.java     | 389 +++++------
 .../maven/cling/invoker/mvnup/goals/JDomUtils.java | 544 ----------------
 .../invoker/mvnup/goals/ModelUpgradeStrategy.java  | 209 +++---
 .../invoker/mvnup/goals/ModelVersionUtils.java     |  85 ++-
 .../invoker/mvnup/goals/PluginUpgradeStrategy.java | 209 +++---
 .../cling/invoker/mvnup/goals/PomDiscovery.java    | 273 ++------
 .../invoker/mvnup/goals/StrategyOrchestrator.java  | 193 +++---
 .../invoker/mvnup/goals/UpgradeConstants.java      | 236 -------
 .../cling/invoker/mvnup/goals/UpgradeStrategy.java |  12 +-
 .../cling/invoker/mvnup/goals/package-info.java    |   2 +-
 .../mvnup/goals/AbstractUpgradeGoalTest.java       |   5 +-
 .../mvnup/goals/CompatibilityFixStrategyTest.java  | 124 ++--
 .../cling/invoker/mvnup/goals/DomUtilsTest.java    | 725 +++++++++++++++++++++
 .../maven/cling/invoker/mvnup/goals/GAVTest.java   | 149 -----
 .../cling/invoker/mvnup/goals/GAVUtilsTest.java    | 102 ++-
 .../invoker/mvnup/goals/InferenceStrategyTest.java | 257 ++++----
 .../cling/invoker/mvnup/goals/JDomUtilsTest.java   | 453 -------------
 .../mvnup/goals/ModelUpgradeStrategyTest.java      | 312 ++++-----
 .../invoker/mvnup/goals/ModelVersionUtilsTest.java |  80 ++-
 .../mvnup/goals/PluginUpgradeStrategyTest.java     | 207 +++---
 .../cling/invoker/mvnup/goals/PomBuilder.java      |  10 +-
 .../mvnup/goals/StrategyOrchestratorTest.java      |   2 +-
 .../maven/cling/invoker/mvnup/goals/TestUtils.java |  11 +
 .../maven/project/DefaultProjectBuilder.java       |  17 +-
 .../org/apache/maven/project/MavenProject.java     |  20 +-
 .../maven/project/ProjectBuildingException.java    |  84 ++-
 .../project/DefaultMavenProjectBuilderTest.java    |  39 ++
 .../project/ProjectBuildingExceptionTest.java      | 163 +++++
 .../apache/maven/project/ResourceIncludeTest.java  |  58 ++
 .../org/test/parent-pom/1.0/parent-pom-1.0.pom     |  31 +
 .../child/pom.xml                                  |  12 +
 .../pom.xml                                        |  10 +
 .../parent-version-inherited-from-remote/pom.xml   |  12 +
 .../maven/impl/model/DefaultModelBuilder.java      |  26 +-
 .../maven/impl/model/DefaultModelValidator.java    | 101 ++-
 .../impl/model/DefaultModelValidatorTest.java      |  40 +-
 .../maven/impl/model/ParentCycleDetectionTest.java |  63 ++
 .../raw-model/dm-with-chained-property-in-id.xml   |  22 +-
 pom.xml                                            |  17 +-
 src/graph/ReactorGraph.java                        |   2 +-
 src/mdo/java/WrapperProperties.java                |   6 +
 src/mdo/model-v3.vm                                |   6 +-
 55 files changed, 3201 insertions(+), 3280 deletions(-)
 create mode 100644 impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/DomUtils.java
 delete mode 100644 impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/GAV.java
 delete mode 100644 impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/GAVUtils.java
 delete mode 100644 impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/JDomUtils.java
 delete mode 100644 impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeConstants.java
 create mode 100644 impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/DomUtilsTest.java
 delete mode 100644 impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/GAVTest.java
 delete mode 100644 impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/JDomUtilsTest.java
 create mode 100644 impl/maven-core/src/test/java/org/apache/maven/project/ProjectBuildingExceptionTest.java
 create mode 100644 impl/maven-core/src/test/remote-repo/org/test/parent-pom/1.0/parent-pom-1.0.pom
 create mode 100644 impl/maven-core/src/test/resources/projects/parent-version-inherited-from-remote-multimodule/child/pom.xml
 create mode 100644 impl/maven-core/src/test/resources/projects/parent-version-inherited-from-remote-multimodule/pom.xml
 create mode 100644 impl/maven-core/src/test/resources/projects/parent-version-inherited-from-remote/pom.xml
 copy compat/maven-model-builder/src/test/resources/poms/validation/raw-model/repository-with-expression.xml => impl/maven-impl/src/test/resources/poms/validation/raw-model/dm-with-chained-property-in-id.xml (71%)


(maven) 01/01: Merge remote-tracking branch 'origin/maven-4.0.x' into backport/maven-4.0.x/pr-12105

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch backport/maven-4.0.x/pr-12105
in repository https://gitbox.apache.org/repos/asf/maven.git

commit b57809c1f84e6eedee0b17eeb43da11a0ed3cb92
Merge: dc30cbfef5 0a792e8a8a
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Tue May 19 17:10:09 2026 +0200

    Merge remote-tracking branch 'origin/maven-4.0.x' into backport/maven-4.0.x/pr-12105
    
    # Conflicts:
    #       impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategy.java

 .../main/appended-resources/META-INF/LICENSE.vm    |   3 +-
 .../model/validation/DefaultModelValidator.java    |  73 ++-
 .../validation/DefaultModelValidatorTest.java      |   4 +
 .../java/org/apache/maven/model/ModelTest.java     |  13 +
 .../plugin/descriptor/PluginDescriptorBuilder.java |  38 +-
 impl/maven-cli/pom.xml                             |   9 +-
 .../maven/cling/invoker/mvnup/UpgradeContext.java  |   2 +-
 .../invoker/mvnup/goals/AbstractUpgradeGoal.java   |  45 +-
 .../mvnup/goals/AbstractUpgradeStrategy.java       |  94 ++-
 .../mvnup/goals/CompatibilityFixStrategy.java      | 490 ++++++--------
 .../maven/cling/invoker/mvnup/goals/DomUtils.java  | 211 ++++++
 .../maven/cling/invoker/mvnup/goals/GAV.java       |  49 --
 .../maven/cling/invoker/mvnup/goals/GAVUtils.java  | 132 ----
 .../invoker/mvnup/goals/InferenceStrategy.java     | 389 +++++------
 .../maven/cling/invoker/mvnup/goals/JDomUtils.java | 544 ----------------
 .../invoker/mvnup/goals/ModelUpgradeStrategy.java  | 209 +++---
 .../invoker/mvnup/goals/ModelVersionUtils.java     |  85 ++-
 .../invoker/mvnup/goals/PluginUpgradeStrategy.java | 209 +++---
 .../cling/invoker/mvnup/goals/PomDiscovery.java    | 273 ++------
 .../invoker/mvnup/goals/StrategyOrchestrator.java  | 193 +++---
 .../invoker/mvnup/goals/UpgradeConstants.java      | 236 -------
 .../cling/invoker/mvnup/goals/UpgradeStrategy.java |  12 +-
 .../cling/invoker/mvnup/goals/package-info.java    |   2 +-
 .../mvnup/goals/AbstractUpgradeGoalTest.java       |   5 +-
 .../mvnup/goals/CompatibilityFixStrategyTest.java  | 124 ++--
 .../cling/invoker/mvnup/goals/DomUtilsTest.java    | 725 +++++++++++++++++++++
 .../maven/cling/invoker/mvnup/goals/GAVTest.java   | 149 -----
 .../cling/invoker/mvnup/goals/GAVUtilsTest.java    | 102 ++-
 .../invoker/mvnup/goals/InferenceStrategyTest.java | 257 ++++----
 .../cling/invoker/mvnup/goals/JDomUtilsTest.java   | 453 -------------
 .../mvnup/goals/ModelUpgradeStrategyTest.java      | 312 ++++-----
 .../invoker/mvnup/goals/ModelVersionUtilsTest.java |  80 ++-
 .../mvnup/goals/PluginUpgradeStrategyTest.java     | 207 +++---
 .../cling/invoker/mvnup/goals/PomBuilder.java      |  10 +-
 .../mvnup/goals/StrategyOrchestratorTest.java      |   2 +-
 .../maven/cling/invoker/mvnup/goals/TestUtils.java |  11 +
 .../maven/project/DefaultProjectBuilder.java       |  17 +-
 .../org/apache/maven/project/MavenProject.java     |  20 +-
 .../maven/project/ProjectBuildingException.java    |  84 ++-
 .../project/DefaultMavenProjectBuilderTest.java    |  39 ++
 .../project/ProjectBuildingExceptionTest.java      | 163 +++++
 .../apache/maven/project/ResourceIncludeTest.java  |  58 ++
 .../org/test/parent-pom/1.0/parent-pom-1.0.pom     |  31 +
 .../child/pom.xml                                  |  12 +
 .../pom.xml                                        |  10 +
 .../parent-version-inherited-from-remote/pom.xml   |  12 +
 .../maven/impl/model/DefaultModelBuilder.java      |  26 +-
 .../maven/impl/model/DefaultModelValidator.java    | 101 ++-
 .../impl/model/DefaultModelValidatorTest.java      |  40 +-
 .../maven/impl/model/ParentCycleDetectionTest.java |  63 ++
 .../raw-model/dm-with-chained-property-in-id.xml   |  46 ++
 pom.xml                                            |  17 +-
 src/graph/ReactorGraph.java                        |   2 +-
 src/mdo/java/WrapperProperties.java                |   6 +
 src/mdo/model-v3.vm                                |   6 +-
 55 files changed, 3236 insertions(+), 3269 deletions(-)

diff --cc impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategy.java
index ff572d49b4,266af03dff..fc76df6354
--- 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
@@@ -490,21 -459,19 +459,21 @@@ public class CompatibilityFixStrategy e
          }
  
          boolean fixed = false;
-         String elementType = repositoriesElement.getName().equals(REPOSITORIES) ? REPOSITORY : PLUGIN_REPOSITORY;
-         List<Element> repositories = repositoriesElement.getChildren(elementType, namespace);
+         String elementType = repositoriesElement.name().equals(REPOSITORIES) ? REPOSITORY : PLUGIN_REPOSITORY;
+         List<Element> repositories = repositoriesElement.children(elementType).toList();
  
          for (Element repository : repositories) {
-             Element urlElement = repository.getChild("url", namespace);
+             Element urlElement = repository.child("url").orElse(null);
              if (urlElement != null) {
-                 String url = urlElement.getTextTrim();
+                 String url = urlElement.textContent().trim();
 -                if (url.contains("${")) {
 -                    // Allow repository URL interpolation; do not disable.
 -                    // Keep a gentle warning to help users notice unresolved placeholders at build time.
 +                String fixedUrl =
 +                        url.replace("${basedir}", "${project.basedir}").replace("${pom.basedir}", "${project.basedir}");
 +                if (!fixedUrl.equals(url)) {
-                     urlElement.setText(fixedUrl);
-                     String repositoryId = getChildText(repository, "id", namespace);
++                    urlElement.textContent(fixedUrl);
+                     String repositoryId = repository.childText("id");
 -                    context.info("Detected interpolated expression in " + elementType + " URL (id: " + repositoryId
 -                            + "): " + url);
 +                    context.detail("Fixed: replaced deprecated expression in " + elementType + " URL (id: "
 +                            + repositoryId + "): " + url + " → " + fixedUrl);
 +                    fixed = true;
                  }
              }
          }
diff --cc impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategyTest.java
index 12bbf60f89,af8b0774c7..bfe296769b
--- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategyTest.java
+++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/CompatibilityFixStrategyTest.java
@@@ -287,203 -281,6 +281,203 @@@ class CompatibilityFixStrategyTest 
          }
      }
  
 +    @Nested
 +    @DisplayName("Repository Expression Fixes")
 +    class RepositoryExpressionFixesTests {
 +
 +        @Test
 +        @DisplayName("should replace ${basedir} with ${project.basedir} in repository URLs")
 +        void shouldReplaceBasedirInRepositoryUrls() 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>test</groupId>
 +                    <artifactId>test</artifactId>
 +                    <version>1.0.0</version>
 +                    <repositories>
 +                        <repository>
 +                            <id>local-repo</id>
 +                            <url>file://${basedir}/internal-repository</url>
 +                        </repository>
 +                    </repositories>
 +                </project>
 +                """;
 +
-             Document document = saxBuilder.build(new StringReader(pomXml));
++            Document document = Document.of(pomXml);
 +            Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
 +
 +            UpgradeContext context = createMockContext();
-             UpgradeResult result = strategy.apply(context, pomMap);
++            UpgradeResult result = strategy.doApply(context, pomMap);
 +
 +            assertTrue(result.success(), "Compatibility fix should succeed");
 +            assertTrue(result.modifiedCount() > 0, "Should have fixed basedir expression");
 +
-             Element root = document.getRootElement();
-             Element repositories = root.getChild("repositories", root.getNamespace());
-             Element repository = repositories.getChild("repository", root.getNamespace());
-             Element url = repository.getChild("url", root.getNamespace());
++            Element root = document.root();
++            Element repositories = DomUtils.findChildElement(root, "repositories");
++            Element repository = DomUtils.findChildElement(repositories, "repository");
++            Element url = DomUtils.findChildElement(repository, "url");
 +            assertEquals(
 +                    "file://${project.basedir}/internal-repository",
-                     url.getTextTrim(),
++                    url.textContent().trim(),
 +                    "Should have replaced ${basedir} with ${project.basedir}");
 +        }
 +
 +        @Test
 +        @DisplayName("should replace ${pom.basedir} with ${project.basedir} in repository URLs")
 +        void shouldReplacePomBasedirInRepositoryUrls() 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>test</groupId>
 +                    <artifactId>test</artifactId>
 +                    <version>1.0.0</version>
 +                    <repositories>
 +                        <repository>
 +                            <id>local-repo</id>
 +                            <url>file://${pom.basedir}/lib</url>
 +                        </repository>
 +                    </repositories>
 +                </project>
 +                """;
 +
-             Document document = saxBuilder.build(new StringReader(pomXml));
++            Document document = Document.of(pomXml);
 +            Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
 +
 +            UpgradeContext context = createMockContext();
-             UpgradeResult result = strategy.apply(context, pomMap);
++            UpgradeResult result = strategy.doApply(context, pomMap);
 +
 +            assertTrue(result.success(), "Compatibility fix should succeed");
 +            assertTrue(result.modifiedCount() > 0, "Should have fixed pom.basedir expression");
 +
-             Element root = document.getRootElement();
-             Element repositories = root.getChild("repositories", root.getNamespace());
-             Element repository = repositories.getChild("repository", root.getNamespace());
-             Element url = repository.getChild("url", root.getNamespace());
++            Element root = document.root();
++            Element repositories = DomUtils.findChildElement(root, "repositories");
++            Element repository = DomUtils.findChildElement(repositories, "repository");
++            Element url = DomUtils.findChildElement(repository, "url");
 +            assertEquals(
 +                    "file://${project.basedir}/lib",
-                     url.getTextTrim(),
++                    url.textContent().trim(),
 +                    "Should have replaced ${pom.basedir} with ${project.basedir}");
 +        }
 +
 +        @Test
 +        @DisplayName("should replace ${basedir} in pluginRepository URLs")
 +        void shouldReplaceBasedirInPluginRepositoryUrls() 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>test</groupId>
 +                    <artifactId>test</artifactId>
 +                    <version>1.0.0</version>
 +                    <pluginRepositories>
 +                        <pluginRepository>
 +                            <id>local-plugins</id>
 +                            <url>file://${basedir}/plugin-repo</url>
 +                        </pluginRepository>
 +                    </pluginRepositories>
 +                </project>
 +                """;
 +
-             Document document = saxBuilder.build(new StringReader(pomXml));
++            Document document = Document.of(pomXml);
 +            Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
 +
 +            UpgradeContext context = createMockContext();
-             UpgradeResult result = strategy.apply(context, pomMap);
++            UpgradeResult result = strategy.doApply(context, pomMap);
 +
 +            assertTrue(result.success(), "Compatibility fix should succeed");
 +            assertTrue(result.modifiedCount() > 0, "Should have fixed basedir in pluginRepository");
 +
-             Element root = document.getRootElement();
-             Element pluginRepositories = root.getChild("pluginRepositories", root.getNamespace());
-             Element pluginRepository = pluginRepositories.getChild("pluginRepository", root.getNamespace());
-             Element url = pluginRepository.getChild("url", root.getNamespace());
++            Element root = document.root();
++            Element pluginRepositories = DomUtils.findChildElement(root, "pluginRepositories");
++            Element pluginRepository = DomUtils.findChildElement(pluginRepositories, "pluginRepository");
++            Element url = DomUtils.findChildElement(pluginRepository, "url");
 +            assertEquals(
 +                    "file://${project.basedir}/plugin-repo",
-                     url.getTextTrim(),
++                    url.textContent().trim(),
 +                    "Should have replaced ${basedir} with ${project.basedir}");
 +        }
 +
 +        @Test
 +        @DisplayName("should replace ${basedir} in profile repository URLs")
 +        void shouldReplaceBasedirInProfileRepositoryUrls() 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>test</groupId>
 +                    <artifactId>test</artifactId>
 +                    <version>1.0.0</version>
 +                    <profiles>
 +                        <profile>
 +                            <id>local</id>
 +                            <repositories>
 +                                <repository>
 +                                    <id>local-repo</id>
 +                                    <url>file://${basedir}/repo</url>
 +                                </repository>
 +                            </repositories>
 +                        </profile>
 +                    </profiles>
 +                </project>
 +                """;
 +
-             Document document = saxBuilder.build(new StringReader(pomXml));
++            Document document = Document.of(pomXml);
 +            Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
 +
 +            UpgradeContext context = createMockContext();
-             UpgradeResult result = strategy.apply(context, pomMap);
++            UpgradeResult result = strategy.doApply(context, pomMap);
 +
 +            assertTrue(result.success(), "Compatibility fix should succeed");
 +            assertTrue(result.modifiedCount() > 0, "Should have fixed basedir in profile repository");
 +
-             Element root = document.getRootElement();
-             Element profiles = root.getChild("profiles", root.getNamespace());
-             Element profile = profiles.getChild("profile", root.getNamespace());
-             Element repositories = profile.getChild("repositories", root.getNamespace());
-             Element repository = repositories.getChild("repository", root.getNamespace());
-             Element url = repository.getChild("url", root.getNamespace());
++            Element root = document.root();
++            Element profiles = DomUtils.findChildElement(root, "profiles");
++            Element profile = DomUtils.findChildElement(profiles, "profile");
++            Element repositories = DomUtils.findChildElement(profile, "repositories");
++            Element repository = DomUtils.findChildElement(repositories, "repository");
++            Element url = DomUtils.findChildElement(repository, "url");
 +            assertEquals(
 +                    "file://${project.basedir}/repo",
-                     url.getTextTrim(),
++                    url.textContent().trim(),
 +                    "Should have replaced ${basedir} with ${project.basedir}");
 +        }
 +
 +        @Test
 +        @DisplayName("should not modify repository URLs without deprecated expressions")
 +        void shouldNotModifyUrlsWithoutDeprecatedExpressions() 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>test</groupId>
 +                    <artifactId>test</artifactId>
 +                    <version>1.0.0</version>
 +                    <repositories>
 +                        <repository>
 +                            <id>central</id>
 +                            <url>https://repo.maven.apache.org/maven2</url>
 +                        </repository>
 +                        <repository>
 +                            <id>local-repo</id>
 +                            <url>file://${project.basedir}/repo</url>
 +                        </repository>
 +                    </repositories>
 +                </project>
 +                """;
 +
-             Document document = saxBuilder.build(new StringReader(pomXml));
++            Document document = Document.of(pomXml);
 +            Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
 +
 +            UpgradeContext context = createMockContext();
-             UpgradeResult result = strategy.apply(context, pomMap);
++            UpgradeResult result = strategy.doApply(context, pomMap);
 +
 +            assertTrue(result.success(), "Compatibility fix should succeed");
 +            assertEquals(0, result.modifiedCount(), "Should not have modified any POMs");
 +        }
 +    }
 +
      @Nested
      @DisplayName("Strategy Description")
      class StrategyDescriptionTests {
diff --cc impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java
index ada85cdf0e,2ba4de0c2b..18ee2cdc76
--- a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java
+++ b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategyTest.java
@@@ -195,6 -187,46 +187,47 @@@ class PluginUpgradeStrategyTest 
              // POM might still be marked as modified due to other plugin management additions
          }
  
+         @Test
+         @DisplayName("should upgrade milestone version below release minimum")
+         void shouldUpgradeMilestoneVersionBelowRelease() 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>test</groupId>
+                     <artifactId>test</artifactId>
+                     <version>1.0.0</version>
+                     <build>
+                         <plugins>
+                             <plugin>
+                                 <groupId>org.apache.maven.plugins</groupId>
+                                 <artifactId>maven-enforcer-plugin</artifactId>
+                                 <version>3.0.0-M1</version>
+                             </plugin>
+                         </plugins>
+                     </build>
+                 </project>
+                 """;
+ 
 -            Document document = saxBuilder.build(new StringReader(pomXml));
++            Document document = Document.of(pomXml);
+             Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);
+ 
+             UpgradeContext context = createMockContext();
 -            UpgradeResult result = strategy.apply(context, pomMap);
++            UpgradeResult result = strategy.doApply(context, pomMap);
+ 
+             assertTrue(result.success(), "Plugin upgrade should succeed");
+             assertTrue(result.modifiedCount() > 0, "Should have upgraded 3.0.0-M1 to 3.0.0");
+ 
 -            Element root = document.getRootElement();
 -            Namespace namespace = root.getNamespace();
 -            Element build = root.getChild("build", namespace);
 -            Element plugins = build.getChild("plugins", namespace);
 -            Element plugin = plugins.getChild("plugin", namespace);
 -            String version = plugin.getChildText("version", namespace);
++            Element root = document.root();
++            Element build = DomUtils.findChildElement(root, "build");
++            Element plugins = DomUtils.findChildElement(build, "plugins");
++            Element plugin = DomUtils.findChildElement(plugins, "plugin");
++            Element versionElement = DomUtils.findChildElement(plugin, "version");
++            String version =
++                    versionElement != null ? versionElement.textContent().trim() : null;
+             assertEquals("3.0.0", version, "3.0.0-M1 should be upgraded to 3.0.0");
+         }
+ 
          @Test
          @DisplayName("should upgrade plugin in pluginManagement")
          void shouldUpgradePluginInPluginManagement() throws Exception {