View Javadoc
1   package org.apache.maven.model.building;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static org.apache.maven.model.building.Result.error;
23  import static org.apache.maven.model.building.Result.newResult;
24  
25  import java.io.File;
26  import java.io.IOException;
27  import java.lang.reflect.Field;
28  import java.nio.file.Files;
29  import java.nio.file.Path;
30  import java.util.ArrayList;
31  import java.util.Collection;
32  import java.util.Collections;
33  import java.util.HashMap;
34  import java.util.HashSet;
35  import java.util.Iterator;
36  import java.util.LinkedHashSet;
37  import java.util.List;
38  import java.util.Map;
39  import java.util.Objects;
40  import java.util.Properties;
41  import java.util.Set;
42  import java.util.concurrent.ConcurrentHashMap;
43  
44  import javax.inject.Inject;
45  import javax.inject.Named;
46  import javax.inject.Singleton;
47  
48  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
49  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
50  import org.apache.maven.artifact.versioning.VersionRange;
51  import org.apache.maven.building.Source;
52  import org.apache.maven.feature.Features;
53  import org.apache.maven.model.Activation;
54  import org.apache.maven.model.ActivationFile;
55  import org.apache.maven.model.Build;
56  import org.apache.maven.model.Dependency;
57  import org.apache.maven.model.DependencyManagement;
58  import org.apache.maven.model.InputLocation;
59  import org.apache.maven.api.model.InputSource;
60  import org.apache.maven.model.Model;
61  import org.apache.maven.model.Parent;
62  import org.apache.maven.model.Plugin;
63  import org.apache.maven.model.PluginManagement;
64  import org.apache.maven.model.Profile;
65  import org.apache.maven.model.Repository;
66  import org.apache.maven.model.building.ModelProblem.Severity;
67  import org.apache.maven.model.building.ModelProblem.Version;
68  import org.apache.maven.model.composition.DependencyManagementImporter;
69  import org.apache.maven.model.inheritance.InheritanceAssembler;
70  import org.apache.maven.model.interpolation.ModelInterpolator;
71  import org.apache.maven.model.interpolation.ModelVersionProcessor;
72  import org.apache.maven.model.io.ModelParseException;
73  import org.apache.maven.model.io.ModelReader;
74  import org.apache.maven.model.management.DependencyManagementInjector;
75  import org.apache.maven.model.management.PluginManagementInjector;
76  import org.apache.maven.model.normalization.ModelNormalizer;
77  import org.apache.maven.model.path.ModelPathTranslator;
78  import org.apache.maven.model.path.ModelUrlNormalizer;
79  import org.apache.maven.model.path.ProfileActivationFilePathInterpolator;
80  import org.apache.maven.model.plugin.LifecycleBindingsInjector;
81  import org.apache.maven.model.plugin.PluginConfigurationExpander;
82  import org.apache.maven.model.plugin.ReportConfigurationExpander;
83  import org.apache.maven.model.plugin.ReportingConverter;
84  import org.apache.maven.model.profile.DefaultProfileActivationContext;
85  import org.apache.maven.model.profile.ProfileActivationContext;
86  import org.apache.maven.model.profile.ProfileInjector;
87  import org.apache.maven.model.profile.ProfileSelector;
88  import org.apache.maven.model.resolution.InvalidRepositoryException;
89  import org.apache.maven.model.resolution.ModelResolver;
90  import org.apache.maven.model.resolution.UnresolvableModelException;
91  import org.apache.maven.model.resolution.WorkspaceModelResolver;
92  import org.apache.maven.model.superpom.SuperPomProvider;
93  import org.apache.maven.model.v4.MavenMerger;
94  import org.apache.maven.model.validation.ModelValidator;
95  import org.codehaus.plexus.interpolation.InterpolationException;
96  import org.codehaus.plexus.interpolation.MapBasedValueSource;
97  import org.codehaus.plexus.interpolation.StringSearchInterpolator;
98  import org.eclipse.sisu.Nullable;
99  
100 /**
101  * @author Benjamin Bentmann
102  */
103 @Named
104 @Singleton
105 public class DefaultModelBuilder
106         implements ModelBuilder
107 {
108     private final MavenMerger modelMerger = new FileToRawModelMerger();
109 
110     private final ModelProcessor modelProcessor;
111     private final ModelValidator modelValidator;
112     private final ModelNormalizer modelNormalizer;
113     private final ModelInterpolator modelInterpolator;
114     private final ModelPathTranslator modelPathTranslator;
115     private final ModelUrlNormalizer modelUrlNormalizer;
116     private final SuperPomProvider superPomProvider;
117     private final InheritanceAssembler inheritanceAssembler;
118     private final ProfileSelector profileSelector;
119     private final ProfileInjector profileInjector;
120     private final PluginManagementInjector pluginManagementInjector;
121     private final DependencyManagementInjector dependencyManagementInjector;
122     private final DependencyManagementImporter dependencyManagementImporter;
123     private final LifecycleBindingsInjector lifecycleBindingsInjector;
124     private final PluginConfigurationExpander pluginConfigurationExpander;
125     private final ReportConfigurationExpander reportConfigurationExpander;
126     private final ReportingConverter reportingConverter;
127     private final ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator;
128     private final ModelVersionProcessor versionProcessor;
129 
130     @SuppressWarnings( "checkstyle:ParameterNumber" )
131     @Inject
132     public DefaultModelBuilder(
133             ModelProcessor modelProcessor,
134             ModelValidator modelValidator,
135             ModelNormalizer modelNormalizer,
136             ModelInterpolator modelInterpolator,
137             ModelPathTranslator modelPathTranslator,
138             ModelUrlNormalizer modelUrlNormalizer,
139             SuperPomProvider superPomProvider,
140             InheritanceAssembler inheritanceAssembler,
141             ProfileSelector profileSelector,
142             ProfileInjector profileInjector,
143             PluginManagementInjector pluginManagementInjector,
144             DependencyManagementInjector dependencyManagementInjector,
145             DependencyManagementImporter dependencyManagementImporter,
146             @Nullable LifecycleBindingsInjector lifecycleBindingsInjector,
147             PluginConfigurationExpander pluginConfigurationExpander,
148             ReportConfigurationExpander reportConfigurationExpander,
149             ReportingConverter reportingConverter,
150             ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator,
151             ModelVersionProcessor versionProcessor )
152     {
153         this.modelProcessor = modelProcessor;
154         this.modelValidator = modelValidator;
155         this.modelNormalizer = modelNormalizer;
156         this.modelInterpolator = modelInterpolator;
157         this.modelPathTranslator = modelPathTranslator;
158         this.modelUrlNormalizer = modelUrlNormalizer;
159         this.superPomProvider = superPomProvider;
160         this.inheritanceAssembler = inheritanceAssembler;
161         this.profileSelector = profileSelector;
162         this.profileInjector = profileInjector;
163         this.pluginManagementInjector = pluginManagementInjector;
164         this.dependencyManagementInjector = dependencyManagementInjector;
165         this.dependencyManagementImporter = dependencyManagementImporter;
166         this.lifecycleBindingsInjector = lifecycleBindingsInjector;
167         this.pluginConfigurationExpander = pluginConfigurationExpander;
168         this.reportConfigurationExpander = reportConfigurationExpander;
169         this.reportingConverter = reportingConverter;
170         this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator;
171         this.versionProcessor = versionProcessor;
172     }
173 
174     /**
175      * @deprecated since Maven 4
176      * @see DefaultModelBuilderFactory#setModelProcessor(ModelProcessor) 
177      */
178     @Deprecated
179     public DefaultModelBuilder setModelProcessor( ModelProcessor modelProcessor )
180     {
181         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
182                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
183                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
184                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
185                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
186     }
187 
188     /**
189      * @deprecated since Maven 4
190      * @see DefaultModelBuilderFactory#setModelProcessor(ModelProcessor) 
191      */
192     @Deprecated
193     public DefaultModelBuilder setModelValidator( ModelValidator modelValidator )
194     {
195         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
196                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
197                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
198                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
199                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
200     }
201 
202     /**
203      * @deprecated since Maven 4
204      * @see DefaultModelBuilderFactory#setModelNormalizer(ModelNormalizer) 
205      */
206     @Deprecated
207     public DefaultModelBuilder setModelNormalizer( ModelNormalizer modelNormalizer )
208     {
209         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
210                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
211                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
212                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
213                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
214     }
215 
216     /**
217      * @deprecated since Maven 4
218      * @see DefaultModelBuilderFactory#setModelInterpolator(ModelInterpolator) 
219      */
220     @Deprecated
221     public DefaultModelBuilder setModelInterpolator( ModelInterpolator modelInterpolator )
222     {
223         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
224                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
225                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
226                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
227                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
228     }
229 
230     /**
231      * @deprecated since Maven 4
232      * @see DefaultModelBuilderFactory#setModelPathTranslator(ModelPathTranslator)
233      */
234     @Deprecated
235     public DefaultModelBuilder setModelPathTranslator( ModelPathTranslator modelPathTranslator )
236     {
237         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
238                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
239                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
240                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
241                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
242     }
243 
244     /**
245      * @deprecated since Maven 4
246      * @see DefaultModelBuilderFactory#setModelUrlNormalizer(ModelUrlNormalizer) 
247      */
248     @Deprecated
249     public DefaultModelBuilder setModelUrlNormalizer( ModelUrlNormalizer modelUrlNormalizer )
250     {
251         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
252                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
253                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
254                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
255                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
256     }
257 
258     /**
259      * @deprecated since Maven 4
260      * @see DefaultModelBuilderFactory#setSuperPomProvider(SuperPomProvider) 
261      */
262     @Deprecated
263     public DefaultModelBuilder setSuperPomProvider( SuperPomProvider superPomProvider )
264     {
265         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
266                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
267                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
268                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
269                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
270     }
271 
272     /**
273      * @deprecated since Maven 4
274      * @see DefaultModelBuilderFactory#setInheritanceAssembler(InheritanceAssembler) 
275      */
276     @Deprecated
277     public DefaultModelBuilder setInheritanceAssembler( InheritanceAssembler inheritanceAssembler )
278     {
279         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
280                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
281                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
282                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
283                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
284     }
285 
286     /**
287      * @deprecated since Maven 4
288      * @see DefaultModelBuilderFactory#setProfileSelector(ProfileSelector)
289      */
290     @Deprecated
291     public DefaultModelBuilder setProfileSelector( ProfileSelector profileSelector )
292     {
293         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
294                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
295                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
296                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
297                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
298     }
299 
300     /**
301      * @deprecated since Maven 4
302      * @see DefaultModelBuilderFactory#setProfileInjector(ProfileInjector) 
303      */
304     @Deprecated
305     public DefaultModelBuilder setProfileInjector( ProfileInjector profileInjector )
306     {
307         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
308                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
309                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
310                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
311                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
312     }
313 
314     /**
315      * @deprecated since Maven 4
316      * @see DefaultModelBuilderFactory#setPluginManagementInjector(PluginManagementInjector) 
317      */
318     @Deprecated
319     public DefaultModelBuilder setPluginManagementInjector( PluginManagementInjector pluginManagementInjector )
320     {
321         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
322                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
323                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
324                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
325                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
326     }
327 
328     /**
329      * @deprecated since Maven 4
330      * @see DefaultModelBuilderFactory#setDependencyManagementInjector(DependencyManagementInjector)  
331      */
332     @Deprecated
333     public DefaultModelBuilder setDependencyManagementInjector(
334             DependencyManagementInjector dependencyManagementInjector )
335     {
336         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
337                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
338                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
339                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
340                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
341     }
342 
343     /**
344      * @deprecated since Maven 4
345      * @see DefaultModelBuilderFactory#setDependencyManagementImporter(DependencyManagementImporter) 
346      */
347     @Deprecated
348     public DefaultModelBuilder setDependencyManagementImporter(
349             DependencyManagementImporter dependencyManagementImporter )
350     {
351         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
352                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
353                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
354                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
355                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
356     }
357 
358     /**
359      * @deprecated since Maven 4
360      * @see DefaultModelBuilderFactory#setLifecycleBindingsInjector(LifecycleBindingsInjector) 
361      */
362     @Deprecated
363     public DefaultModelBuilder setLifecycleBindingsInjector( LifecycleBindingsInjector lifecycleBindingsInjector )
364     {
365         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
366                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
367                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
368                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
369                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
370     }
371 
372     /**
373      * @deprecated since Maven 4
374      * @see DefaultModelBuilderFactory#setPluginConfigurationExpander(PluginConfigurationExpander) 
375      */
376     @Deprecated
377     public DefaultModelBuilder setPluginConfigurationExpander( PluginConfigurationExpander pluginConfigurationExpander )
378     {
379         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
380                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
381                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
382                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
383                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
384     }
385 
386     /**
387      * @deprecated since Maven 4
388      * @see DefaultModelBuilderFactory#setReportConfigurationExpander(ReportConfigurationExpander)  
389      */
390     @Deprecated
391     public DefaultModelBuilder setReportConfigurationExpander( ReportConfigurationExpander reportConfigurationExpander )
392     {
393         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
394                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
395                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
396                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
397                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
398     }
399 
400     /**
401      * @deprecated since Maven 4
402      * @see DefaultModelBuilderFactory#setReportingConverter(ReportingConverter) 
403      */
404     @Deprecated
405     public DefaultModelBuilder setReportingConverter( ReportingConverter reportingConverter )
406     {
407         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
408                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
409                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
410                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
411                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
412     }
413 
414     /**
415      * @deprecated since Maven 4
416      * @see DefaultModelBuilderFactory#setProfileActivationFilePathInterpolator(ProfileActivationFilePathInterpolator)
417      */
418     @Deprecated
419     public DefaultModelBuilder setProfileActivationFilePathInterpolator(
420             ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator )
421     {
422         return new DefaultModelBuilder( modelProcessor, modelValidator, modelNormalizer, modelInterpolator,
423                 modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector,
424                 profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter,
425                 lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander,
426                 reportingConverter, profileActivationFilePathInterpolator, versionProcessor );
427     }
428 
429     @Override
430     public DefaultTransformerContextBuilder newTransformerContextBuilder()
431     {
432         return new DefaultTransformerContextBuilder();
433     }
434 
435     @Override
436     public ModelBuildingResult build( ModelBuildingRequest request )
437         throws ModelBuildingException
438     {
439         return build( request, new LinkedHashSet<>() );
440     }
441 
442     protected ModelBuildingResult build( ModelBuildingRequest request, Collection<String> importIds )
443         throws ModelBuildingException
444     {
445         // phase 1
446         DefaultModelBuildingResult result = new DefaultModelBuildingResult();
447 
448         DefaultModelProblemCollector problems = new DefaultModelProblemCollector( result );
449 
450         // read and validate raw model
451         Model fileModel = readFileModel( request, problems );
452 
453         request.setFileModel( fileModel );
454         result.setFileModel( fileModel );
455 
456         activateFileModel( request, result, problems );
457 
458         if ( !request.isTwoPhaseBuilding() )
459         {
460             return build( request, result, importIds );
461         }
462         else if ( hasModelErrors( problems ) )
463         {
464             throw problems.newModelBuildingException();
465         }
466 
467         return result;
468     }
469 
470     private void activateFileModel( final ModelBuildingRequest request, final DefaultModelBuildingResult result,
471                                     DefaultModelProblemCollector problems )
472             throws ModelBuildingException
473     {
474         Model inputModel = request.getFileModel();
475         problems.setRootModel( inputModel );
476 
477         // profile activation
478         DefaultProfileActivationContext profileActivationContext = getProfileActivationContext( request );
479 
480         problems.setSource( "(external profiles)" );
481         List<Profile> activeExternalProfiles = profileSelector.getActiveProfiles( request.getProfiles(),
482                                                                                   profileActivationContext, problems );
483 
484         result.setActiveExternalProfiles( activeExternalProfiles );
485 
486         if ( !activeExternalProfiles.isEmpty() )
487         {
488             Properties profileProps = new Properties();
489             for ( Profile profile : activeExternalProfiles )
490             {
491                 profileProps.putAll( profile.getProperties() );
492             }
493             profileProps.putAll( profileActivationContext.getUserProperties() );
494             profileActivationContext.setUserProperties( profileProps );
495         }
496 
497         profileActivationContext.setProjectProperties( inputModel.getProperties() );
498         problems.setSource( inputModel );
499         List<Profile> activePomProfiles = profileSelector.getActiveProfiles( inputModel.getProfiles(),
500                                                                              profileActivationContext, problems );
501 
502         // model normalization
503         problems.setSource( inputModel );
504         inputModel.update( modelNormalizer.mergeDuplicates( inputModel.getDelegate(), request, problems ) );
505 
506         Map<String, Activation> interpolatedActivations = getProfileActivations( inputModel, false );
507         injectProfileActivations( inputModel, interpolatedActivations );
508 
509         // profile injection
510         for ( Profile activeProfile : activePomProfiles )
511         {
512             profileInjector.injectProfile( inputModel, activeProfile, request, problems );
513         }
514 
515         for ( Profile activeProfile : activeExternalProfiles )
516         {
517             profileInjector.injectProfile( inputModel, activeProfile, request, problems );
518         }
519     }
520 
521     @SuppressWarnings( "checkstyle:methodlength" )
522     private Model readEffectiveModel( final ModelBuildingRequest request, final DefaultModelBuildingResult result,
523                           DefaultModelProblemCollector problems )
524         throws ModelBuildingException
525     {
526         Model inputModel =
527             readRawModel( request, problems );
528 
529         problems.setRootModel( inputModel );
530 
531         ModelData resultData = new ModelData( request.getModelSource(), inputModel );
532         ModelData superData = new ModelData( null, getSuperModel() );
533 
534         // profile activation
535         DefaultProfileActivationContext profileActivationContext = getProfileActivationContext( request );
536 
537         List<Profile> activeExternalProfiles = result.getActiveExternalProfiles();
538 
539         if ( !activeExternalProfiles.isEmpty() )
540         {
541             Properties profileProps = new Properties();
542             for ( Profile profile : activeExternalProfiles )
543             {
544                 profileProps.putAll( profile.getProperties() );
545             }
546             profileProps.putAll( profileActivationContext.getUserProperties() );
547             profileActivationContext.setUserProperties( profileProps );
548         }
549 
550         Collection<String> parentIds = new LinkedHashSet<>();
551 
552         List<Model> lineage = new ArrayList<>();
553 
554         for ( ModelData currentData = resultData; ; )
555         {
556             String modelId = currentData.getId();
557             result.addModelId( modelId );
558 
559             Model rawModel = currentData.getModel();
560             result.setRawModel( modelId, rawModel );
561 
562             profileActivationContext.setProjectProperties( rawModel.getProperties() );
563             problems.setSource( rawModel );
564             List<Profile> activePomProfiles = profileSelector.getActiveProfiles( rawModel.getProfiles(),
565                                                                                  profileActivationContext, problems );
566             result.setActivePomProfiles( modelId, activePomProfiles );
567 
568             Model tmpModel = rawModel.clone();
569 
570             problems.setSource( tmpModel );
571 
572             // model normalization
573             tmpModel = new Model( modelNormalizer.mergeDuplicates( tmpModel.getDelegate(), request, problems ) );
574 
575             profileActivationContext.setProjectProperties( tmpModel.getProperties() );
576 
577             Map<String, Activation> interpolatedActivations = getInterpolatedActivations( rawModel,
578                                                                                           profileActivationContext,
579                                                                                           problems );
580             injectProfileActivations( tmpModel, interpolatedActivations );
581 
582             // profile injection
583             for ( Profile activeProfile : result.getActivePomProfiles( modelId ) )
584             {
585                 profileInjector.injectProfile( tmpModel, activeProfile, request, problems );
586             }
587 
588             if ( currentData == resultData )
589             {
590                 for ( Profile activeProfile : activeExternalProfiles )
591                 {
592                     profileInjector.injectProfile( tmpModel, activeProfile, request, problems );
593                 }
594                 result.setEffectiveModel( tmpModel );
595             }
596 
597             lineage.add( tmpModel );
598 
599             if ( currentData == superData )
600             {
601                 break;
602             }
603 
604             configureResolver( request.getModelResolver(), tmpModel, problems );
605 
606             ModelData parentData =
607                 readParent( currentData.getModel(), currentData.getSource(), request, result, problems );
608 
609             if ( parentData == null )
610             {
611                 currentData = superData;
612             }
613             else if ( !parentIds.add( parentData.getId() ) )
614             {
615                 StringBuilder message = new StringBuilder( "The parents form a cycle: " );
616                 for ( String parentId : parentIds )
617                 {
618                     message.append( parentId ).append( " -> " );
619                 }
620                 message.append( parentData.getId() );
621 
622                 problems.add( new ModelProblemCollectorRequest( ModelProblem.Severity.FATAL, ModelProblem.Version.BASE )
623                     .setMessage( message.toString() ) );
624 
625                 throw problems.newModelBuildingException();
626             }
627             else
628             {
629                 currentData = parentData;
630             }
631         }
632 
633         problems.setSource( result.getRawModel() );
634         checkPluginVersions( lineage, request, problems );
635 
636         // inheritance assembly
637         Model resultModel = assembleInheritance( lineage, request, problems );
638 
639         // consider caching inherited model
640 
641         problems.setSource( resultModel );
642         problems.setRootModel( resultModel );
643 
644         // model interpolation
645         resultModel = interpolateModel( resultModel, request, problems );
646 
647         // url normalization
648         modelUrlNormalizer.normalize( resultModel, request );
649 
650         result.setEffectiveModel( resultModel );
651 
652         // Now the fully interpolated model is available: reconfigure the resolver
653         configureResolver( request.getModelResolver(), resultModel, problems, true );
654 
655         return resultModel;
656     }
657 
658     private Map<String, Activation> getInterpolatedActivations( Model rawModel,
659                                                                 DefaultProfileActivationContext context,
660                                                                 DefaultModelProblemCollector problems )
661     {
662         Map<String, Activation> interpolatedActivations = getProfileActivations( rawModel, true );
663         for ( Activation activation : interpolatedActivations.values() )
664         {
665             if ( activation.getFile() != null )
666             {
667                 replaceWithInterpolatedValue( activation.getFile(), context, problems );
668             }
669         }
670         return interpolatedActivations;
671     }
672 
673     private void replaceWithInterpolatedValue( ActivationFile activationFile, ProfileActivationContext context,
674                                                DefaultModelProblemCollector problems  )
675     {
676         try
677         {
678             if ( isNotEmpty( activationFile.getExists() ) )
679             {
680                 String path = activationFile.getExists();
681                 String absolutePath = profileActivationFilePathInterpolator.interpolate( path, context );
682                 activationFile.setExists( absolutePath );
683             }
684             else if ( isNotEmpty( activationFile.getMissing() ) )
685             {
686                 String path = activationFile.getMissing();
687                 String absolutePath = profileActivationFilePathInterpolator.interpolate( path, context );
688                 activationFile.setMissing( absolutePath );
689             }
690         }
691         catch ( InterpolationException e )
692         {
693             String path = isNotEmpty(
694                     activationFile.getExists() ) ? activationFile.getExists() : activationFile.getMissing();
695 
696             problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage(
697                     "Failed to interpolate file location " + path + ": " + e.getMessage() ).setLocation(
698                     activationFile.getLocation( isNotEmpty( activationFile.getExists() ) ? "exists" : "missing"  ) )
699                     .setException( e ) );
700         }
701     }
702 
703     private static boolean isNotEmpty( String string )
704     {
705         return string != null && !string.isEmpty();
706     }
707 
708     @Override
709     public ModelBuildingResult build( final ModelBuildingRequest request, final ModelBuildingResult result )
710         throws ModelBuildingException
711     {
712         return build( request, result, new LinkedHashSet<>() );
713     }
714 
715     private ModelBuildingResult build( final ModelBuildingRequest request, final ModelBuildingResult phaseOneResult,
716                                        Collection<String> imports )
717         throws ModelBuildingException
718     {
719         DefaultModelBuildingResult result = asDefaultModelBuildingResult( phaseOneResult );
720 
721         DefaultModelProblemCollector problems = new DefaultModelProblemCollector( result );
722 
723         // phase 2
724         Model resultModel = readEffectiveModel( request, result, problems );
725         problems.setSource( resultModel );
726         problems.setRootModel( resultModel );
727 
728         // model path translation
729         modelPathTranslator.alignToBaseDirectory( resultModel, resultModel.getProjectDirectory(), request );
730 
731         // plugin management injection
732         pluginManagementInjector.injectManagement( resultModel, request, problems );
733 
734         fireEvent( resultModel, request, problems, ModelBuildingEventCatapult.BUILD_EXTENSIONS_ASSEMBLED );
735 
736         if ( request.isProcessPlugins() )
737         {
738             if ( lifecycleBindingsInjector == null )
739             {
740                 throw new IllegalStateException( "lifecycle bindings injector is missing" );
741             }
742 
743             // lifecycle bindings injection
744             lifecycleBindingsInjector.injectLifecycleBindings( resultModel, request, problems );
745         }
746 
747         // dependency management import
748         importDependencyManagement( resultModel, request, problems, imports );
749 
750         // dependency management injection
751         dependencyManagementInjector.injectManagement( resultModel, request, problems );
752 
753         resultModel.update( modelNormalizer.injectDefaultValues( resultModel.getDelegate(), request, problems ) );
754 
755         if ( request.isProcessPlugins() )
756         {
757             // reports configuration
758             reportConfigurationExpander.expandPluginConfiguration( resultModel, request, problems );
759 
760             // reports conversion to decoupled site plugin
761             reportingConverter.convertReporting( resultModel, request, problems );
762 
763             // plugins configuration
764             pluginConfigurationExpander.expandPluginConfiguration( resultModel, request, problems );
765         }
766 
767         // effective model validation
768         modelValidator.validateEffectiveModel( resultModel, request, problems );
769 
770         if ( hasModelErrors( problems ) )
771         {
772             throw problems.newModelBuildingException();
773         }
774 
775         return result;
776     }
777 
778     private DefaultModelBuildingResult asDefaultModelBuildingResult( ModelBuildingResult phaseOneResult )
779     {
780         if ( phaseOneResult instanceof DefaultModelBuildingResult )
781         {
782             return (DefaultModelBuildingResult) phaseOneResult;
783         }
784         else
785         {
786             return new DefaultModelBuildingResult( phaseOneResult );
787         }
788     }
789 
790     @Override
791     public Result<? extends Model> buildRawModel( File pomFile, int validationLevel, boolean locationTracking )
792     {
793         final ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel( validationLevel )
794             .setLocationTracking( locationTracking )
795             .setModelSource( new FileModelSource( pomFile ) );
796         final DefaultModelProblemCollector collector =
797             new DefaultModelProblemCollector( new DefaultModelBuildingResult() );
798         try
799         {
800             return newResult( readFileModel( request, collector ), collector.getProblems() );
801         }
802         catch ( ModelBuildingException e )
803         {
804             return error( collector.getProblems() );
805         }
806     }
807 
808     private Model readFileModel( ModelBuildingRequest request,
809                                  DefaultModelProblemCollector problems )
810         throws ModelBuildingException
811     {
812         ModelSource modelSource = request.getModelSource();
813         org.apache.maven.api.model.Model model = fromCache( request.getModelCache(), modelSource, ModelCacheTag.FILE );
814         if ( model == null )
815         {
816             model = doReadFileModel( modelSource, request, problems );
817 
818             intoCache( request.getModelCache(), modelSource, ModelCacheTag.FILE, model );
819         }
820 
821         if ( modelSource instanceof FileModelSource )
822         {
823             if ( request.getTransformerContextBuilder() instanceof DefaultTransformerContextBuilder )
824             {
825                 DefaultTransformerContextBuilder contextBuilder =
826                         (DefaultTransformerContextBuilder) request.getTransformerContextBuilder();
827                 contextBuilder.putSource( getGroupId( model ), model.getArtifactId(), modelSource );
828             }
829         }
830 
831         return new Model( model );
832     }
833 
834     @SuppressWarnings( "checkstyle:methodlength" )
835     private org.apache.maven.api.model.Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest request,
836                                                               DefaultModelProblemCollector problems )
837             throws ModelBuildingException
838     {
839         org.apache.maven.api.model.Model model;
840         problems.setSource( modelSource.getLocation() );
841         try
842         {
843             boolean strict = request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
844 
845             Map<String, Object> options = new HashMap<>( 3 );
846             options.put( ModelProcessor.IS_STRICT, strict );
847             options.put( ModelProcessor.SOURCE, modelSource );
848 
849             InputSource source;
850             if ( request.isLocationTracking() )
851             {
852                 source = new InputSource( null, modelSource.getLocation() );
853                 options.put( ModelProcessor.INPUT_SOURCE, source );
854             }
855             else
856             {
857                 source = null;
858             }
859 
860             try
861             {
862                 model = modelProcessor.read( modelSource.getInputStream(), options );
863             }
864             catch ( ModelParseException e )
865             {
866                 if ( !strict )
867                 {
868                     throw e;
869                 }
870 
871                 options.put( ModelProcessor.IS_STRICT, Boolean.FALSE );
872 
873                 try
874                 {
875                     model = modelProcessor.read( modelSource.getInputStream(), options );
876                 }
877                 catch ( ModelParseException ne )
878                 {
879                     // still unreadable even in non-strict mode, rethrow original error
880                     throw e;
881                 }
882 
883                 Severity severity = ( modelSource instanceof FileModelSource ) ? Severity.ERROR : Severity.WARNING;
884                 problems.add( new ModelProblemCollectorRequest( severity, Version.V20 )
885                     .setMessage( "Malformed POM " + modelSource.getLocation() + ": " + e.getMessage() )
886                     .setException( e ) );
887             }
888 
889             if ( source != null )
890             {
891                 try
892                 {
893                     Field field = InputSource.class.getDeclaredField( "modelId" );
894                     field.setAccessible( true );
895                     field.set( source, ModelProblemUtils.toId( model ) );
896                 }
897                 catch ( Throwable t )
898                 {
899                     // TODO: use a lazy source ?
900                     throw new IllegalStateException( "Unable to set modelId on InputSource", t );
901                 }
902             }
903         }
904         catch ( ModelParseException e )
905         {
906             problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
907                 .setMessage( "Non-parseable POM " + modelSource.getLocation() + ": " + e.getMessage() )
908                 .setException( e ) );
909             throw problems.newModelBuildingException();
910         }
911         catch ( IOException e )
912         {
913             String msg = e.getMessage();
914             if ( msg == null || msg.length() <= 0 )
915             {
916                 // NOTE: There's java.nio.charset.MalformedInputException and sun.io.MalformedInputException
917                 if ( e.getClass().getName().endsWith( "MalformedInputException" ) )
918                 {
919                     msg = "Some input bytes do not match the file encoding.";
920                 }
921                 else
922                 {
923                     msg = e.getClass().getSimpleName();
924                 }
925             }
926             problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
927                 .setMessage( "Non-readable POM " + modelSource.getLocation() + ": " + msg ).setException( e ) );
928             throw problems.newModelBuildingException();
929         }
930 
931         if ( modelSource instanceof FileModelSource )
932         {
933             model = model.withPomFile( ( (FileModelSource) modelSource ).getFile().toPath() );
934         }
935 
936         Model retModel = new Model( model );
937 
938         problems.setSource( retModel );
939 
940         modelValidator.validateFileModel( retModel, request, problems );
941 
942         if ( hasFatalErrors( problems ) )
943         {
944             throw problems.newModelBuildingException();
945         }
946 
947         return model;
948     }
949 
950     private Model readRawModel( ModelBuildingRequest request, DefaultModelProblemCollector problems )
951         throws ModelBuildingException
952     {
953         ModelSource modelSource = request.getModelSource();
954 
955         ModelData cachedData = fromCache( request.getModelCache(), modelSource, ModelCacheTag.RAW );
956         if ( cachedData != null )
957         {
958             return cachedData.getModel();
959         }
960 
961         Model rawModel;
962         if ( Features.buildConsumer( request.getUserProperties() ).isActive()
963             && modelSource instanceof FileModelSource )
964         {
965             rawModel = readFileModel( request, problems );
966             File pomFile = ( (FileModelSource) modelSource ).getFile();
967 
968             TransformerContext context = null;
969             if ( request.getTransformerContextBuilder() != null )
970             {
971                 context = request.getTransformerContextBuilder().initialize( request, problems );
972             }
973 
974             try
975             {
976                 // must implement TransformContext, but should use request to access system properties/modelcache
977                 org.apache.maven.api.model.Model transformedFileModel = modelProcessor.read( pomFile,
978                         Collections.singletonMap( ModelReader.TRANSFORMER_CONTEXT, context ) );
979 
980                 // rawModel with locationTrackers, required for proper feedback during validations
981 
982                 // Apply enriched data
983                 rawModel = new Model( modelMerger.merge( rawModel.getDelegate(),
984                         transformedFileModel, false, null ) );
985             }
986             catch ( IOException e )
987             {
988                 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V40 ).setException( e ) );
989             }
990         }
991         else if ( request.getFileModel() == null )
992         {
993             rawModel = readFileModel( request, problems );
994         }
995         else
996         {
997             rawModel = request.getFileModel().clone();
998         }
999 
1000         modelValidator.validateRawModel( rawModel, request, problems );
1001 
1002         if ( hasFatalErrors( problems ) )
1003         {
1004             throw problems.newModelBuildingException();
1005         }
1006 
1007         String groupId = getGroupId( rawModel );
1008         String artifactId = rawModel.getArtifactId();
1009         String version = getVersion( rawModel );
1010 
1011         ModelData modelData = new ModelData( modelSource, rawModel, groupId, artifactId, version );
1012         intoCache( request.getModelCache(), modelSource, ModelCacheTag.RAW, modelData );
1013 
1014         return rawModel;
1015     }
1016 
1017     private String getGroupId( Model model )
1018     {
1019         return getGroupId( model.getDelegate() );
1020     }
1021 
1022     private String getGroupId( org.apache.maven.api.model.Model model )
1023     {
1024         String groupId = model.getGroupId();
1025         if ( groupId == null && model.getParent() != null )
1026         {
1027             groupId = model.getParent().getGroupId();
1028         }
1029         return groupId;
1030     }
1031 
1032     private String getVersion( Model model )
1033     {
1034         String version = model.getVersion();
1035         if ( version == null && model.getParent() != null )
1036         {
1037             version = model.getParent().getVersion();
1038         }
1039         return version;
1040     }
1041 
1042     private DefaultProfileActivationContext getProfileActivationContext( ModelBuildingRequest request )
1043     {
1044         DefaultProfileActivationContext context = new DefaultProfileActivationContext();
1045 
1046         context.setActiveProfileIds( request.getActiveProfileIds() );
1047         context.setInactiveProfileIds( request.getInactiveProfileIds() );
1048         context.setSystemProperties( request.getSystemProperties() );
1049         context.setUserProperties( request.getUserProperties() );
1050         context.setProjectDirectory( ( request.getPomFile() != null ) ? request.getPomFile().getParentFile() : null );
1051 
1052         return context;
1053     }
1054 
1055     private void configureResolver( ModelResolver modelResolver, Model model, DefaultModelProblemCollector problems )
1056     {
1057         configureResolver( modelResolver, model, problems, false );
1058     }
1059 
1060     private void configureResolver( ModelResolver modelResolver, Model model, DefaultModelProblemCollector problems,
1061                                     boolean replaceRepositories )
1062     {
1063         if ( modelResolver == null )
1064         {
1065             return;
1066         }
1067 
1068         problems.setSource( model );
1069 
1070         List<Repository> repositories = model.getRepositories();
1071 
1072         for ( Repository repository : repositories )
1073         {
1074             try
1075             {
1076                 modelResolver.addRepository( repository, replaceRepositories );
1077             }
1078             catch ( InvalidRepositoryException e )
1079             {
1080                 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1081                         .setMessage( "Invalid repository " + repository.getId() + ": " + e.getMessage() )
1082                         .setLocation( repository.getLocation( "" ) ).setException( e ) );
1083             }
1084         }
1085     }
1086 
1087     private void checkPluginVersions( List<Model> lineage, ModelBuildingRequest request,
1088                                       ModelProblemCollector problems )
1089     {
1090         if ( request.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
1091         {
1092             return;
1093         }
1094 
1095         Map<String, Plugin> plugins = new HashMap<>();
1096         Map<String, String> versions = new HashMap<>();
1097         Map<String, String> managedVersions = new HashMap<>();
1098 
1099         for ( int i = lineage.size() - 1; i >= 0; i-- )
1100         {
1101             Model model = lineage.get( i );
1102             Build build = model.getBuild();
1103             if ( build != null )
1104             {
1105                 for ( Plugin plugin : build.getPlugins() )
1106                 {
1107                     String key = plugin.getKey();
1108                     if ( versions.get( key ) == null )
1109                     {
1110                         versions.put( key, plugin.getVersion() );
1111                         plugins.put( key, plugin );
1112                     }
1113                 }
1114                 PluginManagement mgmt = build.getPluginManagement();
1115                 if ( mgmt != null )
1116                 {
1117                     for ( Plugin plugin : mgmt.getPlugins() )
1118                     {
1119                         String key = plugin.getKey();
1120                         managedVersions.computeIfAbsent( key, k -> plugin.getVersion() );
1121                     }
1122                 }
1123             }
1124         }
1125 
1126         for ( String key : versions.keySet() )
1127         {
1128             if ( versions.get( key ) == null && managedVersions.get( key ) == null )
1129             {
1130                 InputLocation location = plugins.get( key ).getLocation( "" );
1131                 problems
1132                     .add( new ModelProblemCollectorRequest( Severity.WARNING, Version.V20 )
1133                         .setMessage( "'build.plugins.plugin.version' for " + key + " is missing." )
1134                         .setLocation( location ) );
1135             }
1136         }
1137     }
1138 
1139     private Model assembleInheritance( List<Model> lineage, ModelBuildingRequest request,
1140                                       ModelProblemCollector problems )
1141     {
1142         org.apache.maven.api.model.Model parent = lineage.get( lineage.size() - 1 ).getDelegate();
1143         for ( int i = lineage.size() - 2; i >= 0; i-- )
1144         {
1145             Model child = lineage.get( i );
1146             parent = inheritanceAssembler.assembleModelInheritance( child.getDelegate(), parent, request, problems );
1147         }
1148         return new Model( parent );
1149     }
1150 
1151     private Map<String, Activation> getProfileActivations( Model model, boolean clone )
1152     {
1153         Map<String, Activation> activations = new HashMap<>();
1154         for ( Profile profile : model.getProfiles() )
1155         {
1156             Activation activation = profile.getActivation();
1157 
1158             if ( activation == null )
1159             {
1160                 continue;
1161             }
1162 
1163             if ( clone )
1164             {
1165                 activation = activation.clone();
1166             }
1167 
1168             activations.put( profile.getId(), activation );
1169         }
1170 
1171         return activations;
1172     }
1173 
1174     private void injectProfileActivations( Model model, Map<String, Activation> activations )
1175     {
1176         for ( Profile profile : model.getProfiles() )
1177         {
1178             Activation activation = profile.getActivation();
1179 
1180             if ( activation == null )
1181             {
1182                 continue;
1183             }
1184 
1185             // restore activation
1186             profile.setActivation( activations.get( profile.getId() ) );
1187         }
1188     }
1189 
1190     private Model interpolateModel( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
1191     {
1192         // save profile activations before interpolation, since they are evaluated with limited scope
1193         Map<String, Activation> originalActivations = getProfileActivations( model, true );
1194 
1195         Model interpolatedModel = new Model( modelInterpolator.interpolateModel(
1196                 model.getDelegate(), model.getProjectDirectory(), request, problems ) );
1197         if ( interpolatedModel.getParent() != null )
1198         {
1199             StringSearchInterpolator ssi = new StringSearchInterpolator();
1200             ssi.addValueSource( new MapBasedValueSource( request.getUserProperties() ) );
1201 
1202             ssi.addValueSource( new MapBasedValueSource( model.getProperties() ) );
1203 
1204             ssi.addValueSource( new MapBasedValueSource( request.getSystemProperties() ) );
1205 
1206             try
1207             {
1208                 String interpolated = ssi.interpolate( interpolatedModel.getParent().getVersion() );
1209                 interpolatedModel.getParent().setVersion( interpolated );
1210             }
1211             catch ( Exception e )
1212             {
1213                 ModelProblemCollectorRequest mpcr =
1214                         new ModelProblemCollectorRequest( Severity.ERROR,
1215                                 Version.BASE ).setMessage( "Failed to interpolate field: "
1216                                 + interpolatedModel.getParent().getVersion()
1217                                 + " on class: " ).setException( e );
1218                 problems.add( mpcr );
1219             }
1220 
1221 
1222         }
1223         interpolatedModel.setPomFile( model.getPomFile() );
1224 
1225         // restore profiles with file activation to their value before full interpolation
1226         injectProfileActivations( model, originalActivations );
1227 
1228         return interpolatedModel;
1229     }
1230 
1231     private ModelData readParent( Model childModel, Source childSource, ModelBuildingRequest request,
1232                                   ModelBuildingResult result, DefaultModelProblemCollector problems )
1233         throws ModelBuildingException
1234     {
1235         ModelData parentData = null;
1236 
1237         Parent parent = childModel.getParent();
1238         if ( parent != null )
1239         {
1240             parentData = readParentLocally( childModel, childSource, request, result, problems );
1241             if ( parentData == null )
1242             {
1243                 parentData = readParentExternally( childModel, request, result, problems );
1244             }
1245 
1246             Model parentModel = parentData.getModel();
1247             if ( !"pom".equals( parentModel.getPackaging() ) )
1248             {
1249                 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1250                     .setMessage( "Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint( parentModel )
1251                                      + ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"" )
1252                     .setLocation( parentModel.getLocation( "packaging" ) ) );
1253             }
1254         }
1255 
1256         return parentData;
1257     }
1258 
1259     private ModelData readParentLocally( Model childModel, Source childSource, ModelBuildingRequest request,
1260                                          ModelBuildingResult result, DefaultModelProblemCollector problems )
1261         throws ModelBuildingException
1262     {
1263         final Parent parent = childModel.getParent();
1264         final ModelSource candidateSource;
1265         final Model candidateModel;
1266         final WorkspaceModelResolver resolver = request.getWorkspaceModelResolver();
1267         if ( resolver == null )
1268         {
1269             candidateSource = getParentPomFile( childModel, childSource );
1270 
1271             if ( candidateSource == null )
1272             {
1273                 return null;
1274             }
1275 
1276             ModelBuildingRequest candidateBuildRequest = new DefaultModelBuildingRequest( request )
1277                 .setModelSource( candidateSource );
1278 
1279             candidateModel = readRawModel( candidateBuildRequest, problems );
1280         }
1281         else
1282         {
1283             try
1284             {
1285                 candidateModel =
1286                     resolver.resolveRawModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() );
1287             }
1288             catch ( UnresolvableModelException e )
1289             {
1290                 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE ) //
1291                     .setMessage( e.getMessage() ).setLocation( parent.getLocation( "" ) ).setException( e ) );
1292                 throw problems.newModelBuildingException();
1293             }
1294             if ( candidateModel == null )
1295             {
1296                 return null;
1297             }
1298             candidateSource = new FileModelSource( candidateModel.getPomFile() );
1299         }
1300 
1301         //
1302         // TODO jvz Why isn't all this checking the job of the duty of the workspace resolver, we know that we
1303         // have a model that is suitable, yet more checks are done here and the one for the version is problematic
1304         // before because with parents as ranges it will never work in this scenario.
1305         //
1306 
1307         String groupId = getGroupId( candidateModel );
1308         String artifactId = candidateModel.getArtifactId();
1309 
1310         if ( groupId == null || !groupId.equals( parent.getGroupId() ) || artifactId == null
1311             || !artifactId.equals( parent.getArtifactId() ) )
1312         {
1313             StringBuilder buffer = new StringBuilder( 256 );
1314             buffer.append( "'parent.relativePath'" );
1315             if ( childModel != problems.getRootModel() )
1316             {
1317                 buffer.append( " of POM " ).append( ModelProblemUtils.toSourceHint( childModel ) );
1318             }
1319             buffer.append( " points at " ).append( groupId ).append( ':' ).append( artifactId );
1320             buffer.append( " instead of " ).append( parent.getGroupId() ).append( ':' );
1321             buffer.append( parent.getArtifactId() ).append( ", please verify your project structure" );
1322 
1323             problems.setSource( childModel );
1324             problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.BASE )
1325                 .setMessage( buffer.toString() ).setLocation( parent.getLocation( "" ) ) );
1326             return null;
1327         }
1328 
1329         String version = getVersion( candidateModel );
1330         if ( version != null && parent.getVersion() != null && !version.equals( parent.getVersion() ) )
1331         {
1332             try
1333             {
1334                 VersionRange parentRange = VersionRange.createFromVersionSpec( parent.getVersion() );
1335                 if ( !parentRange.hasRestrictions() )
1336                 {
1337                     // the parent version is not a range, we have version skew, drop back to resolution from repo
1338                     return null;
1339                 }
1340                 if ( !parentRange.containsVersion( new DefaultArtifactVersion( version ) ) )
1341                 {
1342                     // version skew drop back to resolution from the repository
1343                     return null;
1344                 }
1345 
1346                 // Validate versions aren't inherited when using parent ranges the same way as when read externally.
1347                 String rawChildModelVersion = childModel.getVersion();
1348                 
1349                 if ( rawChildModelVersion == null )
1350                 {
1351                     // Message below is checked for in the MNG-2199 core IT.
1352                     problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
1353                         .setMessage( "Version must be a constant" ).setLocation( childModel.getLocation( "" ) ) );
1354 
1355                 }
1356                 else
1357                 {
1358                     if ( rawChildVersionReferencesParent( rawChildModelVersion ) )
1359                     {
1360                         // Message below is checked for in the MNG-2199 core IT.
1361                         problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
1362                             .setMessage( "Version must be a constant" )
1363                             .setLocation( childModel.getLocation( "version" ) ) );
1364 
1365                     }
1366                 }
1367 
1368                 // MNG-2199: What else to check here ?
1369             }
1370             catch ( InvalidVersionSpecificationException e )
1371             {
1372                 // invalid version range, so drop back to resolution from the repository
1373                 return null;
1374             }
1375         }
1376 
1377         //
1378         // Here we just need to know that a version is fine to use but this validation we can do in our workspace
1379         // resolver.
1380         //
1381 
1382         /*
1383          * if ( version == null || !version.equals( parent.getVersion() ) ) { return null; }
1384          */
1385 
1386         return new ModelData( candidateSource, candidateModel, groupId, artifactId, version );
1387     }
1388 
1389     private boolean rawChildVersionReferencesParent( String rawChildModelVersion )
1390     {
1391         return rawChildModelVersion.equals( "${pom.version}" )
1392                 || rawChildModelVersion.equals( "${project.version}" )
1393                 || rawChildModelVersion.equals( "${pom.parent.version}" )
1394                 || rawChildModelVersion.equals( "${project.parent.version}" );
1395     }
1396 
1397     private ModelSource getParentPomFile( Model childModel, Source source )
1398     {
1399         if ( !( source instanceof ModelSource2 ) )
1400         {
1401             return null;
1402         }
1403 
1404         String parentPath = childModel.getParent().getRelativePath();
1405 
1406         if ( parentPath == null || parentPath.length() <= 0 )
1407         {
1408             return null;
1409         }
1410 
1411         return ( (ModelSource2) source ).getRelatedSource( parentPath );
1412     }
1413 
1414     private ModelData readParentExternally( Model childModel, ModelBuildingRequest request,
1415                                             ModelBuildingResult result, DefaultModelProblemCollector problems )
1416         throws ModelBuildingException
1417     {
1418         problems.setSource( childModel );
1419 
1420         Parent parent = childModel.getParent();
1421 
1422         String groupId = parent.getGroupId();
1423         String artifactId = parent.getArtifactId();
1424         String version = parent.getVersion();
1425 
1426         ModelResolver modelResolver = request.getModelResolver();
1427         Objects.requireNonNull( modelResolver,
1428                                 String.format( "request.modelResolver cannot be null (parent POM %s and POM %s)",
1429                                                ModelProblemUtils.toId( groupId, artifactId, version ),
1430                                                ModelProblemUtils.toSourceHint( childModel ) ) );
1431 
1432         ModelSource modelSource;
1433         try
1434         {
1435             modelSource = modelResolver.resolveModel( parent );
1436         }
1437         catch ( UnresolvableModelException e )
1438         {
1439             // Message below is checked for in the MNG-2199 core IT.
1440             StringBuilder buffer = new StringBuilder( 256 );
1441             buffer.append( "Non-resolvable parent POM" );
1442             if ( !containsCoordinates( e.getMessage(), groupId, artifactId, version ) )
1443             {
1444                 buffer.append( ' ' ).append( ModelProblemUtils.toId( groupId, artifactId, version ) );
1445             }
1446             if ( childModel != problems.getRootModel() )
1447             {
1448                 buffer.append( " for " ).append( ModelProblemUtils.toId( childModel ) );
1449             }
1450             buffer.append( ": " ).append( e.getMessage() );
1451             if ( childModel.getProjectDirectory() != null )
1452             {
1453                 if ( parent.getRelativePath() == null || parent.getRelativePath().length() <= 0 )
1454                 {
1455                     buffer.append( " and 'parent.relativePath' points at no local POM" );
1456                 }
1457                 else
1458                 {
1459                     buffer.append( " and 'parent.relativePath' points at wrong local POM" );
1460                 }
1461             }
1462 
1463             problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
1464                 .setMessage( buffer.toString() ).setLocation( parent.getLocation( "" ) ).setException( e ) );
1465             throw problems.newModelBuildingException();
1466         }
1467 
1468         int validationLevel = Math.min( request.getValidationLevel(), ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 );
1469         ModelBuildingRequest lenientRequest = new DefaultModelBuildingRequest( request )
1470                 .setValidationLevel( validationLevel )
1471                 .setFileModel( null )
1472                 .setModelSource( modelSource );
1473 
1474         Model parentModel = readRawModel( lenientRequest, problems );
1475 
1476         if ( !parent.getVersion().equals( version ) )
1477         {
1478             String rawChildModelVersion = childModel.getVersion();
1479             
1480             if ( rawChildModelVersion == null )
1481             {
1482                 // Message below is checked for in the MNG-2199 core IT.
1483                 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
1484                     .setMessage( "Version must be a constant" ).setLocation( childModel.getLocation( "" ) ) );
1485 
1486             }
1487             else
1488             {
1489                 if ( rawChildVersionReferencesParent( rawChildModelVersion )  )
1490                 {
1491                     // Message below is checked for in the MNG-2199 core IT.
1492                     problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 )
1493                         .setMessage( "Version must be a constant" )
1494                         .setLocation( childModel.getLocation( "version" ) ) );
1495 
1496                 }
1497             }
1498 
1499             // MNG-2199: What else to check here ?
1500         }
1501 
1502         return new ModelData( modelSource, parentModel, parent.getGroupId(), parent.getArtifactId(),
1503                               parent.getVersion() );
1504     }
1505 
1506     private Model getSuperModel()
1507     {
1508         return new Model( superPomProvider.getSuperModel( "4.0.0" ) );
1509     }
1510 
1511     private void importDependencyManagement( Model model, ModelBuildingRequest request,
1512                                              DefaultModelProblemCollector problems, Collection<String> importIds )
1513     {
1514         DependencyManagement depMgmt = model.getDependencyManagement();
1515 
1516         if ( depMgmt == null )
1517         {
1518             return;
1519         }
1520 
1521         String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion();
1522 
1523         importIds.add( importing );
1524 
1525         List<org.apache.maven.api.model.DependencyManagement> importMgmts = null;
1526 
1527         for ( Iterator<Dependency> it = depMgmt.getDependencies().iterator(); it.hasNext(); )
1528         {
1529             Dependency dependency = it.next();
1530 
1531             if ( !"pom".equals( dependency.getType() ) || !"import".equals( dependency.getScope() ) )
1532             {
1533                 continue;
1534             }
1535 
1536             it.remove();
1537 
1538             DependencyManagement importMgmt = loadDependencyManagement( model, request, problems,
1539                     dependency, importIds );
1540 
1541             if ( importMgmt != null )
1542             {
1543                 if ( importMgmts == null )
1544                 {
1545                     importMgmts = new ArrayList<>();
1546                 }
1547 
1548                 importMgmts.add( importMgmt.getDelegate() );
1549             }
1550         }
1551 
1552         importIds.remove( importing );
1553 
1554         model.update( dependencyManagementImporter.importManagement(
1555                 model.getDelegate(), importMgmts, request, problems ) );
1556     }
1557 
1558     private DependencyManagement loadDependencyManagement( Model model, ModelBuildingRequest request,
1559                                                            DefaultModelProblemCollector problems,
1560                                                            Dependency dependency,
1561                                                            Collection<String> importIds )
1562     {
1563         String groupId = dependency.getGroupId();
1564         String artifactId = dependency.getArtifactId();
1565         String version = dependency.getVersion();
1566 
1567         if ( groupId == null || groupId.length() <= 0 )
1568         {
1569             problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1570                     .setMessage( "'dependencyManagement.dependencies.dependency.groupId' for "
1571                                      + dependency.getManagementKey() + " is missing." )
1572                     .setLocation( dependency.getLocation( "" ) ) );
1573             return null;
1574         }
1575         if ( artifactId == null || artifactId.length() <= 0 )
1576         {
1577             problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1578                     .setMessage( "'dependencyManagement.dependencies.dependency.artifactId' for "
1579                                      + dependency.getManagementKey() + " is missing." )
1580                     .setLocation( dependency.getLocation( "" ) ) );
1581             return null;
1582         }
1583         if ( version == null || version.length() <= 0 )
1584         {
1585             problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1586                     .setMessage( "'dependencyManagement.dependencies.dependency.version' for "
1587                                      + dependency.getManagementKey() + " is missing." )
1588                     .setLocation( dependency.getLocation( "" ) ) );
1589             return null;
1590         }
1591 
1592         String imported = groupId + ':' + artifactId + ':' + version;
1593 
1594         if ( importIds.contains( imported ) )
1595         {
1596             StringBuilder message =
1597                     new StringBuilder( "The dependencies of type=pom and with scope=import form a cycle: " );
1598             for ( String modelId : importIds )
1599             {
1600                 message.append( modelId ).append( " -> " );
1601             }
1602             message.append( imported );
1603             problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage(
1604                     message.toString() ) );
1605 
1606             return null;
1607         }
1608 
1609         org.apache.maven.api.model.DependencyManagement importMgmt =
1610                 fromCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT );
1611         if ( importMgmt == null )
1612         {
1613             DependencyManagement importMgmtV3 = doLoadDependencyManagement( model, request, problems, dependency,
1614                     groupId, artifactId, version, importIds );
1615             if ( importMgmtV3 != null )
1616             {
1617                 importMgmt = importMgmtV3.getDelegate();
1618                 intoCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT,
1619                         importMgmt );
1620             }
1621         }
1622 
1623         return importMgmt != null ? new DependencyManagement( importMgmt ) : null;
1624     }
1625 
1626     @SuppressWarnings( "checkstyle:parameternumber" )
1627     private DependencyManagement doLoadDependencyManagement( Model model, ModelBuildingRequest request,
1628                                                              DefaultModelProblemCollector problems,
1629                                                              Dependency dependency,
1630                                                              String groupId,
1631                                                              String artifactId,
1632                                                              String version,
1633                                                              Collection<String> importIds )
1634     {
1635         DependencyManagement importMgmt;
1636         final WorkspaceModelResolver workspaceResolver = request.getWorkspaceModelResolver();
1637         final ModelResolver modelResolver = request.getModelResolver();
1638         if ( workspaceResolver == null && modelResolver == null )
1639         {
1640             throw new NullPointerException( String.format(
1641                 "request.workspaceModelResolver and request.modelResolver cannot be null (parent POM %s and POM %s)",
1642                 ModelProblemUtils.toId( groupId, artifactId, version ),
1643                 ModelProblemUtils.toSourceHint( model ) ) );
1644         }
1645 
1646         Model importModel = null;
1647         if ( workspaceResolver != null )
1648         {
1649             try
1650             {
1651                 importModel = workspaceResolver.resolveEffectiveModel( groupId, artifactId, version );
1652             }
1653             catch ( UnresolvableModelException e )
1654             {
1655                 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
1656                     .setMessage( e.getMessage() ).setException( e ) );
1657                 return null;
1658             }
1659         }
1660 
1661         // no workspace resolver or workspace resolver returned null (i.e. model not in workspace)
1662         if ( importModel == null )
1663         {
1664             final ModelSource importSource;
1665             try
1666             {
1667                 importSource = modelResolver.resolveModel( dependency );
1668             }
1669             catch ( UnresolvableModelException e )
1670             {
1671                 StringBuilder buffer = new StringBuilder( 256 );
1672                 buffer.append( "Non-resolvable import POM" );
1673                 if ( !containsCoordinates( e.getMessage(), groupId, artifactId, version ) )
1674                 {
1675                     buffer.append( ' ' ).append( ModelProblemUtils.toId( groupId, artifactId, version ) );
1676                 }
1677                 buffer.append( ": " ).append( e.getMessage() );
1678 
1679                 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1680                     .setMessage( buffer.toString() ).setLocation( dependency.getLocation( "" ) )
1681                     .setException( e ) );
1682                 return null;
1683             }
1684 
1685             final ModelBuildingResult importResult;
1686             try
1687             {
1688                 ModelBuildingRequest importRequest = new DefaultModelBuildingRequest();
1689                 importRequest.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
1690                 importRequest.setModelCache( request.getModelCache() );
1691                 importRequest.setSystemProperties( request.getSystemProperties() );
1692                 importRequest.setUserProperties( request.getUserProperties() );
1693                 importRequest.setLocationTracking( request.isLocationTracking() );
1694 
1695                 importRequest.setModelSource( importSource );
1696                 importRequest.setModelResolver( modelResolver.newCopy() );
1697 
1698                 importResult = build( importRequest, importIds );
1699             }
1700             catch ( ModelBuildingException e )
1701             {
1702                 problems.addAll( e.getProblems() );
1703                 return null;
1704             }
1705 
1706             problems.addAll( importResult.getProblems() );
1707 
1708             importModel = importResult.getEffectiveModel();
1709         }
1710 
1711         importMgmt = importModel.getDependencyManagement();
1712 
1713         if ( importMgmt == null )
1714         {
1715             importMgmt = new DependencyManagement();
1716         }
1717         return importMgmt;
1718     }
1719 
1720     private <T> void intoCache( ModelCache modelCache, String groupId, String artifactId, String version,
1721                                ModelCacheTag<T> tag, T data )
1722     {
1723         if ( modelCache != null )
1724         {
1725             modelCache.put( groupId, artifactId, version, tag, data );
1726         }
1727     }
1728 
1729     private <T> void intoCache( ModelCache modelCache, Source source, ModelCacheTag<T> tag, T data )
1730     {
1731         if ( modelCache != null )
1732         {
1733             modelCache.put( source, tag, data );
1734         }
1735     }
1736 
1737     private static <T> T fromCache( ModelCache modelCache, String groupId, String artifactId, String version,
1738                             ModelCacheTag<T> tag )
1739     {
1740         if ( modelCache != null )
1741         {
1742             return modelCache.get( groupId, artifactId, version, tag );
1743         }
1744         return null;
1745     }
1746 
1747     private static <T> T fromCache( ModelCache modelCache, Source source, ModelCacheTag<T> tag )
1748     {
1749         if ( modelCache != null )
1750         {
1751             return modelCache.get( source, tag );
1752         }
1753         return null;
1754     }
1755 
1756     private void fireEvent( Model model, ModelBuildingRequest request, ModelProblemCollector problems,
1757                             ModelBuildingEventCatapult catapult )
1758         throws ModelBuildingException
1759     {
1760         ModelBuildingListener listener = request.getModelBuildingListener();
1761 
1762         if ( listener != null )
1763         {
1764             ModelBuildingEvent event = new DefaultModelBuildingEvent( model, request, problems );
1765 
1766             catapult.fire( listener, event );
1767         }
1768     }
1769 
1770     private boolean containsCoordinates( String message, String groupId, String artifactId, String version )
1771     {
1772         return message != null && ( groupId == null || message.contains( groupId ) )
1773             && ( artifactId == null || message.contains( artifactId ) )
1774             && ( version == null || message.contains( version ) );
1775     }
1776 
1777     protected boolean hasModelErrors( ModelProblemCollectorExt problems )
1778     {
1779         if ( problems instanceof DefaultModelProblemCollector )
1780         {
1781             return ( (DefaultModelProblemCollector) problems ).hasErrors();
1782         }
1783         else
1784         {
1785             // the default execution path only knows the DefaultModelProblemCollector,
1786             // only reason it's not in signature is because it's package private
1787             throw new IllegalStateException();
1788         }
1789     }
1790 
1791     protected boolean hasFatalErrors( ModelProblemCollectorExt problems )
1792     {
1793         if ( problems instanceof DefaultModelProblemCollector )
1794         {
1795             return ( (DefaultModelProblemCollector) problems ).hasFatalErrors();
1796         }
1797         else
1798         {
1799             // the default execution path only knows the DefaultModelProblemCollector,
1800             // only reason it's not in signature is because it's package private
1801             throw new IllegalStateException();
1802         }
1803     }
1804 
1805     /**
1806      * Builds up the transformer context.
1807      * After the buildplan is ready, the build()-method returns the immutable context useful during distribution.
1808      * This is an inner class, as it must be able to call readRawModel()
1809      *
1810      * @author Robert Scholte
1811      * @since 4.0.0
1812      */
1813     private class DefaultTransformerContextBuilder implements TransformerContextBuilder
1814     {
1815         private final DefaultTransformerContext context = new DefaultTransformerContext();
1816 
1817         private final Map<DefaultTransformerContext.GAKey, Set<Source>> mappedSources
1818                 = new ConcurrentHashMap<>( 64 );
1819 
1820         /**
1821          * If an interface could be extracted, DefaultModelProblemCollector should be ModelProblemCollectorExt
1822          *
1823          * @param request
1824          * @param collector
1825          * @return
1826          */
1827         @Override
1828         public TransformerContext initialize( ModelBuildingRequest request, ModelProblemCollector collector )
1829         {
1830             // We must assume the TransformerContext was created using this.newTransformerContextBuilder()
1831             DefaultModelProblemCollector problems = (DefaultModelProblemCollector) collector;
1832             return new TransformerContext()
1833             {
1834                 @Override
1835                 public String getUserProperty( String key )
1836                 {
1837                     return context.userProperties.computeIfAbsent( key,
1838                                                            k -> request.getUserProperties().getProperty( key ) );
1839                 }
1840 
1841                 @Override
1842                 public Model getRawModel( String gId, String aId )
1843                 {
1844                     return context.modelByGA.computeIfAbsent( new DefaultTransformerContext.GAKey( gId, aId ),
1845                                                               k -> new DefaultTransformerContext.Holder() )
1846                             .computeIfAbsent( () -> findRawModel( gId, aId ) );
1847                 }
1848 
1849                 @Override
1850                 public Model getRawModel( Path path )
1851                 {
1852                     return context.modelByPath.computeIfAbsent( path,
1853                                                                 k -> new DefaultTransformerContext.Holder() )
1854                             .computeIfAbsent( () -> findRawModel( path ) );
1855                 }
1856 
1857                 private Model findRawModel( String groupId, String artifactId )
1858                 {
1859                     Source source = getSource( groupId, artifactId );
1860                     if ( source != null )
1861                     {
1862                         try
1863                         {
1864                             ModelBuildingRequest gaBuildingRequest = new DefaultModelBuildingRequest( request )
1865                                 .setModelSource( (ModelSource) source );
1866                             Model model = readRawModel( gaBuildingRequest, problems );
1867                             if ( source instanceof FileModelSource )
1868                             {
1869                                 Path path = ( ( FileModelSource ) source ).getFile().toPath();
1870                                 context.modelByPath.computeIfAbsent( path, k -> new DefaultTransformerContext.Holder() )
1871                                         .computeIfAbsent( () -> model );
1872                             }
1873                             return model;
1874                         }
1875                         catch ( ModelBuildingException e )
1876                         {
1877                             // gathered with problem collector
1878                         }
1879                     }
1880                     return null;
1881                 }
1882 
1883                 private Model findRawModel( Path p )
1884                 {
1885                     if ( !Files.isRegularFile( p ) )
1886                     {
1887                         throw new IllegalArgumentException( "Not a regular file: " + p );
1888                     }
1889 
1890                     DefaultModelBuildingRequest req = new DefaultModelBuildingRequest( request )
1891                                     .setPomFile( p.toFile() )
1892                                     .setModelSource( new FileModelSource( p.toFile() ) );
1893 
1894                     try
1895                     {
1896                         Model model = readRawModel( req, problems );
1897                         DefaultTransformerContext.GAKey key =
1898                                 new DefaultTransformerContext.GAKey( getGroupId( model ), model.getArtifactId() );
1899                         context.modelByGA.computeIfAbsent( key, k -> new DefaultTransformerContext.Holder() )
1900                                 .computeIfAbsent( () -> model );
1901                         return model;
1902                     }
1903                     catch ( ModelBuildingException e )
1904                     {
1905                         // gathered with problem collector
1906                     }
1907                     return null;
1908                 }
1909             };
1910         }
1911 
1912         @Override
1913         public TransformerContext build()
1914         {
1915             return context;
1916         }
1917 
1918         public Source getSource( String groupId, String artifactId )
1919         {
1920             Set<Source> sources = mappedSources.get( new DefaultTransformerContext.GAKey( groupId, artifactId ) );
1921             if ( sources == null )
1922             {
1923                 return null;
1924             }
1925             return sources.stream().reduce( ( a, b ) ->
1926             {
1927                 throw new IllegalStateException( String.format( "No unique Source for %s:%s: %s and %s",
1928                                                                 groupId, artifactId,
1929                                                                 a.getLocation(), b.getLocation() ) );
1930             } ).orElse( null );
1931         }
1932 
1933         public void putSource( String groupId, String artifactId, Source source )
1934         {
1935             mappedSources.computeIfAbsent( new DefaultTransformerContext.GAKey( groupId, artifactId ),
1936                     k -> new HashSet<>() ).add( source );
1937         }
1938 
1939     }
1940 }