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

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


The following commit(s) were added to refs/heads/maven-3.9.x by this push:
     new 9037805f7 [MNG-7583] Allow concurrent access to the MavenPluginManager 
(#1001)
9037805f7 is described below

commit 9037805f775e1034b90e614eaf2348a7c437410c
Author: Guillaume Nodet <[email protected]>
AuthorDate: Wed Mar 1 11:31:29 2023 +0100

    [MNG-7583] Allow concurrent access to the MavenPluginManager (#1001)
    
    * [MNG-7583] Allow concurrent access to the MavenPluginManager (#855)
    * Add a default method to avoid breaking the api
---
 .../maven/plugin/DefaultPluginDescriptorCache.java | 31 +++++++++++++++--
 .../maven/plugin/DefaultPluginRealmCache.java      | 22 ++++++++++++
 .../apache/maven/plugin/PluginDescriptorCache.java | 16 +++++++++
 .../org/apache/maven/plugin/PluginRealmCache.java  | 15 +++++++++
 .../plugin/internal/DefaultMavenPluginManager.java | 39 +++++++++++-----------
 5 files changed, 101 insertions(+), 22 deletions(-)

diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginDescriptorCache.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginDescriptorCache.java
index d0a2e8374..8278cba9e 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginDescriptorCache.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginDescriptorCache.java
@@ -19,10 +19,10 @@
 package org.apache.maven.plugin;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.maven.RepositoryUtils;
 import org.apache.maven.artifact.ArtifactUtils;
@@ -49,7 +49,7 @@ import org.eclipse.aether.repository.WorkspaceRepository;
 @Component(role = PluginDescriptorCache.class)
 public class DefaultPluginDescriptorCache implements PluginDescriptorCache {
 
-    private Map<Key, PluginDescriptor> descriptors = new HashMap<>(128);
+    private Map<Key, PluginDescriptor> descriptors = new 
ConcurrentHashMap<>(128);
 
     public void flush() {
         descriptors.clear();
@@ -63,6 +63,33 @@ public class DefaultPluginDescriptorCache implements 
PluginDescriptorCache {
         return clone(descriptors.get(cacheKey));
     }
 
+    @Override
+    public PluginDescriptor get(Key key, PluginDescriptorSupplier supplier)
+            throws PluginDescriptorParsingException, 
PluginResolutionException, InvalidPluginDescriptorException {
+        try {
+            return clone(descriptors.computeIfAbsent(key, k -> {
+                try {
+                    return clone(supplier.load());
+                } catch (PluginDescriptorParsingException
+                        | PluginResolutionException
+                        | InvalidPluginDescriptorException e) {
+                    throw new RuntimeException(e);
+                }
+            }));
+        } catch (RuntimeException e) {
+            if (e.getCause() instanceof PluginDescriptorParsingException) {
+                throw (PluginDescriptorParsingException) e.getCause();
+            }
+            if (e.getCause() instanceof PluginResolutionException) {
+                throw (PluginResolutionException) e.getCause();
+            }
+            if (e.getCause() instanceof InvalidPluginDescriptorException) {
+                throw (InvalidPluginDescriptorException) e.getCause();
+            }
+            throw e;
+        }
+    }
+
     public void put(Key cacheKey, PluginDescriptor pluginDescriptor) {
         descriptors.put(cacheKey, clone(pluginDescriptor));
     }
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginRealmCache.java 
b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginRealmCache.java
index 0647235c4..10321374b 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginRealmCache.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginRealmCache.java
@@ -147,6 +147,28 @@ public class DefaultPluginRealmCache implements 
PluginRealmCache, Disposable {
         return cache.get(key);
     }
 
+    @Override
+    public CacheRecord get(Key key, PluginRealmSupplier supplier)
+            throws PluginResolutionException, PluginContainerException {
+        try {
+            return cache.computeIfAbsent(key, k -> {
+                try {
+                    return supplier.load();
+                } catch (PluginResolutionException | PluginContainerException 
e) {
+                    throw new RuntimeException(e);
+                }
+            });
+        } catch (RuntimeException e) {
+            if (e.getCause() instanceof PluginResolutionException) {
+                throw (PluginResolutionException) e.getCause();
+            }
+            if (e.getCause() instanceof PluginContainerException) {
+                throw (PluginContainerException) e.getCause();
+            }
+            throw e;
+        }
+    }
+
     public CacheRecord put(Key key, ClassRealm pluginRealm, List<Artifact> 
pluginArtifacts) {
         Objects.requireNonNull(pluginRealm, "pluginRealm cannot be null");
         Objects.requireNonNull(pluginArtifacts, "pluginArtifacts cannot be 
null");
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/PluginDescriptorCache.java 
b/maven-core/src/main/java/org/apache/maven/plugin/PluginDescriptorCache.java
index ef33da894..763d4af16 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/PluginDescriptorCache.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/PluginDescriptorCache.java
@@ -44,11 +44,27 @@ public interface PluginDescriptorCache {
         // marker interface for cache keys
     }
 
+    @FunctionalInterface
+    interface PluginDescriptorSupplier {
+        PluginDescriptor load()
+                throws PluginResolutionException, 
PluginDescriptorParsingException, InvalidPluginDescriptorException;
+    }
+
     Key createKey(Plugin plugin, List<RemoteRepository> repositories, 
RepositorySystemSession session);
 
     void put(Key key, PluginDescriptor pluginDescriptor);
 
     PluginDescriptor get(Key key);
 
+    default PluginDescriptor get(Key key, PluginDescriptorSupplier supplier)
+            throws PluginResolutionException, 
PluginDescriptorParsingException, InvalidPluginDescriptorException {
+        PluginDescriptor pd = get(key);
+        if (pd == null) {
+            pd = supplier.load();
+            put(key, pd);
+        }
+        return pd;
+    }
+
     void flush();
 }
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/PluginRealmCache.java 
b/maven-core/src/main/java/org/apache/maven/plugin/PluginRealmCache.java
index b8f786a08..bf655efc3 100644
--- a/maven-core/src/main/java/org/apache/maven/plugin/PluginRealmCache.java
+++ b/maven-core/src/main/java/org/apache/maven/plugin/PluginRealmCache.java
@@ -67,6 +67,11 @@ public interface PluginRealmCache {
         // marker interface for cache keys
     }
 
+    @FunctionalInterface
+    interface PluginRealmSupplier {
+        CacheRecord load() throws PluginResolutionException, 
PluginContainerException;
+    }
+
     Key createKey(
             Plugin plugin,
             ClassLoader parentRealm,
@@ -77,6 +82,16 @@ public interface PluginRealmCache {
 
     CacheRecord get(Key key);
 
+    default CacheRecord get(Key key, PluginRealmSupplier supplier)
+            throws PluginResolutionException, PluginContainerException {
+        CacheRecord cr = get(key);
+        if (cr == null) {
+            CacheRecord tcr = supplier.load();
+            cr = put(key, tcr.getRealm(), tcr.getArtifacts());
+        }
+        return cr;
+    }
+
     CacheRecord put(Key key, ClassRealm pluginRealm, List<Artifact> 
pluginArtifacts);
 
     void flush();
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
index 0161e8c48..e652e4c77 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
@@ -168,25 +168,26 @@ public class DefaultMavenPluginManager implements 
MavenPluginManager {
 
     private PluginDescriptorBuilder builder = new PluginDescriptorBuilder();
 
-    public synchronized PluginDescriptor getPluginDescriptor(
+    public PluginDescriptor getPluginDescriptor(
             Plugin plugin, List<RemoteRepository> repositories, 
RepositorySystemSession session)
             throws PluginResolutionException, 
PluginDescriptorParsingException, InvalidPluginDescriptorException {
         PluginDescriptorCache.Key cacheKey = 
pluginDescriptorCache.createKey(plugin, repositories, session);
 
-        PluginDescriptor pluginDescriptor = 
pluginDescriptorCache.get(cacheKey);
-
-        if (pluginDescriptor == null) {
+        PluginDescriptor pluginDescriptor = 
pluginDescriptorCache.get(cacheKey, () -> {
             org.eclipse.aether.artifact.Artifact artifact =
                     pluginDependenciesResolver.resolve(plugin, repositories, 
session);
 
             Artifact pluginArtifact = RepositoryUtils.toArtifact(artifact);
 
-            pluginDescriptor = extractPluginDescriptor(pluginArtifact, plugin);
+            PluginDescriptor descriptor = 
extractPluginDescriptor(pluginArtifact, plugin);
 
-            
pluginDescriptor.setRequiredMavenVersion(artifact.getProperty("requiredMavenVersion",
 null));
+            if (StringUtils.isBlank(descriptor.getRequiredMavenVersion())) {
+                // only take value from underlying POM if plugin descriptor 
has no explicit Maven requirement
+                
descriptor.setRequiredMavenVersion(artifact.getProperty("requiredMavenVersion", 
null));
+            }
 
-            pluginDescriptorCache.put(cacheKey, pluginDescriptor);
-        }
+            return descriptor;
+        });
 
         pluginDescriptor.setPlugin(plugin);
 
@@ -289,7 +290,7 @@ public class DefaultMavenPluginManager implements 
MavenPluginManager {
         }
     }
 
-    public synchronized void setupPluginRealm(
+    public void setupPluginRealm(
             PluginDescriptor pluginDescriptor,
             MavenSession session,
             ClassLoader parent,
@@ -330,19 +331,17 @@ public class DefaultMavenPluginManager implements 
MavenPluginManager {
                     project.getRemotePluginRepositories(),
                     session.getRepositorySession());
 
-            PluginRealmCache.CacheRecord cacheRecord = 
pluginRealmCache.get(cacheKey);
-
-            if (cacheRecord != null) {
-                pluginDescriptor.setClassRealm(cacheRecord.getRealm());
-                pluginDescriptor.setArtifacts(new 
ArrayList<>(cacheRecord.getArtifacts()));
-                for (ComponentDescriptor<?> componentDescriptor : 
pluginDescriptor.getComponents()) {
-                    componentDescriptor.setRealm(cacheRecord.getRealm());
-                }
-            } else {
+            PluginRealmCache.CacheRecord cacheRecord = 
pluginRealmCache.get(cacheKey, () -> {
                 createPluginRealm(pluginDescriptor, session, parent, 
foreignImports, filter);
 
-                cacheRecord = pluginRealmCache.put(
-                        cacheKey, pluginDescriptor.getClassRealm(), 
pluginDescriptor.getArtifacts());
+                return new PluginRealmCache.CacheRecord(
+                        pluginDescriptor.getClassRealm(), 
pluginDescriptor.getArtifacts());
+            });
+
+            pluginDescriptor.setClassRealm(cacheRecord.getRealm());
+            pluginDescriptor.setArtifacts(new 
ArrayList<>(cacheRecord.getArtifacts()));
+            for (ComponentDescriptor<?> componentDescriptor : 
pluginDescriptor.getComponents()) {
+                componentDescriptor.setRealm(cacheRecord.getRealm());
             }
 
             pluginRealmCache.register(project, cacheKey, cacheRecord);

Reply via email to