You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by rf...@apache.org on 2020/01/29 20:18:51 UTC

[maven] branch master updated: [MNG-5669] same pom.xml is read multiple times

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 716cc1f  [MNG-5669] same pom.xml is read multiple times
716cc1f is described below

commit 716cc1fe02661897232a7cc3e4c1bb3b3df3b832
Author: rfscholte <rf...@apache.org>
AuthorDate: Wed Jan 29 21:18:42 2020 +0100

    [MNG-5669] same pom.xml is read multiple times
---
 .../java/org/apache/maven/building/FileSource.java |  31 ++++
 .../org/apache/maven/building/StringSource.java    |  33 +++-
 .../java/org/apache/maven/building/UrlSource.java  |  32 +++-
 .../apache/maven/project/ReactorModelCache.java    |  78 +++++++-
 .../maven/model/building/ArtifactModelSource.java  |  59 ++++++
 .../maven/model/building/DefaultModelBuilder.java  | 206 ++++++++++++++++-----
 .../maven/model/building/FileModelSource.java      |   9 +-
 .../apache/maven/model/building/ModelCache.java    |  29 +++
 .../apache/maven/model/building/ModelCacheTag.java |  26 +++
 .../model/superpom/DefaultSuperPomProvider.java    |   2 +-
 .../internal/DefaultArtifactDescriptorReader.java  |   7 +-
 .../repository/internal/DefaultModelResolver.java  |   7 +-
 12 files changed, 451 insertions(+), 68 deletions(-)

