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/10/15 20:10:10 UTC

[maven] 03/07: Introduce DefaultTransformerContext, initialized during build, immutable during consume.

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

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

commit fb13e32c9bffd33bf83ba3b7d9f57516f41e13bb
Author: rfscholte <rf...@apache.org>
AuthorDate: Tue Oct 13 21:11:23 2020 +0200

    Introduce DefaultTransformerContext, initialized during build, immutable during consume.
---
 .../aether/ConsumerModelSourceTransformer.java     |   3 +-
 .../maven/project/DefaultProjectBuilder.java       |  34 ++--
 .../DefaultConsumerPomXMLFilterFactory.java        |  29 +--
 .../building/BuildModelSourceTransformer.java      |   2 +-
 .../building/DefaultBuildPomXMLFilterFactory.java  |  26 ++-
 .../maven/model/building/DefaultModelBuilder.java  | 203 ++++++++++++---------
 .../building/DefaultModelBuildingRequest.java      |  18 +-
 .../model/building/DefaultTransformerContext.java  |  90 +++++++++
 .../model/building/FilterModelBuildingRequest.java |  11 +-
 .../apache/maven/model/building/ModelBuilder.java  |   3 +-
 .../maven/model/building/ModelBuildingRequest.java |   5 +-
 .../xml/sax/filter/BuildPomXMLFilterFactory.java   |  37 ++++
 .../maven/xml/sax/filter/CiFriendlyXMLFilter.java  |   9 +-
 .../sax/filter/ConsumerPomXMLFilterFactory.java    |  31 ----
 .../xml/sax/filter/CiFriendlyXMLFilterTest.java    |   2 +-
 .../xml/sax/filter/ConsumerPomXMLFilterTest.java   |  13 +-
 16 files changed, 326 insertions(+), 190 deletions(-)

diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformer.java b/maven-core/src/main/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformer.java
index 728c78e..4da661a 100644
--- a/maven-core/src/main/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformer.java
+++ b/maven-core/src/main/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformer.java
@@ -48,7 +48,8 @@ class ConsumerModelSourceTransformer extends AbstractModelSourceTransformer
     protected AbstractSAXFilter getSAXFilter( Path pomFile, TransformerContext context )
         throws TransformerConfigurationException, SAXException, ParserConfigurationException
     {
-        return new DefaultConsumerPomXMLFilterFactory( new DefaultBuildPomXMLFilterFactory( context ) ).get( pomFile );
+        return new DefaultConsumerPomXMLFilterFactory( new DefaultBuildPomXMLFilterFactory( context,
+                                                                                            true ) ).get( pomFile );
     }
     
     /**
diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
index 407f4d0..0613367 100644
--- a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
+++ b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
@@ -56,6 +56,7 @@ import org.apache.maven.model.Plugin;
 import org.apache.maven.model.Profile;
 import org.apache.maven.model.ReportPlugin;
 import org.apache.maven.model.building.ArtifactModelSource;
+import org.apache.maven.model.building.DefaultModelBuilder.TransformerContextBuilder;
 import org.apache.maven.model.building.DefaultModelBuildingRequest;
 import org.apache.maven.model.building.DefaultModelProblem;
 import org.apache.maven.model.building.FileModelSource;
@@ -129,7 +130,7 @@ public class DefaultProjectBuilder
         throws ProjectBuildingException
     {
         return build( pomFile, new FileModelSource( pomFile ),
-                new InternalConfig( request, null, useGlobalModelCache() ? getModelCache() : null ) );
+                new InternalConfig( request, null, useGlobalModelCache() ? getModelCache() : null, null ) );
     }
 
     private boolean useGlobalModelCache()
@@ -142,7 +143,7 @@ public class DefaultProjectBuilder
         throws ProjectBuildingException
     {
         return build( null, modelSource,
-                 new InternalConfig( request, null, useGlobalModelCache() ? getModelCache() : null ) );
+                 new InternalConfig( request, null, useGlobalModelCache() ? getModelCache() : null, null ) );
     }
 
     private ProjectBuildingResult build( File pomFile, ModelSource modelSource, InternalConfig config )
@@ -288,7 +289,7 @@ public class DefaultProjectBuilder
         request.setBuildStartTime( configuration.getBuildStartTime() );
         request.setModelResolver( resolver );
         request.setModelCache( config.modelCache );
-        request.setTransformerContext( (TransformerContext) config.session.getData().get( TransformerContext.KEY ) );
+        request.setTransformerContextBuilder( config.transformerContextBuilder );
 
         return request;
     }
@@ -307,7 +308,8 @@ public class DefaultProjectBuilder
         org.eclipse.aether.artifact.Artifact pomArtifact = RepositoryUtils.toArtifact( artifact );
         pomArtifact = ArtifactDescriptorUtils.toPomArtifact( pomArtifact );
 
-        InternalConfig config = new InternalConfig( request, null, useGlobalModelCache() ? getModelCache() : null );
+        InternalConfig config =
+            new InternalConfig( request, null, useGlobalModelCache() ? getModelCache() : null, null );
 
         boolean localProject;
 
@@ -379,8 +381,9 @@ public class DefaultProjectBuilder
         ReactorModelPool.Builder poolBuilder = new ReactorModelPool.Builder();
         final ReactorModelPool modelPool = poolBuilder.build();
         
-        InternalConfig config = new InternalConfig( request, modelPool,
-                useGlobalModelCache() ? getModelCache() : new ReactorModelCache() );
+        InternalConfig config =
+            new InternalConfig( request, modelPool, useGlobalModelCache() ? getModelCache() : new ReactorModelCache(),
+                        modelBuilder.newTransformerContextBuilder().setUserProperties( request.getUserProperties() ) );
 
         Map<File, MavenProject> projectIndex = new HashMap<>( 256 );
 
@@ -390,10 +393,8 @@ public class DefaultProjectBuilder
         
         if ( Features.buildConsumer().isActive() )
         {
-            ModelBuildingRequest buildingRequest = getModelBuildingRequest( config );
-            final TransformerContext context = modelBuilder.newTransformerContext( buildingRequest );
-            request.getRepositorySession().getData().set( TransformerContext.KEY, context );
-            buildingRequest.setTransformerContext( context );
+            request.getRepositorySession().getData().set( TransformerContext.KEY,
+                                                          config.transformerContextBuilder.build() );
         }
 
         ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
@@ -608,13 +609,8 @@ public class DefaultProjectBuilder
     {
         boolean noErrors = true;
         
-        final TransformerContext transformerContext =
-            (TransformerContext) request.getRepositorySession().getData().get( TransformerContext.KEY );
-
         for ( InterimResult interimResult : interimResults )
         {
-            interimResult.request.setTransformerContext( transformerContext );
-            
             MavenProject project = interimResult.listener.getProject();
             try
             {
@@ -1064,16 +1060,22 @@ public class DefaultProjectBuilder
         private final ReactorModelPool modelPool;
 
         private final ReactorModelCache modelCache;
+        
+        private final TransformerContextBuilder transformerContextBuilder;
 
-        InternalConfig( ProjectBuildingRequest request, ReactorModelPool modelPool, ReactorModelCache modelCache )
+        InternalConfig( ProjectBuildingRequest request, ReactorModelPool modelPool, ReactorModelCache modelCache,
+                        TransformerContextBuilder transformerContextBuilder )
         {
             this.request = request;
             this.modelPool = modelPool;
             this.modelCache = modelCache;
+            this.transformerContextBuilder = transformerContextBuilder;
+            
             session =
                 LegacyLocalRepositoryManager.overlay( request.getLocalRepository(), request.getRepositorySession(),
                                                       repoSystem );
             repositories = RepositoryUtils.toRepos( request.getRemoteRepositories() );
+            
         }
 
     }
diff --git a/maven-core/src/main/java/org/apache/maven/xml/internal/DefaultConsumerPomXMLFilterFactory.java b/maven-core/src/main/java/org/apache/maven/xml/internal/DefaultConsumerPomXMLFilterFactory.java
index f49e62d..eb94a1e 100644
--- a/maven-core/src/main/java/org/apache/maven/xml/internal/DefaultConsumerPomXMLFilterFactory.java
+++ b/maven-core/src/main/java/org/apache/maven/xml/internal/DefaultConsumerPomXMLFilterFactory.java
@@ -9,7 +9,7 @@ package org.apache.maven.xml.internal;
  * "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
+ *  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
@@ -19,10 +19,7 @@ package org.apache.maven.xml.internal;
  * under the License.
  */
 
