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