Skip to content

Commit bcf9838

Browse files
authored
[MNG-8765] Maven Upgrade Tool (#2407)
## Maven Upgrade Tool (mvnup) - New `mvnup` command-line tool with check/apply workflow - Automatic POM discovery and multi-module project support - Model version upgrades from 4.0.0 to 4.1.0 with namespace updates - Intelligent inference to remove redundant information in Maven 4.1.0+ models - Comprehensive plugin compatibility upgrades for Maven 4 ### Plugin Compatibility & Upgrades - Automatic plugin version upgrades for Maven 4 compatibility: * `maven-exec-plugin` → 3.2.0+ * `maven-enforcer-plugin` → 3.0.0+ * `flatten-maven-plugin` → 1.2.7+ * `maven-shade-plugin` → 3.5.0+ * `maven-remote-resources-plugin` → 3.0.0+ - Parent POM plugin detection with proper XML formatting - Plugin management section creation with correct element ordering - Property-based version management support ### Maven 4 Compatibility Fixes - Fix unsupported `combine.children` attributes (`override` → `merge`) - Fix unsupported `combine.self` attributes (`append` → `merge`) - Remove duplicate dependencies in `dependencyManagement` sections - Remove duplicate plugins in `pluginManagement` sections - Comment out repositories with unsupported expressions - Fix incorrect `parent.relativePath` pointing to non-existent POMs - Create `.mvn` directory when not upgrading to 4.1.0 to avoid warnings ### Intelligent Model Inference - Parent element trimming when parent is in same project - Managed dependency removal for project artifacts - Redundant subprojects list removal when matching direct children - GroupId/version inference from parent when using relativePath - Dependency inference that reverses Maven's resolution logic ### Advanced XML Processing - Intelligent indentation detection supporting 2/4 spaces and tabs - Document-wide formatting consistency preservation - Proper element ordering following Maven POM schema standards - pluginManagement placement before plugins sections - Comprehensive JDOM-based XML manipulation with formatting preservation
1 parent 90457e5 commit bcf9838

File tree

63 files changed

+11747
-21
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+11747
-21
lines changed

apache-maven/src/assembly/component.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ under the License.
8787
<include>mvn</include>
8888
<include>mvnenc</include>
8989
<include>mvnsh</include>
90+
<include>mvnup</include>
9091
<include>mvnDebug</include>
9192
<include>mvnencDebug</include>
9293
<!-- This is so that CI systems can periodically run the profiler -->

apache-maven/src/assembly/maven/bin/mvn

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ handle_args() {
228228
--shell)
229229
MAVEN_MAIN_CLASS="org.apache.maven.cling.MavenShellCling"
230230
;;
231+
--up)
232+
MAVEN_MAIN_CLASS="org.apache.maven.cling.MavenUpCling"
233+
;;
231234
*)
232235
;;
233236
esac

