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/09/02 15:35:09 UTC

(maven) branch backport/13001-mvnup-bnd-plugin-upgrade created (now 5d0ee80870)

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

gnodet pushed a change to branch backport/13001-mvnup-bnd-plugin-upgrade
in repository https://gitbox.apache.org/repos/asf/maven.git


      at 5d0ee80870 mvnup: upgrade BND plugins to fix ConcurrentModificationException on JDK 17.0.13+ (#13001)

This branch includes the following new commits:

     new 5d0ee80870 mvnup: upgrade BND plugins to fix ConcurrentModificationException on JDK 17.0.13+ (#13001)

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.



(maven) 01/01: mvnup: upgrade BND plugins to fix ConcurrentModificationException on JDK 17.0.13+ (#13001)

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

gnodet pushed a commit to branch backport/13001-mvnup-bnd-plugin-upgrade
in repository https://gitbox.apache.org/repos/asf/maven.git

commit 5d0ee808705410c4df206614fc57669bd11b8c47
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Sep 2 17:34:30 2026 +0200

    mvnup: upgrade BND plugins to fix ConcurrentModificationException on JDK 17.0.13+ (#13001)
    
    * mvnup: upgrade BND plugins to fix ConcurrentModificationException on JDK 17.0.13+
    
    bndlib < 5.1.0 has a bug (FELIX-6259) where Jar.putResource() modifies
    a TreeMap inside its own computeIfAbsent() call. JDK 17.0.13+ backported
    CME detection for TreeMap.computeIfAbsent() (JDK-8259535), so Maven 4
    (which requires JDK 17+) always hits this with old BND plugin versions.
    
    Add maven-bundle-plugin (>= 5.1.1) and bnd-maven-plugin (>= 5.1.0) to
    the mvnup plugin upgrade list so that `mvn mvnup:check` / `mvn mvnup:apply`
    detects and upgrades these plugins automatically.
    
    Fixes #12987
    
    Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
    
    * Fix inaccurate reason text: use generic description matching actual stack traces
    
    The issue's stack trace shows HashMap$HashIterator.nextNode, not
    TreeMap.computeIfAbsent — simplify the reason to "internal collection
    mutation bugs" which covers both manifestations.
    
    Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
    
    ---------
    
    Co-authored-by: Claude Opus 4.6 <no...@anthropic.com>
---
 .../invoker/mvnup/goals/PluginUpgradeStrategy.java | 14 ++++-
 .../mvnup/goals/PluginUpgradeStrategyTest.java     | 70 +++++++++++++++++++++-
 2 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategy.java b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategy.java
index 2efdc867bb..3f853e7aa9 100644
--- a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategy.java
+++ b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PluginUpgradeStrategy.java
@@ -157,7 +157,19 @@ public class PluginUpgradeStrategy extends AbstractUpgradeStrategy {
                     DEFAULT_MAVEN_PLUGIN_GROUP_ID,
                     "maven-ear-plugin",
                     "3.4.0",
-                    "Older versions use plexus-archiver reflection blocked by JDK 17+ module system"));
+                    "Older versions use plexus-archiver reflection blocked by JDK 17+ module system"),
+            new PluginUpgrade(
+                    "org.apache.felix",
+                    "maven-bundle-plugin",
+                    "5.1.1",
+                    "Versions before 5.1.1 use bndlib < 5.1.0 which has internal collection mutation bugs"
+                            + " (FELIX-6259) that throw ConcurrentModificationException on JDK 17+"),
+            new PluginUpgrade(
+                    "biz.aQute.bnd",
+                    "bnd-maven-plugin",
+                    "5.1.0",
+                    "Versions before 5.1.0 have internal collection mutation bugs (FELIX-6259)"
+                            + " that throw ConcurrentModificationException on JDK 17+"));
 
     private static final List<PluginUpgrade> PLUGIN_DEPENDENCY_UPGRADES = List.of(new PluginUpgrade(
             "org.codehaus.mojo",
diff --git 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
index 272b57b5c2..6338b2a0fc 100644
--- 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
@@ -503,6 +503,72 @@ void shouldUpgradeEarPluginWhenBelowMinimum() throws Exception {
             assertEquals("3.4.0", version, "maven-ear-plugin should be upgraded to 3.4.0");
         }
 
+        @Test
+        @DisplayName("should upgrade maven-bundle-plugin when below minimum")
+        void shouldUpgradeBundlePluginWhenBelowMinimum() throws Exception {
+            Document doc = PomBuilder.create()
+                    .plugin("org.apache.felix", "maven-bundle-plugin", "4.2.1")
+                    .buildDocument();
+            UpgradeResult result = strategy.doApply(createMockContext(), Map.of(Paths.get("pom.xml"), doc));
+
+            assertTrue(result.success() && result.modifiedCount() > 0, "Should have upgraded maven-bundle-plugin");
+            String version = new Editor(doc)
+                    .root()
+                    .path("build", "plugins", "plugin", "version")
+                    .map(Element::textContentTrimmed)
+                    .orElse(null);
+            assertEquals("5.1.1", version, "maven-bundle-plugin should be upgraded to 5.1.1");
+        }
+
+        @Test
+        @DisplayName("should not upgrade maven-bundle-plugin when version is already sufficient")
+        void shouldNotUpgradeBundlePluginWhenSufficient() throws Exception {
+            Document doc = PomBuilder.create()
+                    .plugin("org.apache.felix", "maven-bundle-plugin", "5.1.9")
+                    .buildDocument();
+            strategy.doApply(createMockContext(), Map.of(Paths.get("pom.xml"), doc));
+
+            String version = new Editor(doc)
+                    .root()
+                    .path("build", "plugins", "plugin", "version")
+                    .map(Element::textContentTrimmed)
+                    .orElse(null);
+            assertEquals("5.1.9", version, "maven-bundle-plugin 5.1.9 should not be downgraded");
+        }
+
+        @Test
+        @DisplayName("should upgrade bnd-maven-plugin when below minimum")
+        void shouldUpgradeBndMavenPluginWhenBelowMinimum() throws Exception {
+            Document doc = PomBuilder.create()
+                    .plugin("biz.aQute.bnd", "bnd-maven-plugin", "4.1.0")
+                    .buildDocument();
+            UpgradeResult result = strategy.doApply(createMockContext(), Map.of(Paths.get("pom.xml"), doc));
+
+            assertTrue(result.success() && result.modifiedCount() > 0, "Should have upgraded bnd-maven-plugin");
+            String version = new Editor(doc)
+                    .root()
+                    .path("build", "plugins", "plugin", "version")
+                    .map(Element::textContentTrimmed)
+                    .orElse(null);
+            assertEquals("5.1.0", version, "bnd-maven-plugin should be upgraded to 5.1.0");
+        }
+
+        @Test
+        @DisplayName("should not upgrade bnd-maven-plugin when version is already sufficient")
+        void shouldNotUpgradeBndMavenPluginWhenSufficient() throws Exception {
+            Document doc = PomBuilder.create()
+                    .plugin("biz.aQute.bnd", "bnd-maven-plugin", "7.0.0")
+                    .buildDocument();
+            strategy.doApply(createMockContext(), Map.of(Paths.get("pom.xml"), doc));
+
+            String version = new Editor(doc)
+                    .root()
+                    .path("build", "plugins", "plugin", "version")
+                    .map(Element::textContentTrimmed)
+                    .orElse(null);
+            assertEquals("7.0.0", version, "bnd-maven-plugin 7.0.0 should not be downgraded");
+        }
+
         @Test
         @DisplayName("should not upgrade when version is already higher")
         void shouldNotUpgradeWhenVersionAlreadyHigher() throws Exception {
@@ -813,7 +879,9 @@ void shouldHavePredefinedPluginUpgrades() throws Exception {
                     "maven-failsafe-plugin",
                     "maven-surefire-report-plugin",
                     "maven-war-plugin",
-                    "maven-ear-plugin")) {
+                    "maven-ear-plugin",
+                    "maven-bundle-plugin",
+                    "bnd-maven-plugin")) {
                 assertTrue(
                         upgrades.stream().anyMatch(u -> expected.equals(u.artifactId())),
                         "Should include " + expected + " upgrade");