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 2023/11/07 08:20:58 UTC

(maven) 01/04: [MNG-7615] Use lambas to access ModelCache

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

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

commit 54ca01c7790517cc6977412f84e3dff98ac029a1
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Fri Dec 2 09:56:40 2022 +0100

    [MNG-7615] Use lambas to access ModelCache
---
 maven-model-builder/pom.xml                        |   2 +
 .../maven/model/building/DefaultModelBuilder.java  | 153 +++++++++++----------
 .../apache/maven/model/building/ModelCache.java    |  17 +++
 .../repository/internal/DefaultModelCache.java     |  28 +++-
 4 files changed, 125 insertions(+), 75 deletions(-)

diff --git a/maven-model-builder/pom.xml b/maven-model-builder/pom.xml
index e7a6fe7aa9..f315f64b75 100644
--- a/maven-model-builder/pom.xml
+++ b/maven-model-builder/pom.xml
@@ -142,6 +142,8 @@ under the License.
               <exclude>org.apache.maven.model.building.ModelCache#put(org.apache.maven.building.Source,java.lang.String,java.lang.Object):METHOD_NEW_DEFAULT</exclude>
               <exclude>org.apache.maven.model.building.ModelCache#put(org.apache.maven.building.Source,org.apache.maven.model.building.ModelCacheTag,java.lang.Object):METHOD_NEW_DEFAULT</exclude>
               <exclude>org.apache.maven.model.building.ModelCache#put(java.lang.String,java.lang.String,java.lang.String,org.apache.maven.model.building.ModelCacheTag,java.lang.Object):METHOD_NEW_DEFAULT</exclude>
+              <exclude>org.apache.maven.model.building.ModelCache#computeIfAbsent(java.lang.String,java.lang.String,java.lang.String,org.apache.maven.model.building.ModelCacheTag,java.util.function.Supplier):METHOD_NEW_DEFAULT</exclude>
+              <exclude>org.apache.maven.model.building.ModelCache#computeIfAbsent(org.apache.maven.building.Source,org.apache.maven.model.building.ModelCacheTag,java.util.function.Supplier):METHOD_NEW_DEFAULT</exclude>
               <exclude>org.apache.maven.model.composition.DependencyManagementImporter#importManagement(org.apache.maven.model.Model,java.util.List,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_REMOVED</exclude>
               <exclude>org.apache.maven.model.composition.DefaultDependencyManagementImporter#importManagement(org.apache.maven.model.Model,java.util.List,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_REMOVED</exclude>
               <exclude>org.apache.maven.model.inheritance.DefaultInheritanceAssembler</exclude>
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
index c8ba3ca319..f3399b748d 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java
@@ -38,7 +38,11 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Properties;
 import java.util.Set;
+import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ForkJoinTask;
+import java.util.function.Function;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
 import org.apache.maven.api.feature.Features;