apache-maven/src/assembly/maven/bin/mvn.cmd

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,22 +179,22 @@ if not exist "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadJvmConfig
179179
set JVM_CONFIG_MAVEN_OPTS=
180180
for /F "usebackq tokens=* delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do (
181181
set "line=%%a"
182-
182+
183183
rem Skip empty lines and full-line comments
184184
echo !line! | findstr /b /r /c:"[ ]*#" >nul
185185
if errorlevel 1 (
186186
rem Handle end-of-line comments by taking everything before #
187187
for /f "tokens=1* delims=#" %%i in ("!line!") do set "line=%%i"
188-
188+
189189
rem Trim leading/trailing spaces while preserving spaces in quotes
190190
set "trimmed=!line!"
191191
for /f "tokens=* delims= " %%i in ("!trimmed!") do set "trimmed=%%i"
192192
for /l %%i in (1,1,100) do if "!trimmed:~-1!"==" " set "trimmed=!trimmed:~0,-1!"
193-
193+
194194
rem Replace MAVEN_PROJECTBASEDIR placeholders
195195
set "trimmed=!trimmed:${MAVEN_PROJECTBASEDIR}=%MAVEN_PROJECTBASEDIR%!"
196196
set "trimmed=!trimmed:$MAVEN_PROJECTBASEDIR=%MAVEN_PROJECTBASEDIR%!"
197-
197+
198198
if not "!trimmed!"=="" (
199199
if "!JVM_CONFIG_MAVEN_OPTS!"=="" (
200200
set "JVM_CONFIG_MAVEN_OPTS=!trimmed!"
@@ -229,6 +229,8 @@ if "%~1"=="--debug" (
229229
set "MAVEN_MAIN_CLASS=org.apache.maven.cling.MavenEncCling"
230230
) else if "%~1"=="--shell" (
231231
set "MAVEN_MAIN_CLASS=org.apache.maven.cling.MavenShellCling"
232+
) else if "%~1"=="--up" (
233+
set "MAVEN_MAIN_CLASS=org.apache.maven.cling.MavenUpCling"
232234
)
233235
exit /b 0
234236

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/sh
2+
3+
# Licensed to the Apache Software Foundation (ASF) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The ASF licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
19+
20+
# -----------------------------------------------------------------------------
21+
# Apache Maven Upgrade Script
22+
#
23+
# Environment Variable Prerequisites
24+
#
25+
# JAVA_HOME (Optional) Points to a Java installation.
26+
# MAVEN_OPTS (Optional) Java runtime options used when Maven is executed.
27+
# MAVEN_SKIP_RC (Optional) Flag to disable loading of mavenrc files.
28+
# -----------------------------------------------------------------------------
29+
30+
"`dirname "$0"`/mvn" --up "$@"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
@REM Licensed to the Apache Software Foundation (ASF) under one
2+
@REM or more contributor license agreements. See the NOTICE file
3+
@REM distributed with this work for additional information
4+
@REM regarding copyright ownership. The ASF licenses this file
5+
@REM to you under the Apache License, Version 2.0 (the
6+
@REM "License"); you may not use this file except in compliance
7+
@REM with the License. You may obtain a copy of the License at
8+
@REM
9+
@REM http://www.apache.org/licenses/LICENSE-2.0
10+
@REM
11+
@REM Unless required by applicable law or agreed to in writing,
12+
@REM software distributed under the License is distributed on an
13+
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
@REM KIND, either express or implied. See the License for the
15+
@REM specific language governing permissions and limitations
16+
@REM under the License.
17+
18+
@REM -----------------------------------------------------------------------------
19+
@REM Apache Maven Upgrade Script
20+
@REM
21+
@REM Environment Variable Prerequisites
22+
@REM
23+
@REM JAVA_HOME (Optional) Points to a Java installation.
24+
@REM MAVEN_OPTS (Optional) Java runtime options used when Maven is executed.
25+
@REM MAVEN_SKIP_RC (Optional) Flag to disable loading of mavenrc files.
26+
@REM -----------------------------------------------------------------------------
27+
28+
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
29+
@echo off
30+
@REM set title of command window
31+
title %0
32+
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
33+
@if "%MAVEN_BATCH_ECHO%"=="on" echo %MAVEN_BATCH_ECHO%
34+
35+
@setlocal
36+
37+
@call "%~dp0"mvn.cmd --up %*

apache-maven/src/main/appended-resources/META-INF/LICENSE.vm

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,22 @@ subject to the terms and conditions of the following licenses:
3939
#* *##set ( $spdx = 'EPL-1.0' )
4040
#* *##elseif ( $license.name == "Eclipse Public License, Version 2.0" )
4141
#* *##set ( $spdx = 'EPL-2.0' )
42-
#* *##elseif ( $license.url.contains( "www.apache.org/licenses/LICENSE-2.0" ) )
42+
#* *##elseif ( $license.url.contains( "www.apache.org/licenses/LICENSE-2.0" )
43+
|| $license.url.contains( "https://raw.github.com/hunterhacker/jdom/master/LICENSE.txt" ) )
4344
#* *##set ( $spdx = 'Apache-2.0' )
4445
#* *##elseif ( $license.name == "BSD-2-Clause" || $license.name == "The BSD 2-Clause License"
45-
|| $license.url.contains("www.opensource.org/licenses/bsd-license") )
46+
|| $license.url.contains( "www.opensource.org/licenses/bsd-license" ) )
4647
#* *##set ( $spdx = 'BSD-2-Clause' )
4748
#* *##elseif ( $license.name == "BSD-3-Clause"
48-
|| $license.url.contains("opensource.org/licenses/BSD-3-Clause") )
49+
|| $license.url.contains( "opensource.org/licenses/BSD-3-Clause" ) )
4950
#* *##set ( $spdx = 'BSD-3-Clause' )
5051
#* *##elseif ( $license.name == "Public Domain" )
5152
#* *##set ( $spdx = 'Public-Domain' )
5253
#* *##elseif ( $license.name == "CDDL + GPLv2 with classpath exception" )
5354
#* *##set ( $spdx = 'CDDL+GPLv2-with-classpath-exception' )
5455
#* *##else
5556
#* *### unrecognized license will require analysis to know obligations
56-
#* *##set ( $spdx = 'unrecognized' )
57+
#* *##set ( $spdx = $license )
5758
#* *##end
5859
#* *###
5960
#* *### fix project urls that are wrong in pom

