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