diff --git a/maven-builder-support/src/main/java/org/apache/maven/building/FileSource.java b/maven-builder-support/src/main/java/org/apache/maven/building/FileSource.java
index 66e6441..05db377 100644
--- a/maven-builder-support/src/main/java/org/apache/maven/building/FileSource.java
+++ b/maven-builder-support/src/main/java/org/apache/maven/building/FileSource.java
@@ -35,6 +35,8 @@ public class FileSource
 {
     private final File file;
 
+    private final int hashCode; 
+
     /**
      * Creates a new source backed by the specified file.
      *
@@ -43,6 +45,7 @@ public class FileSource
     public FileSource( File file )
     {
         this.file = Objects.requireNonNull( file, "file cannot be null" ).getAbsoluteFile();
+        this.hashCode = Objects.hash( file );
     }
 
     @Override
@@ -73,4 +76,32 @@ public class FileSource
     {
         return getLocation();
     }
+
+    @Override
+    public int hashCode()
+    {
+        return hashCode;
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+        {
+            return true;
+        }
+
+        if ( obj == null )
+        {
+            return false;
+        }
+
+        if ( !FileSource.class.equals( obj.getClass() ) )
+        {
+            return false;
+        }
+
+        FileSource other = (FileSource) obj;
+        return this.file.equals( other.file );
+    }
 }
diff --git a/maven-builder-support/src/main/java/org/apache/maven/building/StringSource.java b/maven-builder-support/src/main/java/org/apache/maven/building/StringSource.java
index 7705804..68de576 100644
--- a/maven-builder-support/src/main/java/org/apache/maven/building/StringSource.java
+++ b/maven-builder-support/src/main/java/org/apache/maven/building/StringSource.java
@@ -32,10 +32,11 @@ import java.nio.charset.StandardCharsets;
 public class StringSource
     implements Source
 {
+    private final String content;
 
-    private String content;
+    private final String location;
 
-    private String location;
+    private final int hashCode;
 
     /**
      * Creates a new source backed by the specified string.
@@ -57,6 +58,7 @@ public class StringSource
     {
         this.content = ( content != null ) ? content.toString() : "";
         this.location = ( location != null ) ? location : "(memory)";
+        this.hashCode = this.content.hashCode();
     }
 
     @Override
@@ -88,4 +90,31 @@ public class StringSource
         return getLocation();
     }
 
+    @Override
+    public int hashCode()
+    {
+        return hashCode;
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( this == obj ) 
+        {
+            return true;
+        }
+
+        if ( obj == null )
+        {
+            return false;
+        }
+
+        if ( !StringSource.class.equals( obj.getClass() ) )
+        {
+            return false;
+        }
+
+        StringSource other = (StringSource) obj;
+        return this.content.equals( other.content );
+    }
 }
diff --git a/maven-builder-support/src/main/java/org/apache/maven/building/UrlSource.java b/maven-builder-support/src/main/java/org/apache/maven/building/UrlSource.java
index 772091f..7226293 100644
--- a/maven-builder-support/src/main/java/org/apache/maven/building/UrlSource.java
+++ b/maven-builder-support/src/main/java/org/apache/maven/building/UrlSource.java
@@ -33,7 +33,9 @@ public class UrlSource
     implements Source
 {
 
-    private URL url;
+    private final URL url;
+
+    private final int hashCode;
 
     /**
      * Creates a new source backed by the specified URL.
@@ -43,6 +45,7 @@ public class UrlSource
     public UrlSource( URL url )
     {
         this.url = Objects.requireNonNull( url, "url cannot be null" );
+        this.hashCode = Objects.hashCode( url );
     }
 
     @Override
@@ -74,4 +77,31 @@ public class UrlSource
         return getLocation();
     }
 
+    @Override
+    public int hashCode()
+    {
+        return hashCode;
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+        {
+            return true;
+        }
+
+        if ( obj == null )
+        {
+            return false;
+        }
+
+        if ( !UrlSource.class.equals( obj.getClass() ) )
+        {
+            return false;
+        }
+
+        UrlSource other = (UrlSource) obj;
+        return this.url.equals( other.url );
+    }
 }
diff --git a/maven-core/src/main/java/org/apache/maven/project/ReactorModelCache.java b/maven-core/src/main/java/org/apache/maven/project/ReactorModelCache.java
index 343967d..72c25c7 100644
--- a/maven-core/src/main/java/org/apache/maven/project/ReactorModelCache.java
+++ b/maven-core/src/main/java/org/apache/maven/project/ReactorModelCache.java
@@ -19,9 +19,11 @@ package org.apache.maven.project;
  * under the License.
  */
 
+import org.apache.maven.building.Source;
 import org.apache.maven.model.building.ModelCache;
 
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -33,19 +35,33 @@ class ReactorModelCache
     implements ModelCache
 {
 
-    private final Map<CacheKey, Object> models = new ConcurrentHashMap<>( 256 );
+    private final Map<Object, Object> models = new ConcurrentHashMap<>( 256 );
 
+    @Override
     public Object get( String groupId, String artifactId, String version, String tag )
     {
-        return models.get( new CacheKey( groupId, artifactId, version, tag ) );
+        return models.get( new GavCacheKey( groupId, artifactId, version, tag ) );
     }
 
+    @Override
     public void put( String groupId, String artifactId, String version, String tag, Object data )
     {
-        models.put( new CacheKey( groupId, artifactId, version, tag ), data );
+        models.put( new GavCacheKey( groupId, artifactId, version, tag ), data );
     }
 
-    private static final class CacheKey
+    @Override
+    public Object get( Source source, String tag )
+    {
+        return models.get( new SourceCacheKey( source, tag ) );
+    }
+
+    @Override
+    public void put( Source source, String tag, Object data )
+    {
+        models.put( new SourceCacheKey( source, tag ), data );
+    }
+
+    private static final class GavCacheKey
     {
 
         private final String groupId;
@@ -58,7 +74,7 @@ class ReactorModelCache
 
         private final int hashCode;
 
-        CacheKey( String groupId, String artifactId, String version, String tag )
+        GavCacheKey( String groupId, String artifactId, String version, String tag )
         {
             this.groupId = ( groupId != null ) ? groupId : "";
             this.artifactId = ( artifactId != null ) ? artifactId : "";
@@ -81,12 +97,12 @@ class ReactorModelCache
                 return true;
             }
 
-            if ( !( obj instanceof CacheKey ) )
+            if ( !( obj instanceof GavCacheKey ) )
             {
                 return false;
             }
 
-            CacheKey that = (CacheKey) obj;
+            GavCacheKey that = (GavCacheKey) obj;
 
             return artifactId.equals( that.artifactId ) && groupId.equals( that.groupId )
                 && version.equals( that.version ) && tag.equals( that.tag );
@@ -99,5 +115,53 @@ class ReactorModelCache
         }
 
     }
+    
+    private static final class SourceCacheKey
+    {
+        private final Source source;
+        
+        private final String tag;
+        
+        private final int hashCode;
+
+        SourceCacheKey( Source source, String tag )
+        {
+            this.source = source;
+            this.tag = tag;
+            this.hashCode = Objects.hash( source, tag );
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return hashCode;
+        }
+
+        @Override
+        public boolean equals( Object obj )
+        {
+            if ( this == obj ) 
+            {
+                return true;
+            }
+            if ( !( obj instanceof SourceCacheKey ) )
+            {
+                return false;
+            }
+            
+            SourceCacheKey other = (SourceCacheKey) obj;
+            if ( !Objects.equals( this.source, other.source ) )
+            {
+                    return false;
+            }
+            
+            if ( !Objects.equals( this.tag, other.tag ) )
+            {
+                    return false;
+            }
+
+            return true;
+        }
+    }
 
 }
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ArtifactModelSource.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ArtifactModelSource.java
new file mode 100644
index 0000000..c3f01c2
--- /dev/null
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ArtifactModelSource.java
@@ -0,0 +1,59 @@
+package org.apache.maven.model.building;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+
+/**
+ * 
+ * @author Robert Scholte
+ * @since 3.7.0
+ */
+public class ArtifactModelSource extends FileModelSource
+{
+    private final String groupId;
+    
+    private final String artifactId;
+    
+    private final String version;
+
+    public ArtifactModelSource( File file, String groupId, String artifactId, String version )
+    {
+        super( file );
+        this.groupId = groupId;
+        this.artifactId = artifactId;
+        this.version = version;
+    }
+
+    public String getGroupId()
+    {
+        return groupId;
+    }
+
+    public String getArtifactId()
+    {
+        return artifactId;
+    }
+
+    public String getVersion()
+    {
+        return version;
+    }
+}
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 2d01e126..cc1ba71 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
@@ -19,10 +19,11 @@ package org.apache.maven.model.building;
  * under the License.
  */
 