api/maven-api-cli/src/main/java/org/apache/maven/api/cli/ParserRequest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,30 @@ static Builder mvnsh(@Nonnull List<String> args, @Nonnull MessageBuilderFactory
229229
return builder(Tools.MVNSHELL_CMD, Tools.MVNSHELL_NAME, args, messageBuilderFactory);
230230
}
231231

232+
/**
233+
* Creates a new Builder instance for constructing a Maven Upgrade Tool ParserRequest.
234+
*
235+
* @param args the command-line arguments
236+
* @param messageBuilderFactory the factory for creating message builders
237+
* @return a new Builder instance
238+
*/
239+
@Nonnull
240+
static Builder mvnup(@Nonnull String[] args, @Nonnull MessageBuilderFactory messageBuilderFactory) {
241+
return mvnup(Arrays.asList(args), messageBuilderFactory);
242+
}
243+
244+
/**
245+
* Creates a new Builder instance for constructing a Maven Upgrade Tool ParserRequest.
246+
*
247+
* @param args the command-line arguments
248+
* @param messageBuilderFactory the factory for creating message builders
249+
* @return a new Builder instance
250+
*/
251+
@Nonnull
252+
static Builder mvnup(@Nonnull List<String> args, @Nonnull MessageBuilderFactory messageBuilderFactory) {
253+
return builder(Tools.MVNUP_CMD, Tools.MVNUP_NAME, args, messageBuilderFactory);
254+
}
255+
232256
/**
233257
* Creates a new Builder instance for constructing a ParserRequest.
234258
*

api/maven-api-cli/src/main/java/org/apache/maven/api/cli/Tools.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,7 @@ private Tools() {}
3939

4040
public static final String MVNSHELL_CMD = "mvnsh";
4141
public static final String MVNSHELL_NAME = "Maven Shell Tool";
42+
43+
public static final String MVNUP_CMD = "mvnup";
44+
public static final String MVNUP_NAME = "Maven Upgrade Tool";
4245
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.api.cli.mvnup;
20+
21+
import java.util.List;
22+
import java.util.Optional;
23+
import java.util.function.UnaryOperator;
24+
25+
import org.apache.maven.api.annotations.Experimental;
26+
import org.apache.maven.api.annotations.Nonnull;
27+
import org.apache.maven.api.cli.Options;
28+
29+
/**
30+
* Defines the options specific to the Maven upgrade tool.
31+
* This interface extends the general {@link Options} interface, adding upgrade-specific configuration options.
32+
*
33+
* @since 4.0.0
34+
*/
35+
@Experimental
36+
public interface UpgradeOptions extends Options {
37+
/**
38+
* Should the operation be forced (ie overwrite existing files, if any).
39+
*
40+
* @return an {@link Optional} containing the boolean value {@code true} if specified, or empty
41+
*/
42+
Optional<Boolean> force();
43+
44+
/**
45+
* Should imply "yes" to all questions.
46+
*
47+
* @return an {@link Optional} containing the boolean value {@code true} if specified, or empty
48+
*/
49+
Optional<Boolean> yes();
50+
51+
/**
52+
* Returns the list of upgrade goals to be executed.
53+
* These goals can include operations like "check", "dependencies", "plugins", etc.
54+
*
55+
* @return an {@link Optional} containing the list of goals, or empty if not specified
56+
*/
57+
@Nonnull
58+
Optional<List<String>> goals();
59+
60+
/**
61+
* Returns the target POM model version for upgrades.
62+
* Supported values include "4.0.0" and "4.1.0".
63+
*
64+
* @return an {@link Optional} containing the model version, or empty if not specified
65+
*/
66+
@Nonnull
67+
Optional<String> modelVersion();
68+
69+
/**
70+
* Returns the directory to use as starting point for POM discovery.
71+
* If not specified, the current directory will be used.
72+
*
73+
* @return an {@link Optional} containing the directory path, or empty if not specified
74+
*/
75+
@Nonnull
76+
Optional<String> directory();
77+
78+
/**
79+
* Should use inference when upgrading (remove redundant information).
80+
*
81+
* @return an {@link Optional} containing the boolean value {@code true} if specified, or empty
82+
*/
83+
@Nonnull
84+
Optional<Boolean> infer();
85+
86+
/**
87+
* Should fix Maven 4 compatibility issues in POMs.
88+
* This includes fixing unsupported combine attributes, duplicate dependencies,
89+
* unsupported expressions, and other Maven 4 validation issues.
90+
*
91+
* @return an {@link Optional} containing the boolean value {@code true} if specified, or empty
92+
*/
93+
@Nonnull
94+
Optional<Boolean> model();
95+
96+
/**
97+
* Should upgrade plugins known to fail with Maven 4 to their minimum compatible versions.
98+
* This includes upgrading plugins like maven-exec-plugin, maven-enforcer-plugin,
99+
* flatten-maven-plugin, and maven-shade-plugin to versions that work with Maven 4.
100+
*
101+
* @return an {@link Optional} containing the boolean value {@code true} if specified, or empty
102+
*/
103+
@Nonnull
104+
Optional<Boolean> plugins();
105+
106+
/**
107+
* Should apply all upgrade options (equivalent to --model-version 4.1.0 --infer --model --plugins).
108+
* This is a convenience option that combines model upgrade, inference, compatibility fixes, and plugin upgrades.
109+
*
110+
* @return an {@link Optional} containing the boolean value {@code true} if specified, or empty
111+
*/
112+
@Nonnull
113+
Optional<Boolean> all();
114+
115+
/**
116+
* Returns a new instance of UpgradeOptions with values interpolated using the given properties.
117+
*
118+
* @param callback a callback to use for interpolation
119+
* @return a new UpgradeOptions instance with interpolated values
120+
*/
121+
@Nonnull
122+
UpgradeOptions interpolate(UnaryOperator<String> callback);
123+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
/**
21+
* Provides the API for the Maven Upgrade tool ({@code mvnup}).
22+
*
23+
* <p>This package contains interfaces and classes for the Maven upgrade tool,
24+
* which provides functionality for upgrading Maven projects and dependencies.</p>
25+
*
26+
* <p>Key features include:</p>
27+
* <ul>
28+
* <li>Project upgrade capabilities</li>
29+
* <li>Dependency version management</li>
30+
* <li>Configuration migration</li>
31+
* <li>Interactive upgrade workflows</li>
32+
* </ul>
33+
*
34+
* @see org.apache.maven.api.cli.Tools#MVNUP_CMD
35+
* @see org.apache.maven.api.cli.Tools#MVNUP_NAME
36+
* @since 4.0.0
37+
*/
38+
package org.apache.maven.api.cli.mvnup;

0 commit comments

Comments
 (0)