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.util.ArrayList;
28  import java.util.Collection;
29  import java.util.Collections;
30  import java.util.HashMap;
31  import java.util.Iterator;
32  import java.util.LinkedHashSet;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.Objects;
36  import java.util.Optional;
37  import java.util.Properties;
38  import java.util.function.Consumer;
39  import java.util.stream.IntStream;
40  
41  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
42  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
43  import org.apache.maven.artifact.versioning.VersionRange;
44  import org.apache.maven.model.Activation;
45  import org.apache.maven.model.Build;
46  import org.apache.maven.model.Dependency;
47  import org.apache.maven.model.DependencyManagement;
48  import org.apache.maven.model.InputLocation;
49  import org.apache.maven.model.InputLocationTracker;
50  import org.apache.maven.model.InputSource;
51  import org.apache.maven.model.Model;
52  import org.apache.maven.model.Parent;
53  import org.apache.maven.model.Plugin;
54  import org.apache.maven.model.PluginManagement;
55  import org.apache.maven.model.Profile;
56  import org.apache.maven.model.Repository;
57  import org.apache.maven.model.building.ModelProblem.Severity;
58  import org.apache.maven.model.building.ModelProblem.Version;
59  import org.apache.maven.model.composition.DependencyManagementImporter;
60  import org.apache.maven.model.inheritance.InheritanceAssembler;
61  import org.apache.maven.model.interpolation.ModelInterpolator;
62  import org.apache.maven.model.io.ModelParseException;
63  import org.apache.maven.model.management.DependencyManagementInjector;
64  import org.apache.maven.model.management.PluginManagementInjector;
65  import org.apache.maven.model.normalization.ModelNormalizer;
66  import org.apache.maven.model.path.ModelPathTranslator;
67  import org.apache.maven.model.path.ModelUrlNormalizer;
68  import org.apache.maven.model.path.ProfileActivationFilePathInterpolator;
69  import org.apache.maven.model.plugin.LifecycleBindingsInjector;
70  import org.apache.maven.model.plugin.PluginConfigurationExpander;
71  import org.apache.maven.model.plugin.ReportConfigurationExpander;
72  import org.apache.maven.model.plugin.ReportingConverter;
73  import org.apache.maven.model.profile.DefaultProfileActivationContext;
74  import org.apache.maven.model.profile.ProfileActivationContext;
75  import org.apache.maven.model.profile.ProfileInjector;
76  import org.apache.maven.model.profile.ProfileSelector;
77  import org.apache.maven.model.resolution.InvalidRepositoryException;
78  import org.apache.maven.model.resolution.ModelResolver;
79  import org.apache.maven.model.resolution.UnresolvableModelException;
80  import org.apache.maven.model.resolution.WorkspaceModelResolver;
81  import org.apache.maven.model.superpom.SuperPomProvider;
82  import org.apache.maven.model.validation.ModelValidator;
83  import org.codehaus.plexus.interpolation.InterpolationException;
84  import org.codehaus.plexus.interpolation.MapBasedValueSource;
85  import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
86  import org.codehaus.plexus.interpolation.StringSearchInterpolator;
87  import org.codehaus.plexus.util.StringUtils;
88  import org.eclipse.sisu.Nullable;
89  
90  import static org.apache.maven.model.building.Result.error;
91  import static org.apache.maven.model.building.Result.newResult;
92  
93  /**
94   * @author Benjamin Bentmann
95   */
96  @Named
97  @Singleton
98  public class DefaultModelBuilder implements ModelBuilder {
99      @Inject
100     private ModelProcessor modelProcessor;
101 
102     @Inject
103     private ModelValidator modelValidator;
104 
105     @Inject
106     private ModelNormalizer modelNormalizer;
107 
108     @Inject
109     private ModelInterpolator modelInterpolator;
110 
111     @Inject
112     private ModelPathTranslator modelPathTranslator;
113 
114     @Inject
115     private ModelUrlNormalizer modelUrlNormalizer;
116 
117     @Inject
118     private SuperPomProvider superPomProvider;
119 
120     @Inject
121     private InheritanceAssembler inheritanceAssembler;
122 
123     @Inject
124     private ProfileSelector profileSelector;
125 
126     @Inject
127     private ProfileInjector profileInjector;
128 
129     @Inject
130     private PluginManagementInjector pluginManagementInjector;
131 
132     @Inject
133     private DependencyManagementInjector dependencyManagementInjector;
134 
135     @Inject
136     private DependencyManagementImporter dependencyManagementImporter;
137 
138     @Inject
139     @Nullable
140     private LifecycleBindingsInjector lifecycleBindingsInjector;
141 
142     @Inject
143     private PluginConfigurationExpander pluginConfigurationExpander;
144 
145     @Inject
146     private ReportConfigurationExpander reportConfigurationExpander;
147 
148     @Inject
149     private ReportingConverter reportingConverter;
150 
151     @Inject
152     private ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator;
153 
154     public DefaultModelBuilder setModelProcessor(ModelProcessor modelProcessor) {
155         this.modelProcessor = modelProcessor;
156         return this;
157     }
158 
159     public DefaultModelBuilder setModelValidator(ModelValidator modelValidator) {
160         this.modelValidator = modelValidator;
161         return this;
162     }
163 
164     public DefaultModelBuilder setModelNormalizer(ModelNormalizer modelNormalizer) {
165         this.modelNormalizer = modelNormalizer;
166         return this;
167     }
168 
169     public DefaultModelBuilder setModelInterpolator(ModelInterpolator modelInterpolator) {
170         this.modelInterpolator = modelInterpolator;
171         return this;
172     }
173 
174     public DefaultModelBuilder setModelPathTranslator(ModelPathTranslator modelPathTranslator) {
175         this.modelPathTranslator = modelPathTranslator;
176         return this;
177     }
178 
179     public DefaultModelBuilder setModelUrlNormalizer(ModelUrlNormalizer modelUrlNormalizer) {
180         this.modelUrlNormalizer = modelUrlNormalizer;
181         return this;
182     }
183 
184     public DefaultModelBuilder setSuperPomProvider(SuperPomProvider superPomProvider) {
185         this.superPomProvider = superPomProvider;
186         return this;
187     }
188 
189     public DefaultModelBuilder setProfileSelector(ProfileSelector profileSelector) {
190         this.profileSelector = profileSelector;
191         return this;
192     }
193 
194     public DefaultModelBuilder setProfileInjector(ProfileInjector profileInjector) {
195         this.profileInjector = profileInjector;
196         return this;
197     }
198 
199     public DefaultModelBuilder setInheritanceAssembler(InheritanceAssembler inheritanceAssembler) {
200         this.inheritanceAssembler = inheritanceAssembler;
201         return this;
202     }
203 
204     public DefaultModelBuilder setDependencyManagementImporter(DependencyManagementImporter depMgmtImporter) {
205         this.dependencyManagementImporter = depMgmtImporter;
206         return this;
207     }
208 
209     public DefaultModelBuilder setDependencyManagementInjector(DependencyManagementInjector depMgmtInjector) {
210         this.dependencyManagementInjector = depMgmtInjector;
211         return this;
212     }
213 
214     public DefaultModelBuilder setLifecycleBindingsInjector(LifecycleBindingsInjector lifecycleBindingsInjector) {
215         this.lifecycleBindingsInjector = lifecycleBindingsInjector;
216         return this;
217     }
218 
219     public DefaultModelBuilder setPluginConfigurationExpander(PluginConfigurationExpander pluginConfigurationExpander) {
220         this.pluginConfigurationExpander = pluginConfigurationExpander;
221         return this;
222     }
223 
224     public DefaultModelBuilder setPluginManagementInjector(PluginManagementInjector pluginManagementInjector) {
225         this.pluginManagementInjector = pluginManagementInjector;
226         return this;
227     }
228 
229     public DefaultModelBuilder setReportConfigurationExpander(ReportConfigurationExpander reportConfigurationExpander) {
230         this.reportConfigurationExpander = reportConfigurationExpander;
231         return this;
232     }
233 
234     public DefaultModelBuilder setReportingConverter(ReportingConverter reportingConverter) {
235         this.reportingConverter = reportingConverter;
236         return this;
237     }
238 
239     public DefaultModelBuilder setProfileActivationFilePathInterpolator(
240             ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator) {
241         this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator;
242         return this;
243     }
244 
245     @SuppressWarnings("checkstyle:methodlength")
246     @Override
247     public ModelBuildingResult build(ModelBuildingRequest request) throws ModelBuildingException {
248         return build(request, new LinkedHashSet<String>());
249     }
250 
251     @SuppressWarnings("checkstyle:methodlength")
252     protected ModelBuildingResult build(ModelBuildingRequest request, Collection<String> importIds)
253             throws ModelBuildingException {
254         // phase 1
255         DefaultModelBuildingResult result = new DefaultModelBuildingResult();
256 
257         DefaultModelProblemCollector problems = new DefaultModelProblemCollector(result);
258 
259         // read and validate raw model
260         Model inputModel = request.getRawModel();
261         if (inputModel == null) {
262             inputModel = readModel(request.getModelSource(), request.getPomFile(), request, problems);
263         }
264 
265         // profile activation
266         DefaultProfileActivationContext profileActivationContext = getProfileActivationContext(request, inputModel);
267 
268         problems.setSource("(external profiles)");
269         List<Profile> activeExternalProfiles =
270                 profileSelector.getActiveProfiles(request.getProfiles(), profileActivationContext, problems);
271 
272         result.setActiveExternalProfiles(activeExternalProfiles);
273 
274         if (!activeExternalProfiles.isEmpty()) {
275             Properties profileProps = new Properties();
276             for (Profile profile : activeExternalProfiles) {
277                 profileProps.putAll(profile.getProperties());
278             }
279             profileProps.putAll(profileActivationContext.getUserProperties());
280             profileActivationContext.setUserProperties(profileProps);
281         }
282 
283         problems.setRootModel(inputModel);
284 
285         ModelData resultData = new ModelData(request.getModelSource(), inputModel);
286         ModelData superData = new ModelData(null, getSuperModel());
287 
288         Collection<String> parentIds = new LinkedHashSet<>();
289         List<ModelData> lineage = new ArrayList<>();
290 
291         for (ModelData currentData = resultData; currentData != null; ) {
292             lineage.add(currentData);
293 
294             Model rawModel = currentData.getModel();
295             currentData.setRawModel(rawModel);
296 
297             Model tmpModel = rawModel.clone();
298             currentData.setModel(tmpModel);
299 
300             problems.setSource(tmpModel);
301 
302             // model normalization
303             modelNormalizer.mergeDuplicates(tmpModel, request, problems);
304 
305             profileActivationContext.setProjectProperties(tmpModel.getProperties());
306 
307             List<Profile> interpolatedProfiles = getInterpolatedProfiles(rawModel, profileActivationContext, problems);
308             tmpModel.setProfiles(interpolatedProfiles);
309 
310             List<Profile> activePomProfiles =
311                     profileSelector.getActiveProfiles(tmpModel.getProfiles(), profileActivationContext, problems);
312 
313             List<Profile> rawProfiles = new ArrayList<>();
314             for (Profile activePomProfile : activePomProfiles) {
315                 rawProfiles.add(rawModel.getProfiles().get(interpolatedProfiles.indexOf(activePomProfile)));
316             }
317             currentData.setActiveProfiles(rawProfiles);
318 
319             // profile injection
320             for (Profile activeProfile : activePomProfiles) {
321                 profileInjector.injectProfile(tmpModel, activeProfile, request, problems);
322             }
323 
324             if (currentData == resultData) {
325                 for (Profile activeProfile : activeExternalProfiles) {
326                     profileInjector.injectProfile(tmpModel, activeProfile, request, problems);
327                 }
328             }
329 
330             if (currentData == superData) {
331                 break;
332             }
333 
334             configureResolver(request.getModelResolver(), tmpModel, problems);
335 
336             ModelData parentData = readParent(tmpModel, currentData.getSource(), request, problems);
337 
338             if (parentData == null) {
339                 currentData = superData;
340             } else if (currentData == resultData) { // First iteration - add initial id after version resolution.
341                 currentData.setGroupId(
342                         currentData.getRawModel().getGroupId() == null
343                                 ? parentData.getGroupId()
344                                 : currentData.getRawModel().getGroupId());
345 
346                 currentData.setVersion(
347                         currentData.getRawModel().getVersion() == null
348                                 ? parentData.getVersion()
349                                 : currentData.getRawModel().getVersion());
350 
351                 currentData.setArtifactId(currentData.getRawModel().getArtifactId());
352                 parentIds.add(currentData.getId());
353                 // Reset - only needed for 'getId'.
354                 currentData.setGroupId(null);
355                 currentData.setArtifactId(null);
356                 currentData.setVersion(null);
357                 currentData = parentData;
358             } else if (!parentIds.add(parentData.getId())) {
359                 String message = "The parents form a cycle: ";
360                 for (String modelId : parentIds) {
361                     message += modelId + " -> ";
362                 }
363                 message += parentData.getId();
364 
365                 problems.add(new ModelProblemCollectorRequest(ModelProblem.Severity.FATAL, ModelProblem.Version.BASE)
366                         .setMessage(message));
367 
368                 throw problems.newModelBuildingException();
369             } else {
370                 currentData = parentData;
371             }
372         }
373 
374         problems.setSource(inputModel);
375         checkPluginVersions(lineage, request, problems);
376 
377         // inheritance assembly
378         assembleInheritance(lineage, request, problems);
379 
380         Model resultModel = resultData.getModel();
381 
382         problems.setSource(resultModel);
383         problems.setRootModel(resultModel);
384 
385         // model interpolation
386         resultModel = interpolateModel(resultModel, request, problems);
387         resultData.setModel(resultModel);
388 
389         if (resultModel.getParent() != null) {
390             final ModelData parentData = lineage.get(1);
391             if (parentData.getVersion() == null || parentData.getVersion().contains("${")) {
392                 final Model interpolatedParent = interpolateModel(parentData.getModel(), request, problems);
393                 // parentData.setModel( interpolatedParent );
394                 parentData.setVersion(interpolatedParent.getVersion());
395             }
396         }
397 
398         // url normalization
399         modelUrlNormalizer.normalize(resultModel, request);
400 
401         // Now the fully interpolated model is available: reconfigure the resolver
402         configureResolver(request.getModelResolver(), resultModel, problems, true);
403 
404         resultData.setGroupId(resultModel.getGroupId());
405         resultData.setArtifactId(resultModel.getArtifactId());
406         resultData.setVersion(resultModel.getVersion());
407 
408         result.setEffectiveModel(resultModel);
409 
410         for (ModelData currentData : lineage) {
411             String modelId = (currentData != superData) ? currentData.getId() : "";
412 
413             result.addModelId(modelId);
414             result.setActivePomProfiles(modelId, currentData.getActiveProfiles());
415             result.setRawModel(modelId, currentData.getRawModel());
416         }
417 
418         if (!request.isTwoPhaseBuilding()) {
419             build(request, result, importIds);
420         }
421 
422         return result;
423     }
424 
425     @FunctionalInterface
426     private interface InterpolateString {
427         String apply(String s) throws InterpolationException;
428     }
429 
430     private List<Profile> getInterpolatedProfiles(
431             Model rawModel, DefaultProfileActivationContext context, DefaultModelProblemCollector problems) {
432         List<Profile> interpolatedActivations = getProfiles(rawModel, true);
433 
434         if (interpolatedActivations.isEmpty()) {
435             return Collections.emptyList();
436         }
437         RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
438 
439         interpolator.addValueSource(new MapBasedValueSource(context.getProjectProperties()));
440         interpolator.addValueSource(new MapBasedValueSource(context.getUserProperties()));
441         interpolator.addValueSource(new MapBasedValueSource(context.getSystemProperties()));
442 
443         class Interpolation {
444             final InputLocationTracker target;
445 
446             final InterpolateString impl;
447 
448             Interpolation(InputLocationTracker target, InterpolateString impl) {
449                 this.target = target;
450                 this.impl = impl;
451             }
452 
453             void performFor(String value, String locationKey, Consumer<String> mutator) {
454                 if (StringUtils.isEmpty(value)) {
455                     return;
456                 }
457                 try {
458                     mutator.accept(impl.apply(value));
459                 } catch (InterpolationException e) {
460                     problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
461                             .setMessage("Failed to interpolate value " + value + ": " + e.getMessage())
462                             .setLocation(target.getLocation(locationKey))
463                             .setException(e));
464                 }
465             }
466         }
467         for (Profile profile : interpolatedActivations) {
468             Activation activation = profile.getActivation();
469             Optional<Activation> a = Optional.ofNullable(activation);
470             a.map(Activation::getFile).ifPresent(fa -> {
471                 Interpolation nt =
472                         new Interpolation(fa, s -> profileActivationFilePathInterpolator.interpolate(s, context));
473                 nt.performFor(fa.getExists(), "exists", fa::setExists);
474                 nt.performFor(fa.getMissing(), "missing", fa::setMissing);
475             });
476             a.map(Activation::getOs).ifPresent(oa -> {
477                 Interpolation nt = new Interpolation(oa, interpolator::interpolate);
478                 nt.performFor(oa.getArch(), "arch", oa::setArch);
479                 nt.performFor(oa.getFamily(), "family", oa::setFamily);
480                 nt.performFor(oa.getName(), "name", oa::setName);
481                 nt.performFor(oa.getVersion(), "version", oa::setVersion);
482             });
483             a.map(Activation::getProperty).ifPresent(pa -> {
484                 Interpolation nt = new Interpolation(pa, interpolator::interpolate);
485                 nt.performFor(pa.getName(), "name", pa::setName);
486                 nt.performFor(pa.getValue(), "value", pa::setValue);
487             });
488             a.map(Activation::getJdk)
489                     .ifPresent(ja -> new Interpolation(activation, interpolator::interpolate)
490                             .performFor(ja, "jdk", activation::setJdk));
491         }
492         return interpolatedActivations;
493     }
494 
495     @Override
496     public ModelBuildingResult build(ModelBuildingRequest request, ModelBuildingResult result)
497             throws ModelBuildingException {
498         return build(request, result, new LinkedHashSet<String>());
499     }
500 
501     private ModelBuildingResult build(
502             ModelBuildingRequest request, ModelBuildingResult result, Collection<String> imports)
503             throws ModelBuildingException {
504         // phase 2
505         Model resultModel = result.getEffectiveModel();
506 
507         DefaultModelProblemCollector problems = new DefaultModelProblemCollector(result);
508         problems.setSource(resultModel);
509         problems.setRootModel(resultModel);
510 
511         // model path translation
512         modelPathTranslator.alignToBaseDirectory(resultModel, resultModel.getProjectDirectory(), request);
513 
514         // plugin management injection
515         pluginManagementInjector.injectManagement(resultModel, request, problems);
516 
517         fireEvent(resultModel, request, problems, ModelBuildingEventCatapult.BUILD_EXTENSIONS_ASSEMBLED);
518 
519         if (request.isProcessPlugins()) {
520             if (lifecycleBindingsInjector == null) {
521                 throw new IllegalStateException("lifecycle bindings injector is missing");
522             }
523 
524             // lifecycle bindings injection
525             lifecycleBindingsInjector.injectLifecycleBindings(resultModel, request, problems);
526         }
527 
528         // dependency management import
529         importDependencyManagement(resultModel, request, problems, imports);
530 
531         // dependency management injection
532         dependencyManagementInjector.injectManagement(resultModel, request, problems);
533 
534         modelNormalizer.injectDefaultValues(resultModel, request, problems);
535 
536         if (request.isProcessPlugins()) {
537             // reports configuration
538             reportConfigurationExpander.expandPluginConfiguration(resultModel, request, problems);
539 
540             // reports conversion to decoupled site plugin
541             reportingConverter.convertReporting(resultModel, request, problems);
542 
543             // plugins configuration
544             pluginConfigurationExpander.expandPluginConfiguration(resultModel, request, problems);
545         }
546 
547         // effective model validation
548         modelValidator.validateEffectiveModel(resultModel, request, problems);
549 
550         if (hasModelErrors(problems)) {
551             throw problems.newModelBuildingException();
552         }
553 
554         return result;
555     }
556 
557     @Override
558     public Result<? extends Model> buildRawModel(File pomFile, int validationLevel, boolean locationTracking) {
559         final ModelBuildingRequest request = new DefaultModelBuildingRequest()
560                 .setValidationLevel(validationLevel)
561                 .setLocationTracking(locationTracking);
562         final DefaultModelProblemCollector collector =
563                 new DefaultModelProblemCollector(new DefaultModelBuildingResult());
564         try {
565             return newResult(readModel(null, pomFile, request, collector), collector.getProblems());
566         } catch (ModelBuildingException e) {
567             return error(collector.getProblems());
568         }
569     }
570 
571     private Model readModel(
572             ModelSource modelSource, File pomFile, ModelBuildingRequest request, DefaultModelProblemCollector problems)
573             throws ModelBuildingException {
574         Model model;
575 
576         if (modelSource == null) {
577             if (pomFile != null) {
578                 modelSource = new FileModelSource(pomFile);
579             } else {
580                 throw new NullPointerException("neither pomFile nor modelSource can be null");
581             }
582         }
583 
584         problems.setSource(modelSource.getLocation());
585         try {
586             boolean strict = request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
587             InputSource source = request.isLocationTracking() ? new InputSource() : null;
588 
589             Map<String, Object> options = new HashMap<>();
590             options.put(ModelProcessor.IS_STRICT, strict);
591             options.put(ModelProcessor.INPUT_SOURCE, source);
592             options.put(ModelProcessor.SOURCE, modelSource);
593 
594             try {
595                 model = modelProcessor.read(modelSource.getInputStream(), options);
596             } catch (ModelParseException e) {
597                 if (!strict) {
598                     throw e;
599                 }
600 
601                 options.put(ModelProcessor.IS_STRICT, Boolean.FALSE);
602 
603                 try {
604                     model = modelProcessor.read(modelSource.getInputStream(), options);
605                 } catch (ModelParseException ne) {
606                     // still unreadable even in non-strict mode, rethrow original error
607                     throw e;
608                 }
609 
610                 if (pomFile != null) {
611                     problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.V20)
612                             .setMessage("Malformed POM " + modelSource.getLocation() + ": " + e.getMessage())
613                             .setException(e));
614                 } else {
615                     problems.add(new ModelProblemCollectorRequest(Severity.WARNING, Version.V20)
616                             .setMessage("Malformed POM " + modelSource.getLocation() + ": " + e.getMessage())
617                             .setException(e));
618                 }
619             }
620 
621             if (source != null) {
622                 source.setModelId(ModelProblemUtils.toId(model));
623                 source.setLocation(modelSource.getLocation());
624             }
625         } catch (ModelParseException e) {
626             problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.BASE)
627                     .setMessage("Non-parseable POM " + modelSource.getLocation() + ": " + e.getMessage())
628                     .setException(e));
629             throw problems.newModelBuildingException();
630         } catch (IOException e) {
631             String msg = e.getMessage();
632             if (msg == null || msg.length() <= 0) {
633                 // NOTE: There's java.nio.charset.MalformedInputException and sun.io.MalformedInputException
634                 if (e.getClass().getName().endsWith("MalformedInputException")) {
635                     msg = "Some input bytes do not match the file encoding.";
636                 } else {
637                     msg = e.getClass().getSimpleName();
638                 }
639             }
640             problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.BASE)
641                     .setMessage("Non-readable POM " + modelSource.getLocation() + ": " + msg)
642                     .setException(e));
643             throw problems.newModelBuildingException();
644         }
645 
646         model.setPomFile(pomFile);
647 
648         problems.setSource(model);
649         modelValidator.validateRawModel(model, request, problems);
650 
651         if (hasFatalErrors(problems)) {
652             throw problems.newModelBuildingException();
653         }
654 
655         return model;
656     }
657 
658     private DefaultProfileActivationContext getProfileActivationContext(ModelBuildingRequest request, Model rawModel) {
659         DefaultProfileActivationContext context = new DefaultProfileActivationContext();
660 
661         context.setActiveProfileIds(request.getActiveProfileIds());
662         context.setInactiveProfileIds(request.getInactiveProfileIds());
663         context.setSystemProperties(request.getSystemProperties());
664         // enrich user properties with project packaging
665         Properties userProperties = request.getUserProperties();
666         userProperties.computeIfAbsent(
667                 (Object) ProfileActivationContext.PROPERTY_NAME_PACKAGING, (p) -> (Object) rawModel.getPackaging());
668         context.setUserProperties(userProperties);
669         context.setProjectDirectory(
670                 (request.getPomFile() != null) ? request.getPomFile().getParentFile() : null);
671 
672         return context;
673     }
674 
675     private void configureResolver(ModelResolver modelResolver, Model model, DefaultModelProblemCollector problems) {
676         configureResolver(modelResolver, model, problems, false);
677     }
678 
679     private void configureResolver(
680             ModelResolver modelResolver,
681             Model model,
682             DefaultModelProblemCollector problems,
683             boolean replaceRepositories) {
684         if (modelResolver == null) {
685             return;
686         }
687 
688         problems.setSource(model);
689 
690         List<Repository> repositories = model.getRepositories();
691 
692         for (Repository repository : repositories) {
693             try {
694                 modelResolver.addRepository(repository, replaceRepositories);
695             } catch (InvalidRepositoryException e) {
696                 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
697                         .setMessage("Invalid repository " + repository.getId() + ": " + e.getMessage())
698                         .setLocation(repository.getLocation(""))
699                         .setException(e));
700             }
701         }
702     }
703 
704     private void checkPluginVersions(
705             List<ModelData> lineage, ModelBuildingRequest request, ModelProblemCollector problems) {
706         if (request.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
707             return;
708         }
709 
710         Map<String, Plugin> plugins = new HashMap<>();
711         Map<String, String> versions = new HashMap<>();
712         Map<String, String> managedVersions = new HashMap<>();
713 
714         for (int i = lineage.size() - 1; i >= 0; i--) {
715             Model model = lineage.get(i).getModel();
716             Build build = model.getBuild();
717             if (build != null) {
718                 for (Plugin plugin : build.getPlugins()) {
719                     String key = plugin.getKey();
720                     if (versions.get(key) == null) {
721                         versions.put(key, plugin.getVersion());
722                         plugins.put(key, plugin);
723                     }
724                 }
725                 PluginManagement mgmt = build.getPluginManagement();
726                 if (mgmt != null) {
727                     for (Plugin plugin : mgmt.getPlugins()) {
728                         String key = plugin.getKey();
729                         if (managedVersions.get(key) == null) {
730                             managedVersions.put(key, plugin.getVersion());
731                         }
732                     }
733                 }
734             }
735         }
736 
737         for (String key : versions.keySet()) {
738             if (versions.get(key) == null && managedVersions.get(key) == null) {
739                 InputLocation location = plugins.get(key).getLocation("");
740                 problems.add(new ModelProblemCollectorRequest(Severity.WARNING, Version.V20)
741                         .setMessage("'build.plugins.plugin.version' for " + key + " is missing.")
742                         .setLocation(location));
743             }
744         }
745     }
746 
747     private void assembleInheritance(
748             List<ModelData> lineage, ModelBuildingRequest request, ModelProblemCollector problems) {
749         for (int i = lineage.size() - 2; i >= 0; i--) {
750             Model parent = lineage.get(i + 1).getModel();
751             Model child = lineage.get(i).getModel();
752             inheritanceAssembler.assembleModelInheritance(child, parent, request, problems);
753         }
754     }
755 
756     private List<Profile> getProfiles(Model model, boolean clone) {
757         ArrayList<Profile> profiles = new ArrayList<>();
758         for (Profile profile : model.getProfiles()) {
759             if (clone) {
760                 profile = profile.clone();
761             }
762             profiles.add(profile);
763         }
764         return profiles;
765     }
766 
767     private Model interpolateModel(Model model, ModelBuildingRequest request, ModelProblemCollector problems) {
768         // save profile activations before interpolation, since they are evaluated with limited scope
769         List<Profile> originalProfiles = getProfiles(model, true);
770 
771         Model interpolatedModel =
772                 modelInterpolator.interpolateModel(model, model.getProjectDirectory(), request, problems);
773         if (interpolatedModel.getParent() != null) {
774             StringSearchInterpolator ssi = new StringSearchInterpolator();
775             ssi.addValueSource(new MapBasedValueSource(request.getUserProperties()));
776 
777             ssi.addValueSource(new MapBasedValueSource(model.getProperties()));
778 
779             ssi.addValueSource(new MapBasedValueSource(request.getSystemProperties()));
780 
781             try {
782                 String interpolated =
783                         ssi.interpolate(interpolatedModel.getParent().getVersion());
784                 interpolatedModel.getParent().setVersion(interpolated);
785             } catch (Exception e) {
786                 ModelProblemCollectorRequest mpcr = new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
787                         .setMessage("Failed to interpolate field: "
788                                 + interpolatedModel.getParent().getVersion()
789                                 + " on class: ")
790                         .setException(e);
791                 problems.add(mpcr);
792             }
793         }
794         interpolatedModel.setPomFile(model.getPomFile());
795 
796         // restore profiles with any activation to their value before full interpolation
797         List<Profile> interpolatedProfiles = model.getProfiles();
798         IntStream.range(0, interpolatedProfiles.size())
799                 .forEach(i -> interpolatedProfiles
800                         .get(i)
801                         .setActivation(originalProfiles.get(i).getActivation()));
802 
803         return interpolatedModel;
804     }
805 
806     private ModelData readParent(
807             Model childModel,
808             ModelSource childSource,
809             ModelBuildingRequest request,
810             DefaultModelProblemCollector problems)
811             throws ModelBuildingException {
812         ModelData parentData;
813 
814         Parent parent = childModel.getParent();
815 
816         if (parent != null) {
817             String groupId = parent.getGroupId();
818             String artifactId = parent.getArtifactId();
819             String version = parent.getVersion();
820 
821             parentData = getCache(request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW);
822 
823             if (parentData == null) {
824                 parentData = readParentLocally(childModel, childSource, request, problems);
825 
826                 if (parentData == null) {
827                     parentData = readParentExternally(childModel, request, problems);
828                 }
829 
830                 putCache(request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW, parentData);
831             } else {
832                 /*
833                  * NOTE: This is a sanity check of the cache hit. If the cached parent POM was locally resolved, the
834                  * child's <relativePath> should point at that parent, too. If it doesn't, we ignore the cache and
835                  * resolve externally, to mimic the behavior if the cache didn't exist in the first place. Otherwise,
836                  * the cache would obscure a bad POM.
837                  */
838 
839                 File pomFile = parentData.getModel().getPomFile();
840                 if (pomFile != null) {
841                     FileModelSource pomSource = new FileModelSource(pomFile);
842                     ModelSource expectedParentSource = getParentPomFile(childModel, childSource);
843 
844                     if (expectedParentSource == null
845                             || (expectedParentSource instanceof ModelSource2
846                                     && !pomSource.equals(expectedParentSource))) {
847                         parentData = readParentExternally(childModel, request, problems);
848                     }
849                 }
850             }
851 
852             Model parentModel = parentData.getModel();
853 
854             if (!"pom".equals(parentModel.getPackaging())) {
855                 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
856                         .setMessage("Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint(parentModel)
857                                 + ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"")
858                         .setLocation(parentModel.getLocation("packaging")));
859             }
860         } else {
861             parentData = null;
862         }
863 
864         return parentData;
865     }
866 
867     private ModelData readParentLocally(
868             Model childModel,
869             ModelSource childSource,
870             ModelBuildingRequest request,
871             DefaultModelProblemCollector problems)
872             throws ModelBuildingException {
873         final Parent parent = childModel.getParent();
874         final ModelSource candidateSource;
875         final Model candidateModel;
876         final WorkspaceModelResolver resolver = request.getWorkspaceModelResolver();
877         if (resolver == null) {
878             candidateSource = getParentPomFile(childModel, childSource);
879 
880             if (candidateSource == null) {
881                 return null;
882             }
883 
884             File pomFile = null;
885             if (candidateSource instanceof FileModelSource) {
886                 pomFile = ((FileModelSource) candidateSource).getPomFile();
887             }
888 
889             candidateModel = readModel(candidateSource, pomFile, request, problems);
890         } else {
891             try {
892                 candidateModel =
893                         resolver.resolveRawModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion());
894             } catch (UnresolvableModelException e) {
895                 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.BASE) //
896                         .setMessage(e.getMessage().toString())
897                         .setLocation(parent.getLocation(""))
898                         .setException(e));
899                 throw problems.newModelBuildingException();
900             }
901             if (candidateModel == null) {
902                 return null;
903             }
904             candidateSource = new FileModelSource(candidateModel.getPomFile());
905         }
906 
907         //
908         // TODO jvz Why isn't all this checking the job of the duty of the workspace resolver, we know that we
909         // have a model that is suitable, yet more checks are done here and the one for the version is problematic
910         // before because with parents as ranges it will never work in this scenario.
911         //
912 
913         String groupId = candidateModel.getGroupId();
914         if (groupId == null && candidateModel.getParent() != null) {
915             groupId = candidateModel.getParent().getGroupId();
916         }
917         String artifactId = candidateModel.getArtifactId();
918         String version = candidateModel.getVersion();
919         if (version == null && candidateModel.getParent() != null) {
920             version = candidateModel.getParent().getVersion();
921         }
922 
923         if (groupId == null
924                 || !groupId.equals(parent.getGroupId())
925                 || artifactId == null
926                 || !artifactId.equals(parent.getArtifactId())) {
927             StringBuilder buffer = new StringBuilder(256);
928             buffer.append("'parent.relativePath'");
929             if (childModel != problems.getRootModel()) {
930                 buffer.append(" of POM ").append(ModelProblemUtils.toSourceHint(childModel));
931             }
932             buffer.append(" points at ").append(groupId).append(':').append(artifactId);
933             buffer.append(" instead of ").append(parent.getGroupId()).append(':');
934             buffer.append(parent.getArtifactId()).append(", please verify your project structure");
935 
936             problems.setSource(childModel);
937             problems.add(new ModelProblemCollectorRequest(Severity.WARNING, Version.BASE)
938                     .setMessage(buffer.toString())
939                     .setLocation(parent.getLocation("")));
940             return null;
941         }
942         if (version != null && parent.getVersion() != null && !version.equals(parent.getVersion())) {
943             try {
944                 VersionRange parentRange = VersionRange.createFromVersionSpec(parent.getVersion());
945                 if (!parentRange.hasRestrictions()) {
946                     // the parent version is not a range, we have version skew, drop back to resolution from repo
947                     return null;
948                 }
949                 if (!parentRange.containsVersion(new DefaultArtifactVersion(version))) {
950                     // version skew drop back to resolution from the repository
951                     return null;
952                 }
953 
954                 // Validate versions aren't inherited when using parent ranges the same way as when read externally.
955                 String rawChildModelVersion = childModel.getVersion();
956 
957                 if (rawChildModelVersion == null) {
958                     // Message below is checked for in the MNG-2199 core IT.
959                     problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.V31)
960                             .setMessage("Version must be a constant")
961                             .setLocation(childModel.getLocation("")));
962 
963                 } else {
964                     if (rawChildVersionReferencesParent(rawChildModelVersion)) {
965                         // Message below is checked for in the MNG-2199 core IT.
966                         problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.V31)
967                                 .setMessage("Version must be a constant")
968                                 .setLocation(childModel.getLocation("version")));
969                     }
970                 }
971 
972                 // MNG-2199: What else to check here ?
973             } catch (InvalidVersionSpecificationException e) {
974                 // invalid version range, so drop back to resolution from the repository
975                 return null;
976             }
977         }
978 
979         //
980         // Here we just need to know that a version is fine to use but this validation we can do in our workspace
981         // resolver.
982         //
983 
984         /*
985          * if ( version == null || !version.equals( parent.getVersion() ) ) { return null; }
986          */
987 
988         ModelData parentData = new ModelData(candidateSource, candidateModel, groupId, artifactId, version);
989 
990         return parentData;
991     }
992 
993     private boolean rawChildVersionReferencesParent(String rawChildModelVersion) {
994         return rawChildModelVersion.equals("${pom.version}")
995                 || rawChildModelVersion.equals("${project.version}")
996                 || rawChildModelVersion.equals("${pom.parent.version}")
997                 || rawChildModelVersion.equals("${project.parent.version}");
998     }
999 
1000     private ModelSource getParentPomFile(Model childModel, ModelSource source) {
1001         if (!(source instanceof ModelSource2)) {
1002             return null;
1003         }
1004 
1005         String parentPath = childModel.getParent().getRelativePath();
1006 
1007         if (parentPath == null || parentPath.length() <= 0) {
1008             return null;
1009         }
1010 
1011         return ((ModelSource2) source).getRelatedSource(parentPath);
1012     }
1013 
1014     private ModelData readParentExternally(
1015             Model childModel, ModelBuildingRequest request, DefaultModelProblemCollector problems)
1016             throws ModelBuildingException {
1017         problems.setSource(childModel);
1018 
1019         Parent parent = childModel.getParent().clone();
1020 
1021         String groupId = parent.getGroupId();
1022         String artifactId = parent.getArtifactId();
1023         String version = parent.getVersion();
1024 
1025         ModelResolver modelResolver = request.getModelResolver();
1026         Objects.requireNonNull(
1027                 modelResolver,
1028                 String.format(
1029                         "request.modelResolver cannot be null (parent POM %s and POM %s)",
1030                         ModelProblemUtils.toId(groupId, artifactId, version),
1031                         ModelProblemUtils.toSourceHint(childModel)));
1032 
1033         ModelSource modelSource;
1034         try {
1035             modelSource = modelResolver.resolveModel(parent);
1036         } catch (UnresolvableModelException e) {
1037             // Message below is checked for in the MNG-2199 core IT.
1038             StringBuilder buffer = new StringBuilder(256);
1039             buffer.append("Non-resolvable parent POM");
1040             if (!containsCoordinates(e.getMessage(), groupId, artifactId, version)) {
1041                 buffer.append(' ').append(ModelProblemUtils.toId(groupId, artifactId, version));
1042             }
1043             if (childModel != problems.getRootModel()) {
1044                 buffer.append(" for ").append(ModelProblemUtils.toId(childModel));
1045             }
1046             buffer.append(": ").append(e.getMessage());
1047             if (childModel.getProjectDirectory() != null) {
1048                 if (parent.getRelativePath() == null || parent.getRelativePath().length() <= 0) {
1049                     buffer.append(" and 'parent.relativePath' points at no local POM");
1050                 } else {
1051                     buffer.append(" and 'parent.relativePath' points at wrong local POM");
1052                 }
1053             }
1054 
1055             problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.BASE)
1056                     .setMessage(buffer.toString())
1057                     .setLocation(parent.getLocation(""))
1058                     .setException(e));
1059             throw problems.newModelBuildingException();
1060         }
1061 
1062         ModelBuildingRequest lenientRequest = request;
1063         if (request.getValidationLevel() > ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
1064             lenientRequest = new FilterModelBuildingRequest(request) {
1065                 @Override
1066                 public int getValidationLevel() {
1067                     return ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
1068                 }
1069             };
1070         }
1071 
1072         Model parentModel = readModel(modelSource, null, lenientRequest, problems);
1073 
1074         if (!parent.getVersion().equals(version)) {
1075             String rawChildModelVersion = childModel.getVersion();
1076 
1077             if (rawChildModelVersion == null) {
1078                 // Message below is checked for in the MNG-2199 core IT.
1079                 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.V31)
1080                         .setMessage("Version must be a constant")
1081                         .setLocation(childModel.getLocation("")));
1082 
1083             } else {
1084                 if (rawChildVersionReferencesParent(rawChildModelVersion)) {
1085                     // Message below is checked for in the MNG-2199 core IT.
1086                     problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.V31)
1087                             .setMessage("Version must be a constant")
1088                             .setLocation(childModel.getLocation("version")));
1089                 }
1090             }
1091 
1092             // MNG-2199: What else to check here ?
1093         }
1094 
1095         ModelData parentData = new ModelData(
1096                 modelSource, parentModel, parent.getGroupId(), parent.getArtifactId(), parent.getVersion());
1097 
1098         return parentData;
1099     }
1100 
1101     private Model getSuperModel() {
1102         return superPomProvider.getSuperModel("4.0.0").clone();
1103     }
1104 
1105     @SuppressWarnings("checkstyle:methodlength")
1106     private void importDependencyManagement(
1107             Model model,
1108             ModelBuildingRequest request,
1109             DefaultModelProblemCollector problems,
1110             Collection<String> importIds) {
1111         DependencyManagement depMgmt = model.getDependencyManagement();
1112 
1113         if (depMgmt == null) {
1114             return;
1115         }
1116 
1117         String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion();
1118 
1119         importIds.add(importing);
1120 
1121         final WorkspaceModelResolver workspaceResolver = request.getWorkspaceModelResolver();
1122         final ModelResolver modelResolver = request.getModelResolver();
1123 
1124         ModelBuildingRequest importRequest = null;
1125 
1126         List<DependencyManagement> importMgmts = null;
1127 
1128         for (Iterator<Dependency> it = depMgmt.getDependencies().iterator(); it.hasNext(); ) {
1129             Dependency dependency = it.next();
1130 
1131             if (!"pom".equals(dependency.getType()) || !"import".equals(dependency.getScope())) {
1132                 continue;
1133             }
1134 
1135             it.remove();
1136 
1137             String groupId = dependency.getGroupId();
1138             String artifactId = dependency.getArtifactId();
1139             String version = dependency.getVersion();
1140 
1141             if (groupId == null || groupId.length() <= 0) {
1142                 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
1143                         .setMessage("'dependencyManagement.dependencies.dependency.groupId' for "
1144                                 + dependency.getManagementKey() + " is missing.")
1145                         .setLocation(dependency.getLocation("")));
1146                 continue;
1147             }
1148             if (artifactId == null || artifactId.length() <= 0) {
1149                 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
1150                         .setMessage("'dependencyManagement.dependencies.dependency.artifactId' for "
1151                                 + dependency.getManagementKey() + " is missing.")
1152                         .setLocation(dependency.getLocation("")));
1153                 continue;
1154             }
1155             if (version == null || version.length() <= 0) {
1156                 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
1157                         .setMessage("'dependencyManagement.dependencies.dependency.version' for "
1158                                 + dependency.getManagementKey() + " is missing.")
1159                         .setLocation(dependency.getLocation("")));
1160                 continue;
1161             }
1162 
1163             String imported = groupId + ':' + artifactId + ':' + version;
1164 
1165             if (importIds.contains(imported)) {
1166                 String message = "The dependencies of type=pom and with scope=import form a cycle: ";
1167                 for (String modelId : importIds) {
1168                     message += modelId + " -> ";
1169                 }
1170                 message += imported;
1171                 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE).setMessage(message));
1172 
1173                 continue;
1174             }
1175 
1176             DependencyManagement importMgmt =
1177                     getCache(request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT);
1178 
1179             if (importMgmt == null) {
1180                 if (workspaceResolver == null && modelResolver == null) {
1181                     throw new NullPointerException(String.format(
1182                             "request.workspaceModelResolver and request.modelResolver cannot be null"
1183                                     + " (parent POM %s and POM %s)",
1184                             ModelProblemUtils.toId(groupId, artifactId, version),
1185                             ModelProblemUtils.toSourceHint(model)));
1186                 }
1187 
1188                 Model importModel = null;
1189                 if (workspaceResolver != null) {
1190                     try {
1191                         importModel = workspaceResolver.resolveEffectiveModel(groupId, artifactId, version);
1192                     } catch (UnresolvableModelException e) {
1193                         problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.BASE)
1194                                 .setMessage(e.getMessage().toString())
1195                                 .setException(e));
1196                         continue;
1197                     }
1198                 }
1199 
1200                 // no workspace resolver or workspace resolver returned null (i.e. model not in workspace)
1201                 if (importModel == null) {
1202                     final ModelSource importSource;
1203                     try {
1204                         importSource = modelResolver.resolveModel(groupId, artifactId, version);
1205                     } catch (UnresolvableModelException e) {
1206                         StringBuilder buffer = new StringBuilder(256);
1207                         buffer.append("Non-resolvable import POM");
1208                         if (!containsCoordinates(e.getMessage(), groupId, artifactId, version)) {
1209                             buffer.append(' ').append(ModelProblemUtils.toId(groupId, artifactId, version));
1210                         }
1211                         buffer.append(": ").append(e.getMessage());
1212 
1213                         problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
1214                                 .setMessage(buffer.toString())
1215                                 .setLocation(dependency.getLocation(""))
1216                                 .setException(e));
1217                         continue;
1218                     }
1219 
1220                     if (importRequest == null) {
1221                         importRequest = new DefaultModelBuildingRequest();
1222                         importRequest.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
1223                         importRequest.setModelCache(request.getModelCache());
1224                         importRequest.setSystemProperties(request.getSystemProperties());
1225                         importRequest.setUserProperties(request.getUserProperties());
1226                         importRequest.setLocationTracking(request.isLocationTracking());
1227                     }
1228 
1229                     importRequest.setModelSource(importSource);
1230                     importRequest.setModelResolver(modelResolver.newCopy());
1231 
1232                     final ModelBuildingResult importResult;
1233                     try {
1234                         importResult = build(importRequest, importIds);
1235                     } catch (ModelBuildingException e) {
1236                         problems.addAll(e.getProblems());
1237                         continue;
1238                     }
1239 
1240                     problems.addAll(importResult.getProblems());
1241 
1242                     importModel = importResult.getEffectiveModel();
1243                 }
1244 
1245                 importMgmt = importModel.getDependencyManagement();
1246 
1247                 if (importMgmt == null) {
1248                     importMgmt = new DependencyManagement();
1249                 }
1250 
1251                 putCache(request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, importMgmt);
1252             }
1253 
1254             if (importMgmts == null) {
1255                 importMgmts = new ArrayList<>();
1256             }
1257 
1258             importMgmts.add(importMgmt);
1259         }
1260 
1261         importIds.remove(importing);
1262 
1263         dependencyManagementImporter.importManagement(model, importMgmts, request, problems);
1264     }
1265 
1266     private <T> void putCache(
1267             ModelCache modelCache, String groupId, String artifactId, String version, ModelCacheTag<T> tag, T data) {
1268         if (modelCache != null) {
1269             modelCache.put(groupId, artifactId, version, tag.getName(), tag.intoCache(data));
1270         }
1271     }
1272 
1273     private <T> T getCache(
1274             ModelCache modelCache, String groupId, String artifactId, String version, ModelCacheTag<T> tag) {
1275         if (modelCache != null) {
1276             Object data = modelCache.get(groupId, artifactId, version, tag.getName());
1277             if (data != null) {
1278                 return tag.fromCache(tag.getType().cast(data));
1279             }
1280         }
1281         return null;
1282     }
1283 
1284     private void fireEvent(
1285             Model model,
1286             ModelBuildingRequest request,
1287             ModelProblemCollector problems,
1288             ModelBuildingEventCatapult catapult)
1289             throws ModelBuildingException {
1290         ModelBuildingListener listener = request.getModelBuildingListener();
1291 
1292         if (listener != null) {
1293             ModelBuildingEvent event = new DefaultModelBuildingEvent(model, request, problems);
1294 
1295             catapult.fire(listener, event);
1296         }
1297     }
1298 
1299     private boolean containsCoordinates(String message, String groupId, String artifactId, String version) {
1300         return message != null
1301                 && (groupId == null || message.contains(groupId))
1302                 && (artifactId == null || message.contains(artifactId))
1303                 && (version == null || message.contains(version));
1304     }
1305 
1306     protected boolean hasModelErrors(ModelProblemCollectorExt problems) {
1307         if (problems instanceof DefaultModelProblemCollector) {
1308             return ((DefaultModelProblemCollector) problems).hasErrors();
1309         } else {
1310             // the default execution path only knows the DefaultModelProblemCollector,
1311             // only reason it's not in signature is because it's package private
1312             throw new IllegalStateException();
1313         }
1314     }
1315 
1316     protected boolean hasFatalErrors(ModelProblemCollectorExt problems) {
1317         if (problems instanceof DefaultModelProblemCollector) {
1318             return ((DefaultModelProblemCollector) problems).hasFatalErrors();
1319         } else {
1320             // the default execution path only knows the DefaultModelProblemCollector,
1321             // only reason it's not in signature is because it's package private
1322             throw new IllegalStateException();
1323         }
1324     }
1325 }