-import java.util.Optional;
-
 import org.apache.maven.model.building.DefaultBuildPomXMLFilterFactory;
-import org.apache.maven.model.building.TransformerContext;
 import org.apache.maven.xml.sax.filter.ConsumerPomXMLFilterFactory;
 
 /**
@@ -34,32 +31,8 @@ import org.apache.maven.xml.sax.filter.ConsumerPomXMLFilterFactory;
  */
 public class DefaultConsumerPomXMLFilterFactory extends ConsumerPomXMLFilterFactory
 {
-    private final TransformerContext context;
-    
     public DefaultConsumerPomXMLFilterFactory( DefaultBuildPomXMLFilterFactory buildPomXMLFilterFactory )
     {
         super( buildPomXMLFilterFactory );
-        this.context = buildPomXMLFilterFactory.getContext();
-    }
-    
-    @Override
-    protected Optional<String> getChangelist()
-    {
-        return Optional.ofNullable( context.getUserProperty( "changelist" ) );
-    }
-
-    @Override
-    protected Optional<String> getRevision()
-    {
-        return Optional.ofNullable( context.getUserProperty( "revision" ) );
     }
-
-    @Override
-    protected Optional<String> getSha1()
-    {
-        return Optional.ofNullable( context.getUserProperty( "sha1" ) );
-    }
-
-
-
 }
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/BuildModelSourceTransformer.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/BuildModelSourceTransformer.java
index dbf9211..590db48 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/BuildModelSourceTransformer.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/BuildModelSourceTransformer.java
@@ -53,7 +53,7 @@ class BuildModelSourceTransformer extends AbstractModelSourceTransformer
     protected AbstractSAXFilter getSAXFilter( Path pomFile, TransformerContext context )
         throws TransformerConfigurationException, SAXException, ParserConfigurationException
     {
-        BuildPomXMLFilterFactory buildPomXMLFilterFactory = new DefaultBuildPomXMLFilterFactory( context );
+        BuildPomXMLFilterFactory buildPomXMLFilterFactory = new DefaultBuildPomXMLFilterFactory( context, false );
         
         return buildPomXMLFilterFactory.get( pomFile );
     }
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java
index 3de90de..adf4060 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java
@@ -38,16 +38,12 @@ public class DefaultBuildPomXMLFilterFactory extends BuildPomXMLFilterFactory
 {
     private final TransformerContext context;
     
-    public DefaultBuildPomXMLFilterFactory( TransformerContext context )
+    public DefaultBuildPomXMLFilterFactory( TransformerContext context, boolean consume )
     {
+        super( consume );
         this.context = context;
     }
     
-    public final TransformerContext getContext()
-    {
-        return context;
-    }
-    
     @Override
     protected Function<Path, Optional<RelativeProject>> getRelativePathMapper()
     {
@@ -61,6 +57,24 @@ public class DefaultBuildPomXMLFilterFactory extends BuildPomXMLFilterFactory
                             .map( m -> toVersion( m ) )
                             .orElse( null );
     }
+    
+    @Override
+    protected Optional<String> getChangelist()
+    {
+        return Optional.ofNullable( context.getUserProperty( "changelist" ) );
+    }
+
+    @Override
+    protected Optional<String> getRevision()
+    {
+        return Optional.ofNullable( context.getUserProperty( "revision" ) );
+    }
+
+    @Override
+    protected Optional<String> getSha1()
+    {
+        return Optional.ofNullable( context.getUserProperty( "sha1" ) );
+    }
 
     private static RelativeProject toRelativeProject( final Model m )
     {
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 139ed70..29e4e07 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
@@ -264,86 +264,9 @@ public class DefaultModelBuilder
     }
     
     @Override
-    public TransformerContext newTransformerContext( ModelBuildingRequest request )
+    public TransformerContextBuilder newTransformerContextBuilder()
     {
-        return new TransformerContext()
-        {
-            @Override
-            public String getUserProperty( String key )
-            {
-                return request.getUserProperties().getProperty( key );
-            }
-            
-            @Override
-            public Model getRawModel( String groupId, String artifactId )
-                throws IllegalStateException
-            {
-                Source source = fromCache( request.getModelCache(), groupId, artifactId );
-                if ( source != null )
-                {
-                    try
-                    {
-                        ModelBuildingRequest req = new FilterModelBuildingRequest( request ) 
-                        {
-                            public ModelSource getModelSource() 
-                            {
-                                return (ModelSource) source;
-                            };
-                        };
-                        ModelBuildingRequest gaBuildingRequest = new FilterModelBuildingRequest( request ) 
-                        {
-                            @Override
-                            public ModelSource getModelSource()
-                            {
-                                return (ModelSource) source;
-                            }
-                            
-                        };
-                        
-                        // @todo use originals
-                        DefaultModelBuildingResult res = new DefaultModelBuildingResult();
-                        return readRawModel( gaBuildingRequest, new DefaultModelProblemCollector( res ), null );
-                    }
-                    catch ( ModelBuildingException e )
-                    {
-                        // TODO Auto-generated catch block
-                        e.printStackTrace();
-                    }
-                }
-                return null;
-            }
-            
-            @Override
-            public Model getRawModel( Path p )
-            {
-                File pomFile;
-                if ( Files.isDirectory( p ) )
-                {
-                    pomFile = modelLocator.locatePom( p.toFile() );
-                }
-                else
-                {
-                    pomFile = p.toFile();
-                }
-                
-                DefaultModelBuildingRequest req = new DefaultModelBuildingRequest( request )
-                                .setPomFile( pomFile )
-                                .setModelSource( new FileModelSource( pomFile ) );
-                
-                DefaultModelBuildingResult res = new DefaultModelBuildingResult();
-                try
-                {
-                    return readRawModel( req, new DefaultModelProblemCollector( res ),
-                                         null );
-                }
-                catch ( ModelBuildingException e )
-                {
-                    // TODO Auto-generated catch block
-                    e.printStackTrace();
-                }
-                return null;
-            }
-        };
+        return new TransformerContextBuilder();
     }
     
     @Override
@@ -797,12 +720,19 @@ public class DefaultModelBuilder
         if ( Features.buildConsumer().isActive() && modelSource instanceof FileModelSource )
         {
             rawModel = readFileModel( request, problems );
-            File pomFile = ( (FileModelSource) modelSource ).getFile();            
-
+            File pomFile = ( (FileModelSource) modelSource ).getFile();
+            
+            TransformerContext context = null;
+            if ( request.getTransformerContextBuilder() != null )
+            {
+                context = request.getTransformerContextBuilder().initialize( request, null, problems );   
+            }
+            
             try
             {
+                // must implement TransformContext, but should use request to access system properties/modelcache
                 Model transformedFileModel = modelProcessor.read( pomFile,
-                       Collections.singletonMap( ModelReader.TRANSFORMER_CONTEXT, request.getTransformerContext() ) );
+                   Collections.singletonMap( ModelReader.TRANSFORMER_CONTEXT, context ) );
 
                 // rawModel with locationTrackers, required for proper feedback during validations
                 
@@ -1865,4 +1795,113 @@ public class DefaultModelBuilder
             // don't merge
         }
     }
