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