Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@

import static eu.maveniverse.domtrip.maven.MavenPomElements.Elements.ARTIFACT_ID;
import static eu.maveniverse.domtrip.maven.MavenPomElements.Elements.BUILD;
import static eu.maveniverse.domtrip.maven.MavenPomElements.Elements.DEPENDENCIES;
import static eu.maveniverse.domtrip.maven.MavenPomElements.Elements.DEPENDENCY;
import static eu.maveniverse.domtrip.maven.MavenPomElements.Elements.GROUP_ID;
import static eu.maveniverse.domtrip.maven.MavenPomElements.Elements.PARENT;
import static eu.maveniverse.domtrip.maven.MavenPomElements.Elements.PLUGIN;
Expand Down Expand Up @@ -100,6 +102,12 @@ public class PluginUpgradeStrategy extends AbstractUpgradeStrategy {
"3.0.0",
MAVEN_4_COMPATIBILITY_REASON));

private static final List<PluginUpgrade> PLUGIN_DEPENDENCY_UPGRADES = List.of(new PluginUpgrade(
"org.codehaus.mojo",
"extra-enforcer-rules",
"1.4",
"Versions before 1.4 use a removed DependencyGraphBuilder API incompatible with Maven 4"));

private Session session;

@Inject
Expand Down Expand Up @@ -262,6 +270,7 @@ private boolean upgradePluginsInSection(
return pluginsElement
.children(PLUGIN)
.map(pluginElement -> {
boolean upgraded = false;
String groupId = getChildText(pluginElement, GROUP_ID);
String artifactId = getChildText(pluginElement, ARTIFACT_ID);

Expand All @@ -275,10 +284,13 @@ private boolean upgradePluginsInSection(
PluginUpgradeInfo upgrade = pluginUpgrades.get(pluginKey);

if (upgrade != null) {
return upgradePluginVersion(pluginElement, upgrade, pomDocument, sectionName, context);
upgraded = upgradePluginVersion(pluginElement, upgrade, pomDocument, sectionName, context);
}
}
return false;

upgraded |= upgradePluginDependencies(pluginElement, pomDocument, sectionName, context);

return upgraded;
})
.reduce(false, Boolean::logicalOr);
}
Expand Down Expand Up @@ -370,6 +382,46 @@ private boolean upgradePropertyVersion(
return false;
}

/**
* Upgrades plugin dependencies (e.g., extra-enforcer-rules inside maven-enforcer-plugin).
*/
private boolean upgradePluginDependencies(
Element pluginElement, Document pomDocument, String sectionName, UpgradeContext context) {
Element dependenciesElement = pluginElement.child(DEPENDENCIES).orElse(null);
if (dependenciesElement == null) {
return false;
}

Map<String, PluginUpgradeInfo> depUpgrades = getPluginDependencyUpgradesMap();

return dependenciesElement
.children(DEPENDENCY)
.map(depElement -> {
String groupId = getChildText(depElement, GROUP_ID);
String artifactId = getChildText(depElement, ARTIFACT_ID);

if (groupId != null && artifactId != null) {
String depKey = groupId + ":" + artifactId;
PluginUpgradeInfo upgrade = depUpgrades.get(depKey);

if (upgrade != null) {
return upgradePluginVersion(
depElement, upgrade, pomDocument, sectionName + "/plugin/dependencies", context);
}
}
return false;
})
.reduce(false, Boolean::logicalOr);
}

private Map<String, PluginUpgradeInfo> getPluginDependencyUpgradesMap() {
return PLUGIN_DEPENDENCY_UPGRADES.stream()
.collect(Collectors.toMap(
upgrade -> upgrade.groupId() + ":" + upgrade.artifactId(),
upgrade ->
new PluginUpgradeInfo(upgrade.groupId(), upgrade.artifactId(), upgrade.minVersion())));
}

/**
* Simple version comparison to check if current version is below minimum version.
* This is a basic implementation that works for most Maven plugin versions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,93 @@ void shouldNotUpgradeWhenPropertyNotFound() throws Exception {
}
}

@Nested
@DisplayName("Plugin Dependency Upgrades")
class PluginDependencyUpgradeTests {

@Test
@DisplayName("should upgrade extra-enforcer-rules dependency when below minimum")
void shouldUpgradeExtraEnforcerRulesDependency() 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.5.0</version>
<dependencies>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>extra-enforcer-rules</artifactId>
<version>1.0-beta-4</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
""";

Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);

UpgradeContext context = createMockContext();
UpgradeResult result = strategy.doApply(context, pomMap);

assertTrue(result.success(), "Plugin dependency upgrade should succeed");
assertTrue(result.modifiedCount() > 0, "Should have upgraded extra-enforcer-rules");

String xml = document.toXml();
assertTrue(xml.contains("<version>1.4</version>"), "extra-enforcer-rules should be upgraded to 1.4");
assertFalse(xml.contains("1.0-beta-4"), "Old version should be gone");
}

@Test
@DisplayName("should not upgrade extra-enforcer-rules when version is already sufficient")
void shouldNotUpgradeExtraEnforcerRulesWhenSufficient() 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.5.0</version>
<dependencies>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>extra-enforcer-rules</artifactId>
<version>1.8.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
""";

Document document = Document.of(pomXml);
Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), document);

UpgradeContext context = createMockContext();
strategy.doApply(context, pomMap);

String xml = document.toXml();
assertTrue(xml.contains("1.8.0"), "Version 1.8.0 should be preserved");
}
}

@Nested
@DisplayName("Plugin Management")
class PluginManagementTests {
Expand Down
Loading