+    
+    /**
+     * Builds up the transformer context.
+     * After the buildplan is ready, the build()-method returns the immutable context useful during distribution
+     * 
+     * @author Robert Scholte
+     * @since 3.7.0
+     */
+    public class TransformerContextBuilder
+    {
+        private final DefaultTransformerContext context = new DefaultTransformerContext();
+        
+        private Properties userProperties;
+        
+        public TransformerContextBuilder setUserProperties( Properties userProperties )
+        {
+            this.userProperties = userProperties;
+            return this;
+        }
+        
+        TransformerContext initialize( ModelBuildingRequest request, DefaultModelBuildingResult result,
+                                       ModelProblemCollector problems )
+        {
+            return new TransformerContext()
+            {
+                @Override
+                public String getUserProperty( String key )
+                {
+                    return context.userProperties.computeIfAbsent( key,
+                                                                   k -> userProperties.getProperty( key ) );
+                }
+                
+                @Override
+                public Model getRawModel( String gId, String aId )
+                {
+                    return context.modelByGA.computeIfAbsent( new DefaultTransformerContext.GAKey( gId, aId ),
+                                                              k -> findRawModel( gId, aId ) );
+                }
+                
+                @Override
+                public Model getRawModel( Path path )
+                {
+                    return context.modelByPath.computeIfAbsent( path, k -> findRawModel( path ) );
+                }
+
+                private Model findRawModel( String groupId, String artifactId )
+                {
+                    Source source = fromCache( request.getModelCache(), groupId, artifactId );
+                    if ( source != null )
+                    {
+                        try
+                        {
+                            ModelBuildingRequest gaBuildingRequest = new FilterModelBuildingRequest( request ) 
+                            {
+                                @Override
+                                public ModelSource getModelSource()
+                                {
+                                    return (ModelSource) source;
+                                }
+                                
+                            };
+                            DefaultModelBuildingResult res = new DefaultModelBuildingResult();
+                            return readRawModel( gaBuildingRequest, new DefaultModelProblemCollector( res ), null );
+                        }
+                        catch ( ModelBuildingException e )
+                        {
+                            // gathered with problem collector
+                        }
+                    }
+                    return null;
+                }
+                
+                private Model findRawModel( Path p )
+                {
+                    File pomFile;
+                    if ( Files.isDirectory( p ) )
+                    {
+                        pomFile = modelLocator.locatePom( p.toFile() );
+                    }
+                    else
+                    {
+                        pomFile = p.toFile();
+                    }
+                    
+                    DefaultModelBuildingRequest req = new DefaultModelBuildingRequest( request )
+                                    .setPomFile( pomFile )
+                                    .setModelSource( new FileModelSource( pomFile ) );
+                    
+                    DefaultModelBuildingResult res = new DefaultModelBuildingResult();
+                    try
+                    {
+                        return readRawModel( req, new DefaultModelProblemCollector( res ),
+                                             null );
+                    }
+                    catch ( ModelBuildingException e )
+                    {
+                        // gathered with problem collector
+
+                    }
+                    return null;
+                }
+            };
+        }
+
+        public TransformerContext build()
+        {
+            return context;
+        }        
+    }
 }
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java
index 8cf8376..8e58ff8 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java
@@ -27,6 +27,7 @@ import java.util.Properties;
 
 import org.apache.maven.model.Model;
 import org.apache.maven.model.Profile;