-
+import org.apache.maven.artifact.versioning.ArtifactVersion;
 import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
 import org.apache.maven.artifact.versioning.VersionRange;
+import org.apache.maven.building.Source;
 import org.apache.maven.model.Activation;
 import org.apache.maven.model.Build;
 import org.apache.maven.model.Dependency;
@@ -414,6 +415,16 @@ public class DefaultModelBuilder
         resultData.setArtifactId( resultModel.getArtifactId() );
         resultData.setVersion( resultModel.getVersion() );
 
+        if ( request.getPomFile() != null )
+        {
+            intoCache( request.getModelCache(), new FileModelSource( request.getPomFile() ), ModelCacheTag.RAW,
+                      resultData );
+        }
+        else
+        {
+            intoCache( request.getModelCache(), request.getModelSource(), ModelCacheTag.RAW, resultData );
+        }
+
         result.setEffectiveModel( resultModel );
 
         for ( ModelData currentData : lineage )
@@ -522,31 +533,37 @@ public class DefaultModelBuilder
                              DefaultModelProblemCollector problems )
         throws ModelBuildingException
     {
-        Model model;
-
         if ( modelSource == null )
         {
-            if ( pomFile != null )
-            {
-                modelSource = new FileModelSource( pomFile );
-            }
-            else
-            {
-                throw new NullPointerException( "neither pomFile nor modelSource can be null" );
-            }
+            modelSource =
+                new FileModelSource( Objects.requireNonNull( pomFile, "neither pomFile nor modelSource can be null" ) );
+        }
+
+        Model model = getModelFromCache( modelSource, request.getModelCache() );
+        if ( model != null )
+        {
+            return model;
         }
 
         problems.setSource( modelSource.getLocation() );
         try
         {
             boolean strict = request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
-            InputSource source = request.isLocationTracking() ? new InputSource() : null;
 
-            Map<String, Object> options = new HashMap<>();
+            Map<String, Object> options = new HashMap<>( 3 );
             options.put( ModelProcessor.IS_STRICT, strict );
-            options.put( ModelProcessor.INPUT_SOURCE, source );
             options.put( ModelProcessor.SOURCE, modelSource );
 
+            InputSource source;
+            if ( request.isLocationTracking() ) 
+            {
+                source = (InputSource) options.computeIfAbsent( ModelProcessor.INPUT_SOURCE, k -> new InputSource() );
+            }
+            else
+            {
+                source = null;
+            }
+
             try
             {
                 model = modelProcessor.read( modelSource.getInputStream(), options );
@@ -627,9 +644,71 @@ public class DefaultModelBuilder
             throw problems.newModelBuildingException();
         }
 
+        if ( pomFile != null )
+        {
+            intoCache( request.getModelCache(), modelSource, ModelCacheTag.FILEMODEL, model );
+        }
+
+        String groupId = getGroupId( model );
+        String artifactId = model.getArtifactId();
+        String version = getVersion( model );
+
+        ModelData modelData = new ModelData( modelSource, model, groupId, artifactId, version );
+        intoCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW, modelData );
+
         return model;
     }
 
