From c46e86d6c42d65dd010522de82f1d226926eb525 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Wed, 8 Apr 2026 22:15:25 +0200 Subject: [PATCH 1/4] Do not force md download always Right now, metadata discovery causes all metadata download over and over, for maven plugins that does not have G level metadata. Usually those plugins are enlisted in POM. One of most prominent plugin is spotless. So this PR adds following change: * discover via G level metadata (will not succeed) * discover via project (here will) * try harder via G level metadata (set policy "always") --- .../prefix/internal/DefaultPluginPrefixResolver.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java b/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java index d2566b6ffb3f..1278c82e40a1 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java @@ -102,7 +102,7 @@ public PluginPrefixResult resolve(PluginPrefixRequest request) throws NoPluginFo LinkedHashMap::new, Collectors.mapping(Plugin::getArtifactId, Collectors.toSet()))); request.getPluginGroups().forEach(g -> candidates.put(g, null)); - PluginPrefixResult result = resolveFromRepository(request, candidates); + PluginPrefixResult result = resolveFromRepository(request, candidates, false); // If we haven't been able to resolve the plugin from the repository, // as a last resort, we go through all declared plugins, load them @@ -114,6 +114,10 @@ public PluginPrefixResult resolve(PluginPrefixRequest request) throws NoPluginFo } } + if (result == null) { + result = resolveFromRepository(request, candidates, true); + } + if (result == null) { throw new NoPluginFoundForPrefixException( request.getPrefix(), @@ -152,7 +156,7 @@ private PluginPrefixResult resolveFromProject(PluginPrefixRequest request, List< } private PluginPrefixResult resolveFromRepository( - PluginPrefixRequest request, LinkedHashMap> candidates) { + PluginPrefixRequest request, LinkedHashMap> candidates, boolean force) { RequestTrace trace = RequestTrace.newChild(null, request); List requests = new ArrayList<>(); @@ -181,7 +185,7 @@ private PluginPrefixResult resolveFromRepository( // second try, refetch all (possibly outdated) metadata that wasn't updated in the first attempt - if (!request.getRepositorySession().isOffline() && !requests.isEmpty()) { + if (force && !request.getRepositorySession().isOffline() && !requests.isEmpty()) { DefaultRepositorySystemSession session = new DefaultRepositorySystemSession(request.getRepositorySession()); session.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); From 1fe19bf5e940d575f6304b114a9cac3a1b314690 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Mon, 13 Apr 2026 14:20:54 +0200 Subject: [PATCH 2/4] Undo change; go back to original code --- .../prefix/internal/DefaultPluginPrefixResolver.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java b/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java index ce37071d8cbb..4a21d24535ad 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java @@ -105,18 +105,18 @@ public PluginPrefixResult resolve(PluginPrefixRequest request) throws NoPluginFo LinkedHashMap::new, Collectors.mapping(Plugin::getArtifactId, Collectors.toSet()))); request.getPluginGroups().forEach(g -> candidates.put(g, null)); - PluginPrefixResult result = resolveFromRepository(request, candidates, false); - - // If we haven't been able to resolve the plugin from the repository, - // as a last resort, we go through all declared plugins, load them + PluginPrefixResult result = null; + // First, we go through all declared plugins, load them // one by one, and try to find a matching prefix. - if (result == null && build != null) { + if (build != null) { result = resolveFromProject(request, build.getPlugins()); if (result == null && management != null) { result = resolveFromProject(request, management.getPlugins()); } } + // Second, we go use G level metadata to discover prefix + // This order allows user managed clashing prefixes (they can declare them in POM) if (result == null) { result = resolveFromRepository(request, candidates, true); } From 2083f907200e56db4519d3ee7245d43a3012a8d1 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Mon, 13 Apr 2026 14:34:02 +0200 Subject: [PATCH 3/4] Try some simple heuristics --- .../internal/DefaultPluginPrefixResolver.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java b/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java index 4a21d24535ad..7d327b85a72d 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java @@ -118,7 +118,7 @@ public PluginPrefixResult resolve(PluginPrefixRequest request) throws NoPluginFo // Second, we go use G level metadata to discover prefix // This order allows user managed clashing prefixes (they can declare them in POM) if (result == null) { - result = resolveFromRepository(request, candidates, true); + result = resolveFromRepository(request, candidates); } if (result == null) { @@ -137,6 +137,27 @@ public PluginPrefixResult resolve(PluginPrefixRequest request) throws NoPluginFo } private PluginPrefixResult resolveFromProject(PluginPrefixRequest request, List plugins) { + if (plugins.isEmpty()) { + return null; + } + PluginPrefixResult result = null; + // try optimistically; first if A contains prefix? + List candidates = plugins.stream() + .filter(p -> p.getArtifactId().contains(request.getPrefix())) + .collect(Collectors.toList()); + if (!candidates.isEmpty()) { + result = doResolveFromProject(request, candidates); + } + // if no luck; try the rest + if (result == null) { + List remainder = new ArrayList<>(plugins); + remainder.removeAll(candidates); + result = doResolveFromProject(request, remainder); + } + return result; + } + + private PluginPrefixResult doResolveFromProject(PluginPrefixRequest request, List plugins) { for (Plugin plugin : plugins) { try { PluginDescriptor pluginDescriptor = @@ -159,7 +180,7 @@ private PluginPrefixResult resolveFromProject(PluginPrefixRequest request, List< } private PluginPrefixResult resolveFromRepository( - PluginPrefixRequest request, LinkedHashMap> candidates, boolean force) { + PluginPrefixRequest request, LinkedHashMap> candidates) { RequestTrace trace = RequestTrace.newChild(null, request); List requests = new ArrayList<>(); @@ -188,7 +209,7 @@ private PluginPrefixResult resolveFromRepository( // second try, refetch all (possibly outdated) metadata that wasn't updated in the first attempt - if (force && !request.getRepositorySession().isOffline() && !requests.isEmpty()) { + if (!request.getRepositorySession().isOffline() && !requests.isEmpty()) { DefaultRepositorySystemSession session = new DefaultRepositorySystemSession(request.getRepositorySession()); session.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); From 7a071e46eacd668a8bb5eb2e1b5ca2217f3129ae Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Mon, 13 Apr 2026 20:56:00 +0200 Subject: [PATCH 4/4] Improvement --- .../internal/DefaultPluginPrefixResolver.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java b/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java index 7d327b85a72d..4df3dcc5c4b7 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java @@ -24,8 +24,10 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -109,10 +111,10 @@ public PluginPrefixResult resolve(PluginPrefixRequest request) throws NoPluginFo // First, we go through all declared plugins, load them // one by one, and try to find a matching prefix. if (build != null) { - result = resolveFromProject(request, build.getPlugins()); - if (result == null && management != null) { - result = resolveFromProject(request, management.getPlugins()); - } + result = resolveFromProject( + request, + build.getPlugins(), + management != null ? management.getPlugins() : Collections.emptyList()); } // Second, we go use G level metadata to discover prefix @@ -136,28 +138,30 @@ public PluginPrefixResult resolve(PluginPrefixRequest request) throws NoPluginFo return result; } - private PluginPrefixResult resolveFromProject(PluginPrefixRequest request, List plugins) { - if (plugins.isEmpty()) { + private PluginPrefixResult resolveFromProject( + PluginPrefixRequest request, List plugins, List pluginMgmt) { + if (plugins.isEmpty() && pluginMgmt.isEmpty()) { return null; } PluginPrefixResult result = null; // try optimistically; first if A contains prefix? - List candidates = plugins.stream() + Set candidates = new LinkedHashSet<>(); + Stream.concat(plugins.stream(), pluginMgmt.stream()) .filter(p -> p.getArtifactId().contains(request.getPrefix())) - .collect(Collectors.toList()); + .forEach(candidates::add); if (!candidates.isEmpty()) { result = doResolveFromProject(request, candidates); } // if no luck; try the rest if (result == null) { - List remainder = new ArrayList<>(plugins); + Set remainder = new LinkedHashSet<>(plugins); remainder.removeAll(candidates); result = doResolveFromProject(request, remainder); } return result; } - private PluginPrefixResult doResolveFromProject(PluginPrefixRequest request, List plugins) { + private PluginPrefixResult doResolveFromProject(PluginPrefixRequest request, Collection plugins) { for (Plugin plugin : plugins) { try { PluginDescriptor pluginDescriptor =