+import org.apache.maven.model.building.DefaultModelBuilder.TransformerContextBuilder;
 import org.apache.maven.model.resolution.ModelResolver;
 import org.apache.maven.model.resolution.WorkspaceModelResolver;
 
@@ -38,8 +39,6 @@ import org.apache.maven.model.resolution.WorkspaceModelResolver;
 public class DefaultModelBuildingRequest
     implements ModelBuildingRequest
 {
-    private Model fileModel;
-
     private Model rawModel;
 
     private File pomFile;
@@ -74,7 +73,7 @@ public class DefaultModelBuildingRequest
 
     private WorkspaceModelResolver workspaceResolver;
     
-    private TransformerContext context;
+    private TransformerContextBuilder contextBuilder;
 
     /**
      * Creates an empty request.
@@ -104,7 +103,7 @@ public class DefaultModelBuildingRequest
         setModelResolver( request.getModelResolver() );
         setModelBuildingListener( request.getModelBuildingListener() );
         setModelCache( request.getModelCache() );
-        setTransformerContext( request.getTransformerContext() );
+        setTransformerContextBuilder( request.getTransformerContextBuilder() );
     }
 
     @Override
@@ -411,17 +410,18 @@ public class DefaultModelBuildingRequest
         this.workspaceResolver = workspaceResolver;
         return this;
     }
-    
+
     @Override
-    public TransformerContext getTransformerContext()
+    public TransformerContextBuilder getTransformerContextBuilder()
     {
-        return context;
+        return contextBuilder;
     }
     
     @Override
-    public ModelBuildingRequest setTransformerContext( TransformerContext context )
+    public ModelBuildingRequest setTransformerContextBuilder( TransformerContextBuilder contextBuilder )
     {
-        this.context = context;
+        this.contextBuilder = contextBuilder;
         return this;
     }
+
 }
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultTransformerContext.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultTransformerContext.java
new file mode 100644
index 0000000..48b60c2
--- /dev/null
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultTransformerContext.java
@@ -0,0 +1,90 @@
+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.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import org.apache.maven.model.Model;
+
+/**
+ * 
+ * @author Robert Scholte
+ * @since 3.7.0
+ */
+class DefaultTransformerContext implements TransformerContext
+{
+    final Map<String, String> userProperties = new HashMap<>();
+    
+    final Map<Path, Model> modelByPath = new HashMap<>();
+
+    final Map<GAKey, Model> modelByGA = new HashMap<>();
+    
+    @Override
+    public String getUserProperty( String key )
+    {
+        return userProperties.get( key );
+    }
+
+    @Override
+    public Model getRawModel( Path p )
+    {
+        return modelByPath.get( p );
+    }
+
+    @Override
+    public Model getRawModel( String groupId, String artifactId )
+    {
+        return modelByGA.get( new GAKey( groupId, artifactId ) );
+    }
+    
+    static class GAKey
+    {
+        private final String groupId;
+        private final String artifactId;
+        private final int hashCode;
+        
+        GAKey( String groupId, String artifactId )
+        {
+            this.groupId = groupId;
+            this.artifactId = artifactId;
+            this.hashCode = Objects.hash( groupId, artifactId );
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return hashCode;
+        }
+
+        @Override
+        public boolean equals( Object obj )
+        {
+            if ( this == obj )
+            {
+                return true;
+            }
+            GAKey other = (GAKey) obj;
+            return Objects.equals( artifactId, other.artifactId ) && Objects.equals( groupId, other.groupId );
+        }
+    }
+}
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java
index e56dc22..668f997 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java
@@ -26,6 +26,7 @@ import java.util.Properties;
 
 import org.apache.maven.model.Model;
 import org.apache.maven.model.Profile;
+import org.apache.maven.model.building.DefaultModelBuilder.TransformerContextBuilder;
 import org.apache.maven.model.resolution.ModelResolver;
 import org.apache.maven.model.resolution.WorkspaceModelResolver;
 
@@ -281,17 +282,17 @@ class FilterModelBuildingRequest
         request.setWorkspaceModelResolver( workspaceResolver );
         return this;
     }
