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/26 14:16:02 UTC

[maven] branch MNG-5669 created (now d478e2a)

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

rfscholte pushed a change to branch MNG-5669
in repository https://gitbox.apache.org/repos/asf/maven.git.


      at d478e2a  [MNG-5669] same pom.xml is read multiple times

This branch includes the following new commits:

     new d478e2a  [MNG-5669] same pom.xml is read multiple times

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: [MNG-5669] same pom.xml is read multiple times

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

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

commit d478e2a91dc18f8881a7351ed9947cf5a00f5921
Author: rfscholte <rf...@apache.org>
AuthorDate: Sun Jan 26 15:15:50 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  | 198 ++++++++++++++++-----
 .../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, 447 insertions(+), 64 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..d9f38fe 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 )
+        {
+            putCache( request.getModelCache(), new FileModelSource( request.getPomFile() ), ModelCacheTag.RAW,
+                      resultData );
+        }
+        else
+        {
+            putCache( 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 )
+        {
+            putCache( 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 );
+        putCache( 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 = getCache( cache, artifactModelSource.getGroupId(),
+                                            artifactModelSource.getArtifactId(),
+                                            artifactModelSource.getVersion(), ModelCacheTag.RAW );
+            if ( modelData != null )
+            {
+                model = modelData.getModel();
+            }
+            else 
+            {
+                model = null;
+            }
+        }
+        else
+        {
+            model = getCache( 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 = getCache( 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 );
+                    
+                    putCache( request.getModelCache(), 
+                              parentData.getGroupId(), parentData.getArtifactId(),
+                              parentData.getVersion(), ModelCacheTag.RAW, parentData );
                 }
             }
 
@@ -1338,6 +1427,14 @@ public class DefaultModelBuilder
         }
     }
 
+    private <T> void putCache( ModelCache modelCache, Source source, ModelCacheTag<T> tag, T data )
+    {
+        if ( modelCache != null )
+        {
+            modelCache.put( source, tag.getName(), tag.intoCache( data ) );
+        }
+    }
+
     private <T> T getCache( ModelCache modelCache, String groupId, String artifactId, String version,
                             ModelCacheTag<T> tag )
     {
@@ -1352,6 +1449,19 @@ public class DefaultModelBuilder
         return null;
     }
 
+    private <T> T getCache( 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