+    private Model getModelFromCache( ModelSource modelSource, ModelCache cache )
+    {
+        Model model;
+        if ( modelSource instanceof ArtifactModelSource )
+        {
+            ArtifactModelSource artifactModelSource = ( ArtifactModelSource ) modelSource;
+            ModelData modelData = fromCache( cache, artifactModelSource.getGroupId(),
+                                            artifactModelSource.getArtifactId(),
+                                            artifactModelSource.getVersion(), ModelCacheTag.RAW );
+            if ( modelData != null )
+            {
+                model = modelData.getModel();
+            }
+            else 
+            {
+                model = null;
+            }
+        }
+        else
+        {
+            model = fromCache( cache, modelSource, ModelCacheTag.FILEMODEL );
+            
+            if ( model != null )
+            {
+                model = model.clone();
+            }
+        }
+        return model;
+    }
+
+    private String getGroupId( Model model )
+    {
+        String groupId = model.getGroupId();
+        if ( groupId == null && model.getParent() != null )
+        {
+            groupId = model.getParent().getGroupId();
+        }
+        return groupId;
+    }
+
+    private String getVersion( Model model ) 
+    {
+        String version = model.getVersion();
+        if ( version == null && model.getParent() != null )
+        {
+            version = model.getParent().getVersion();
+        } 
+        return version;
+    }
+
     private DefaultProfileActivationContext getProfileActivationContext( ModelBuildingRequest request )
     {
         DefaultProfileActivationContext context = new DefaultProfileActivationContext();
@@ -822,49 +901,59 @@ public class DefaultModelBuilder
                                   DefaultModelProblemCollector problems )
         throws ModelBuildingException
     {
-        ModelData parentData;
+        ModelData parentData = null;
 
         Parent parent = childModel.getParent();
 
         if ( parent != null )
         {
-            String groupId = parent.getGroupId();
-            String artifactId = parent.getArtifactId();
-            String version = parent.getVersion();
-
-            parentData = getCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW );
+            ModelSource expectedParentSource = getParentPomFile( childModel, childSource );
 
-            if ( parentData == null )
+            if ( expectedParentSource != null )
             {
-                parentData = readParentLocally( childModel, childSource, request, problems );
+                ModelData candidateData = readParentLocally( childModel, childSource, request, problems );
 
-                if ( parentData == null )
+                if ( candidateData != null )
                 {
-                    parentData = readParentExternally( childModel, request, problems );
-                }
+                    /*
+                     * NOTE: This is a sanity check of the cache hit. If the cached parent POM was locally resolved, 
+                     * the child's GAV should match with that parent, too. If it doesn't, we ignore the cache and
+                     * resolve externally, to mimic the behavior if the cache didn't exist in the first place. 
+                     * Otherwise, the cache would obscure a bad POM.
+                     */
+                    try
+                    {
+                        VersionRange parentVersion = VersionRange.createFromVersionSpec( parent.getVersion() );
+                        ArtifactVersion actualVersion = new DefaultArtifactVersion( candidateData.getVersion() );
 
-                putCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW, parentData );
+                        if ( parent.getGroupId().equals( candidateData.getGroupId() )
+                            && parent.getArtifactId().equals( candidateData.getArtifactId() )
+                            && parentVersion.containsVersion( actualVersion ) )
+                        {
+                            parentData = candidateData;
+                        }
+                    }
+                    catch ( InvalidVersionSpecificationException e )
+                    {
+                        // This should already been blocked during validation
+                    }
+                }
             }
-            else
+
+            if ( parentData == null )
             {
-                /*
-                 * NOTE: This is a sanity check of the cache hit. If the cached parent POM was locally resolved, the
-                 * child's <relativePath> should point at that parent, too. If it doesn't, we ignore the cache and
-                 * resolve externally, to mimic the behavior if the cache didn't exist in the first place. Otherwise,
-                 * the cache would obscure a bad POM.
-                 */
-
-                File pomFile = parentData.getModel().getPomFile();
-                if ( pomFile != null )
+                parentData = fromCache( request.getModelCache(), 
+                                       parent.getGroupId(), parent.getArtifactId(),
+                                       parent.getVersion(), ModelCacheTag.RAW );
+                
+                // ArtifactModelSource means repositorySource
+                if ( parentData == null || !( parentData.getSource() instanceof ArtifactModelSource ) )
                 {
-                    FileModelSource pomSource = new FileModelSource( pomFile );
-                    ModelSource expectedParentSource = getParentPomFile( childModel, childSource );
-
-                    if ( expectedParentSource == null || ( expectedParentSource instanceof ModelSource2
-                        && !pomSource.equals(  expectedParentSource ) ) )
-                    {
-                        parentData = readParentExternally( childModel, request, problems );
-                    }
+                    parentData = readParentExternally( childModel, request, problems );
+                    
+                    intoCache( request.getModelCache(), 
+                              parentData.getGroupId(), parentData.getArtifactId(),
+                              parentData.getVersion(), ModelCacheTag.RAW, parentData );
                 }
             }
 