@@ -1007,12 +1011,11 @@ public class DefaultModelBuilder implements ModelBuilder {
     private Model readFileModel(ModelBuildingRequest request, DefaultModelProblemCollector problems)
             throws ModelBuildingException {
         ModelSource modelSource = request.getModelSource();
-        org.apache.maven.api.model.Model model = fromCache(request.getModelCache(), modelSource, ModelCacheTag.FILE);
-        if (model == null) {
-            model = doReadFileModel(modelSource, request, problems);
-
-            intoCache(request.getModelCache(), modelSource, ModelCacheTag.FILE, model);
-        }
+        org.apache.maven.api.model.Model model = cache(
+                request.getModelCache(),
+                modelSource,
+                ModelCacheTag.FILE,
+                () -> doReadFileModel(modelSource, request, problems));
 
         if (modelSource instanceof FileModelSource) {
             if (request.getTransformerContextBuilder() instanceof DefaultTransformerContextBuilder) {
@@ -1129,45 +1132,41 @@ public class DefaultModelBuilder implements ModelBuilder {
             throws ModelBuildingException {
         ModelSource modelSource = request.getModelSource();
 
-        ModelData cachedData = fromCache(request.getModelCache(), modelSource, ModelCacheTag.RAW);
-        if (cachedData != null) {
-            return cachedData.getModel();
-        }
+        ModelData cachedData = cache(request.getModelCache(), modelSource, ModelCacheTag.RAW, () -> {
+            Model rawModel;
+            if (Features.buildConsumer(request.getUserProperties()) && modelSource instanceof FileModelSource) {
+                rawModel = readFileModel(request, problems);
+                File pomFile = ((FileModelSource) modelSource).getFile();
 
-        Model rawModel;
-        if (Features.buildConsumer(request.getUserProperties()) && modelSource instanceof FileModelSource) {
-            rawModel = readFileModel(request, problems);
-            File pomFile = ((FileModelSource) modelSource).getFile();
-
-            try {
-                if (request.getTransformerContextBuilder() != null) {
-                    TransformerContext context =
-                            request.getTransformerContextBuilder().initialize(request, problems);
-                    transformer.transform(pomFile.toPath(), context, rawModel);
+                try {
+                    if (request.getTransformerContextBuilder() != null) {
+                        TransformerContext context =
+                                request.getTransformerContextBuilder().initialize(request, problems);
+                        transformer.transform(pomFile.toPath(), context, rawModel);
+                    }
+                } catch (TransformerException e) {
+                    problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.V40).setException(e));
                 }
-            } catch (TransformerException e) {
-                problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.V40).setException(e));
+            } else if (request.getFileModel() == null) {
+                rawModel = readFileModel(request, problems);
+            } else {
+                rawModel = request.getFileModel().clone();
             }
-        } else if (request.getFileModel() == null) {
-            rawModel = readFileModel(request, problems);
-        } else {
-            rawModel = request.getFileModel().clone();
-        }
 
-        modelValidator.validateRawModel(rawModel, request, problems);
+            modelValidator.validateRawModel(rawModel, request, problems);
 
-        if (hasFatalErrors(problems)) {
-            throw problems.newModelBuildingException();
-        }
-
-        String groupId = getGroupId(rawModel);
-        String artifactId = rawModel.getArtifactId();
-        String version = getVersion(rawModel);
+            if (hasFatalErrors(problems)) {
+                throw problems.newModelBuildingException();
+            }
 
-        ModelData modelData = new ModelData(modelSource, rawModel, groupId, artifactId, version);
-        intoCache(request.getModelCache(), modelSource, ModelCacheTag.RAW, modelData);
+            String groupId = getGroupId(rawModel);
+            String artifactId = rawModel.getArtifactId();
+            String version = getVersion(rawModel);
 
-        return rawModel;
+            ModelData modelData = new ModelData(modelSource, rawModel, groupId, artifactId, version);
+            return modelData;
+        });
+        return cachedData != null ? cachedData.getModel() : null;
     }
 
     private String getGroupId(Model model) {
@@ -1708,15 +1707,11 @@ public class DefaultModelBuilder implements ModelBuilder {
         }
 
         org.apache.maven.api.model.DependencyManagement importMgmt =
-                fromCache(request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT);
-        if (importMgmt == null) {
-            DependencyManagement importMgmtV3 = doLoadDependencyManagement(
-                    model, request, problems, dependency, groupId, artifactId, version, importIds);
-            if (importMgmtV3 != null) {
-                importMgmt = importMgmtV3.getDelegate();
-                intoCache(request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, importMgmt);
-            }
-        }
+                cache(request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, () -> {
+                    DependencyManagement importMgmtV3 = doLoadDependencyManagement(
+                            model, request, problems, dependency, groupId, artifactId, version, importIds);
+                    return importMgmtV3 != null ? importMgmtV3.getDelegate() : null;
+                });
 
         // [MNG-5600] Dependency management import should support exclusions.
         List<Exclusion> exclusions = dependency.getDelegate().getExclusions();
@@ -1823,32 +1818,50 @@ public class DefaultModelBuilder implements ModelBuilder {
         return importMgmt;
     }
 
-    private <T> void intoCache(
-            ModelCache modelCache, String groupId, String artifactId, String version, ModelCacheTag<T> tag, T data) {
-        if (modelCache != null) {
-            modelCache.put(groupId, artifactId, version, tag, data);
-        }
-    }
-
-    private <T> void intoCache(ModelCache modelCache, Source source, ModelCacheTag<T> tag, T data) {
-        if (modelCache != null) {
-            modelCache.put(source, tag, data);
-        }
-    }
-
-    private static <T> T fromCache(
-            ModelCache modelCache, String groupId, String artifactId, String version, ModelCacheTag<T> tag) {
-        if (modelCache != null) {
-            return modelCache.get(groupId, artifactId, version, tag);
+    private static <T> T cache(
+            ModelCache cache,
+            String groupId,
+            String artifactId,
+            String version,
+            ModelCacheTag<T> tag,
+            Callable<T> supplier) {
+        return doWithCache(cache, supplier, s -> cache.computeIfAbsent(groupId, artifactId, version, tag, s));
+    }
+
+    private static <T> T cache(ModelCache cache, Source source, ModelCacheTag<T> tag, Callable<T> supplier) {
+        return doWithCache(cache, supplier, s -> cache.computeIfAbsent(source, tag, s));
+    }
+
+    private static <T> T doWithCache(
+            ModelCache cache, Callable<T> supplier, Function<Supplier<Supplier<T>>, T> asyncSupplierConsumer) {
+        if (cache != null) {
+            return asyncSupplierConsumer.apply(() -> {
+                ForkJoinTask<T> task = ForkJoinTask.adapt(supplier);
+                task.fork();
+                return () -> {
+                    task.quietlyJoin();
+                    if (task.isCompletedAbnormally()) {
+                        Throwable e = task.getException();
+                        while (e instanceof RuntimeException && e.getCause() != null) {
+                            e = e.getCause();
+                        }
+                        uncheckedThrow(e);
+                    }
+                    return task.getRawResult();
+                };
+            });
+        } else {
+            try {
+                return supplier.call();
+            } catch (Exception e) {
+                uncheckedThrow(e);
+                return null;
+            }
         }
-        return null;
     }
 
-    private static <T> T fromCache(ModelCache modelCache, Source source, ModelCacheTag<T> tag) {
-        if (modelCache != null) {
-            return modelCache.get(source, tag);
-        }
-        return null;
+    static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
+        throw (T) t; // rely on vacuous cast
     }
 
     private void fireEvent(
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCache.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCache.java
index 63fd48372d..6f9cba374e 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCache.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCache.java
@@ -18,6 +18,8 @@
  */
 package org.apache.maven.model.building;
 
+import java.util.function.Supplier;
+
 import org.apache.maven.building.Source;
 
 /**
@@ -127,4 +129,19 @@ public interface ModelCache {
         Object obj = get(groupId, artifactId, version, tag.getName());
         return (obj != null) ? tag.fromCache(tag.getType().cast(obj)) : null;
     }
+
+    default <T> T computeIfAbsent(
+            String groupId, String artifactId, String version, ModelCacheTag<T> tag, Supplier<Supplier<T>> data) {
+        Object obj = computeIfAbsent(groupId, artifactId, version, tag.getName(), (Supplier) data);
+        return (obj != null) ? tag.fromCache(tag.getType().cast(obj)) : null;
+    }
+
+    default <T> T computeIfAbsent(Source path, ModelCacheTag<T> tag, Supplier<Supplier<T>> data) {
+        Object obj = computeIfAbsent(path, tag.getName(), (Supplier) data);
+        return (obj != null) ? tag.fromCache(tag.getType().cast(obj)) : null;
+    }
+
+    Object computeIfAbsent(String groupId, String artifactId, String version, String tag, Supplier<Supplier<?>> data);
+
+    Object computeIfAbsent(Source path, String tag, Supplier<Supplier<?>> data);
 }
diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelCache.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelCache.java
index c503487e76..7b2831e921 100644
--- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelCache.java
+++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelCache.java
@@ -21,6 +21,7 @@ package org.apache.maven.repository.internal;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Supplier;
 
 import org.apache.maven.building.Source;
 import org.apache.maven.model.building.ModelCache;
@@ -34,10 +35,10 @@ public class DefaultModelCache implements ModelCache {
 
     private static final String KEY = DefaultModelCache.class.getName();
 
-    private final Map<Object, Object> cache;
+    private final Map<Object, Supplier<?>> cache;
 
     public static ModelCache newInstance(RepositorySystemSession session) {
-        Map<Object, Object> cache;
+        Map<Object, Supplier<?>> cache;
         if (session.getCache() == null) {
             cache = new ConcurrentHashMap<>();
         } else {
@@ -50,7 +51,7 @@ public class DefaultModelCache implements ModelCache {
         return new DefaultModelCache(cache);
     }
 
-    private DefaultModelCache(Map<Object, Object> cache) {
+    private DefaultModelCache(Map<Object, Supplier<?>> cache) {
         this.cache = cache;
     }
 
@@ -73,11 +74,28 @@ public class DefaultModelCache implements ModelCache {
     }
 
     protected Object get(Object key) {
-        return cache.get(key);
+        Supplier<?> s = cache.get(key);
+        return s != null ? s.get() : null;
     }
 
     protected void put(Object key, Object data) {
-        cache.put(key, data);
+        cache.put(key, () -> data);
+    }
+
+    @Override
+    public Object computeIfAbsent(
+            String groupId, String artifactId, String version, String tag, Supplier<Supplier<?>> data) {
+        return computeIfAbsent(new GavCacheKey(groupId, artifactId, version, tag), data);
+    }
+
+    @Override
+    public Object computeIfAbsent(Source path, String tag, Supplier<Supplier<?>> data) {
+        return computeIfAbsent(new SourceCacheKey(path, tag), data);
+    }
+
+    protected Object computeIfAbsent(Object key, Supplier<Supplier<?>> data) {
+        Supplier<?> s = cache.computeIfAbsent(key, k -> data.get());
+        return s != null ? s.get() : null;
     }
 
     static class GavCacheKey {