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