@@ -1224,7 +1313,7 @@ public class DefaultModelBuilder
                 continue;
             }
 
-            DependencyManagement importMgmt = getCache( request.getModelCache(), groupId, artifactId, version,
+            DependencyManagement importMgmt = fromCache( request.getModelCache(), groupId, artifactId, version,
                                                         ModelCacheTag.IMPORT );
 
             if ( importMgmt == null )
@@ -1313,7 +1402,7 @@ public class DefaultModelBuilder
                     importMgmt = new DependencyManagement();
                 }
 
-                putCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, importMgmt );
+                intoCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, importMgmt );
             }
 
             if ( importMgmts == null )
@@ -1329,7 +1418,7 @@ public class DefaultModelBuilder
         dependencyManagementImporter.importManagement( model, importMgmts, request, problems );
     }
 
-    private <T> void putCache( ModelCache modelCache, String groupId, String artifactId, String version,
+    private <T> void intoCache( ModelCache modelCache, String groupId, String artifactId, String version,
                                ModelCacheTag<T> tag, T data )
     {
         if ( modelCache != null )
@@ -1338,7 +1427,15 @@ public class DefaultModelBuilder
         }
     }
 
-    private <T> T getCache( ModelCache modelCache, String groupId, String artifactId, String version,
+    private <T> void intoCache( ModelCache modelCache, Source source, ModelCacheTag<T> tag, T data )
+    {
+        if ( modelCache != null )
+        {
+            modelCache.put( source, tag.getName(), tag.intoCache( data ) );
+        }
+    }
+
+    private <T> T fromCache( ModelCache modelCache, String groupId, String artifactId, String version,
                             ModelCacheTag<T> tag )
     {
         if ( modelCache != null )
@@ -1352,6 +1449,19 @@ public class DefaultModelBuilder
         return null;
     }
 
+    private <T> T fromCache( ModelCache modelCache, Source source, ModelCacheTag<T> tag )
+    {
+        if ( modelCache != null )
+        {
+            Object data = modelCache.get( source, tag.getName() );
+            if ( data != null )
+            {
+                return tag.fromCache( tag.getType().cast( data ) );
+            }
+        }
+        return null;
+    }
+
     private void fireEvent( Model model, ModelBuildingRequest request, ModelProblemCollector problems,
                             ModelBuildingEventCatapult catapult )
         throws ModelBuildingException
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/FileModelSource.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/FileModelSource.java
index f329eb2..c5a8e0d 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/FileModelSource.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/FileModelSource.java
@@ -88,8 +88,13 @@ public class FileModelSource extends FileSource implements ModelSource2
         {
             return true;
         }
-        
-        if ( !( obj instanceof FileModelSource ) ) 
+
+        if ( obj == null )
+        {
+            return false;
+        }
+
+        if ( !FileModelSource.class.equals( obj.getClass() )  ) 
         {
             return false;
         }
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 132a511..80d169a 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
@@ -19,6 +19,8 @@ package org.apache.maven.model.building;
  * under the License.
  */
 
+import org.apache.maven.building.Source;
+
 /**
  * Caches auxiliary data used during model building like already processed raw/effective models. The data in the cache
  * is meant for exclusive consumption by the model builder and is opaque to the cache implementation. The cache key is
@@ -27,9 +29,36 @@ package org.apache.maven.model.building;
  * model builder.
  *
  * @author Benjamin Bentmann
+ * @author Robert Scholte
  */
 public interface ModelCache
 {
+    /**
+     * Puts the specified data into the cache.
+     * 
+     * @param path The path of the cache record, must not be {@code null}.
+     * @param tag The tag of the cache record, must not be {@code null}.
+     * @param data The data to store in the cache, must not be {@code null}.
+     * @since 3.7.0
+     */
+    default void put( Source path, String tag, Object data ) 
+    {
+        // only useful for ReactorModelCache
+    }
+
+    /**
+     * Gets the specified data from the cache.
+     * 
+     * @param path The path of the cache record, must not be {@code null}.
+     * @param tag The tag of the cache record, must not be {@code null}.
+     * @return The requested data or {@code null} if none was present in the cache.
+     * @since 3.7.0
+     */
+    default Object get( Source path, String tag ) 
+    {
+        // only useful for ReactorModelCache
+        return null;
+    }
 
     /**
      * Puts the specified data into the cache.
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCacheTag.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCacheTag.java
index 8452f96..f38bb62 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCacheTag.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCacheTag.java
@@ -129,4 +129,30 @@ interface ModelCacheTag<T>
 
     };
 
+    ModelCacheTag<Model> FILEMODEL = new ModelCacheTag<Model>() 
+    {
+        @Override
+        public String getName()
+        {
+            return "file-model";
+        }
+
+        @Override
+        public Class<Model> getType()
+        {
+            return Model.class;
+        }
+
+        @Override
+        public Model intoCache( Model data )
+        {
+            return ( data != null ) ? data.clone() : null;
+        }
+
+        @Override
+        public Model fromCache( Model data )
+        {
+            return intoCache( data );
+        }
+    };
 }
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/superpom/DefaultSuperPomProvider.java b/maven-model-builder/src/main/java/org/apache/maven/model/superpom/DefaultSuperPomProvider.java
index 930e63d..9d71623 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/superpom/DefaultSuperPomProvider.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/superpom/DefaultSuperPomProvider.java
@@ -74,7 +74,7 @@ public class DefaultSuperPomProvider
 
             try
             {
-                Map<String, Object> options = new HashMap<>();
+                Map<String, Object> options = new HashMap<>( 2 );
                 options.put( "xml:4.0.0", "xml:4.0.0" );
 
                 String modelId = "org.apache.maven:maven-model-builder:"
diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java
index 586c83e..d318395 100644
--- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java
+++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java
@@ -32,9 +32,9 @@ import javax.inject.Singleton;
 import org.apache.maven.model.DistributionManagement;
 import org.apache.maven.model.Model;
 import org.apache.maven.model.Relocation;
+import org.apache.maven.model.building.ArtifactModelSource;
 import org.apache.maven.model.building.DefaultModelBuilderFactory;
 import org.apache.maven.model.building.DefaultModelBuildingRequest;
-import org.apache.maven.model.building.FileModelSource;
 import org.apache.maven.model.building.ModelBuilder;
 import org.apache.maven.model.building.ModelBuildingException;
 import org.apache.maven.model.building.ModelBuildingRequest;
@@ -286,7 +286,10 @@ public class DefaultArtifactDescriptorReader
                 }
                 else
                 {
-                    modelRequest.setModelSource( new FileModelSource( pomArtifact.getFile() ) );
+                    modelRequest.setModelSource( new ArtifactModelSource( pomArtifact.getFile(),
+                                                                          pomArtifact.getGroupId(),
+                                                                          pomArtifact.getArtifactId(),
+                                                                          pomArtifact.getVersion() ) );
                 }
 
                 model = modelBuilder.build( modelRequest ).getEffectiveModel();
diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java
index 338f4ff..f23bfe4 100644
--- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java
+++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java
@@ -19,7 +19,6 @@ package org.apache.maven.repository.internal;
  * under the License.
  */
 
-import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
@@ -30,7 +29,7 @@ import java.util.Set;
 import org.apache.maven.model.Dependency;
 import org.apache.maven.model.Parent;
 import org.apache.maven.model.Repository;
-import org.apache.maven.model.building.FileModelSource;
+import org.apache.maven.model.building.ArtifactModelSource;
 import org.apache.maven.model.building.ModelSource;
 import org.apache.maven.model.resolution.InvalidRepositoryException;
 import org.apache.maven.model.resolution.ModelResolver;
@@ -176,9 +175,7 @@ class DefaultModelResolver
             throw new UnresolvableModelException( e.getMessage(), groupId, artifactId, version, e );
         }
 
-        File pomFile = pomArtifact.getFile();
-
-        return new FileModelSource( pomFile );
+        return new ArtifactModelSource( pomArtifact.getFile(), groupId, artifactId, version );
     }
 
     @Override