-    
+
     @Override
-    public TransformerContext getTransformerContext()
+    public TransformerContextBuilder getTransformerContextBuilder()
     {
-        return request.getTransformerContext();
+        return request.getTransformerContextBuilder();
     }
     
     @Override
-    public ModelBuildingRequest setTransformerContext( TransformerContext context )
+    public ModelBuildingRequest setTransformerContextBuilder( TransformerContextBuilder contextBuilder )
     {
-        request.setTransformerContext( context );
+        request.setTransformerContextBuilder( contextBuilder );
         return this;
     }
 }
\ No newline at end of file
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java
index 6f6def0..aa63df7 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java
@@ -22,6 +22,7 @@ package org.apache.maven.model.building;
 import java.io.File;
 
 import org.apache.maven.model.Model;
+import org.apache.maven.model.building.DefaultModelBuilder.TransformerContextBuilder;
 
 /**
  * Builds the effective model from a POM.
@@ -60,6 +61,6 @@ public interface ModelBuilder
      */
     Result<? extends Model> buildRawModel( File pomFile, int validationLevel, boolean locationTracking );
     
-    TransformerContext newTransformerContext( ModelBuildingRequest request );
+    TransformerContextBuilder newTransformerContextBuilder();
 
 }
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java
index c21a417..37ea102 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java
@@ -26,6 +26,7 @@ import java.util.Properties;
 
 import org.apache.maven.model.Model;
 import org.apache.maven.model.Profile;
+import org.apache.maven.model.building.DefaultModelBuilder.TransformerContextBuilder;
 import org.apache.maven.model.resolution.ModelResolver;
 import org.apache.maven.model.resolution.WorkspaceModelResolver;
 
@@ -335,9 +336,9 @@ public interface ModelBuildingRequest
 
     ModelBuildingRequest setWorkspaceModelResolver( WorkspaceModelResolver workspaceResolver );
     
-    TransformerContext getTransformerContext();
+    TransformerContextBuilder getTransformerContextBuilder();
 
-    ModelBuildingRequest setTransformerContext( TransformerContext context );
+    ModelBuildingRequest setTransformerContextBuilder( TransformerContextBuilder contextBuilder );
     
     
 }
diff --git a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/BuildPomXMLFilterFactory.java b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/BuildPomXMLFilterFactory.java
index 6f3f319..fc7c095 100644
--- a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/BuildPomXMLFilterFactory.java
+++ b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/BuildPomXMLFilterFactory.java
@@ -42,6 +42,13 @@ import org.xml.sax.ext.LexicalHandler;
  */
 public class BuildPomXMLFilterFactory
 {
+    private final boolean consume;
+    
+    public BuildPomXMLFilterFactory( boolean consume )
+    {
+        this.consume = consume;
+    }
+    
     /**
      * 
      * @param projectFile will be used by ConsumerPomXMLFilter to get the right filter
@@ -74,6 +81,18 @@ public class BuildPomXMLFilterFactory
             parentFilter.setLexicalHandler( parent );
             parent = parentFilter;
         }
+        
+        CiFriendlyXMLFilter ciFriendlyFilter = new CiFriendlyXMLFilter( consume );
+        getChangelist().ifPresent( ciFriendlyFilter::setChangelist  );
+        getRevision().ifPresent( ciFriendlyFilter::setRevision );
+        getSha1().ifPresent( ciFriendlyFilter::setSha1 );
+        
+        if ( ciFriendlyFilter.isSet() )
+        {
+            ciFriendlyFilter.setParent( parent );
+            ciFriendlyFilter.setLexicalHandler( parent );
+            parent = ciFriendlyFilter;
+        }
 
         return new BuildPomXMLFilter( parent );
     }
@@ -109,4 +128,22 @@ public class BuildPomXMLFilterFactory
     {
         return null;
     }
+    
+    // getters for the 3 magic properties of CIFriendly versions ( https://maven.apache.org/maven-ci-friendly.html )
+
+    protected Optional<String> getChangelist()
+    {
+        return Optional.empty();
+    }
+
+    protected Optional<String> getRevision()
+    {
+        return Optional.empty();
+    }
+
+    protected Optional<String> getSha1()
+    {
+        return Optional.empty();
+    }
+
 }
diff --git a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilter.java b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilter.java
index 4375f18..cecea6a 100644
--- a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilter.java
+++ b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilter.java
@@ -33,6 +33,13 @@ import org.xml.sax.SAXException;
 class CiFriendlyXMLFilter
     extends AbstractSAXFilter
 {
+    private final boolean replace;
+    
+    CiFriendlyXMLFilter( boolean replace )
+    {
+        this.replace = replace;
+    }
+
     private Function<String, String> replaceChain = Function.identity();
     
     private String characters; 
@@ -98,7 +105,7 @@ class CiFriendlyXMLFilter
         if ( parseVersion )
         {
             // assuming this has the best performance
-            if ( characters != null && characters.contains( "${" ) )
+            if ( replace && characters != null && characters.contains( "${" ) )
             {
                 char[] ch = replaceChain.apply( characters ).toCharArray();
                 super.characters( ch, 0, ch.length );
diff --git a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/ConsumerPomXMLFilterFactory.java b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/ConsumerPomXMLFilterFactory.java
index f7751d2..2b2f542 100644
--- a/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/ConsumerPomXMLFilterFactory.java
+++ b/maven-xml/src/main/java/org/apache/maven/xml/sax/filter/ConsumerPomXMLFilterFactory.java
@@ -20,7 +20,6 @@ package org.apache.maven.xml.sax.filter;
  */
 
 import java.nio.file.Path;
-import java.util.Optional;
 
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.TransformerConfigurationException;
@@ -49,18 +48,6 @@ public class ConsumerPomXMLFilterFactory
         // Ensure that xs:any elements aren't touched by next filters
         AbstractSAXFilter filter = new FastForwardFilter( parent );
         
-        CiFriendlyXMLFilter ciFriendlyFilter = new CiFriendlyXMLFilter();
-        getChangelist().ifPresent( ciFriendlyFilter::setChangelist  );
-        getRevision().ifPresent( ciFriendlyFilter::setRevision );
-        getSha1().ifPresent( ciFriendlyFilter::setSha1 );
-        
-        if ( ciFriendlyFilter.isSet() )
-        {
-            ciFriendlyFilter.setParent( parent );
-            ciFriendlyFilter.setLexicalHandler( parent );
-            filter = ciFriendlyFilter;
-        }
-        
         // Strip modules
         filter = new ModulesXMLFilter( filter );
         // Adjust relativePath
@@ -68,22 +55,4 @@ public class ConsumerPomXMLFilterFactory
         
         return new ConsumerPomXMLFilter( filter );
     }
-    
-    // getters for the 3 magic properties of CIFriendly versions ( https://maven.apache.org/maven-ci-friendly.html )
-
-    protected Optional<String> getChangelist()
-    {
-        return Optional.empty();
-    }
-
-    protected Optional<String> getRevision()
-    {
-        return Optional.empty();
-    }
-
-    protected Optional<String> getSha1()
-    {
-        return Optional.empty();
-    }
-
 }
diff --git a/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilterTest.java b/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilterTest.java
index e93c720..7dcdc4f 100644
--- a/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilterTest.java
+++ b/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/CiFriendlyXMLFilterTest.java
@@ -35,7 +35,7 @@ public class CiFriendlyXMLFilterTest extends AbstractXMLFilterTests
     @Before
     public void setUp()
     {
-        filter = new CiFriendlyXMLFilter();
+        filter = new CiFriendlyXMLFilter( true );
         filter.setChangelist( "CHANGELIST" );
     }
     
diff --git a/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/ConsumerPomXMLFilterTest.java b/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/ConsumerPomXMLFilterTest.java
index 16d458b..d6cd04a 100644
--- a/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/ConsumerPomXMLFilterTest.java
+++ b/maven-xml/src/test/java/org/apache/maven/xml/sax/filter/ConsumerPomXMLFilterTest.java
@@ -44,7 +44,7 @@ public class ConsumerPomXMLFilterTest extends AbstractXMLFilterTests
     @Override
     protected AbstractSAXFilter getFilter() throws SAXException, ParserConfigurationException, TransformerConfigurationException
     {
-        final BuildPomXMLFilterFactory buildPomXMLFilterFactory = new BuildPomXMLFilterFactory()
+        final BuildPomXMLFilterFactory buildPomXMLFilterFactory = new BuildPomXMLFilterFactory( true )
         {
             @Override
             protected Function<Path, Optional<RelativeProject>> getRelativePathMapper()
@@ -57,10 +57,7 @@ public class ConsumerPomXMLFilterTest extends AbstractXMLFilterTests
             {
                 return null;
             }
-        };
-        
-        ConsumerPomXMLFilter filter = new ConsumerPomXMLFilterFactory( buildPomXMLFilterFactory )
-        {
+            
             @Override
             protected Optional<String> getSha1()
             {
@@ -78,7 +75,11 @@ public class ConsumerPomXMLFilterTest extends AbstractXMLFilterTests
             {
                 return Optional.of( "CL" );
             }
-        }.get( Paths.get( "pom.xml" ) );
+
+        };
+        
+        ConsumerPomXMLFilter filter =
+            new ConsumerPomXMLFilterFactory( buildPomXMLFilterFactory ).get( Paths.get( "pom.xml" ) );
         filter.setFeature( "http://xml.org/sax/features/namespaces", true );
         return filter;
     }