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).ifPresent(ja -> new Interpolation(activation, interpolator::interpolate)
489                     .performFor(ja, "jdk", activation::setJdk));
490         }
491         return interpolatedActivations;
492     }
493 
494     @Override
495     public ModelBuildingResult build(ModelBuildingRequest request, ModelBuildingResult result)
496             throws ModelBuildingException {
497         return build(request, result, new LinkedHashSet<String>());
498     }
499 
500     private ModelBuildingResult build(
501             ModelBuildingRequest request, ModelBuildingResult result, Collection<String> imports)
502             throws ModelBuildingException {
503         // phase 2
504         Model resultModel = result.getEffectiveModel();
505 
506         DefaultModelProblemCollector problems = new DefaultModelProblemCollector(result);
507         problems.setSource(resultModel);
508         problems.setRootModel(resultModel);
509 
510         // model path translation
511         modelPathTranslator.alignToBaseDirectory(resultModel, resultModel.getProjectDirectory(), request);
512 
513         // plugin management injection
514         pluginManagementInjector.injectManagement(resultModel, request, problems);
515 
516         fireEvent(resultModel, request, problems, ModelBuildingEventCatapult.BUILD_EXTENSIONS_ASSEMBLED);
517 
518         if (request.isProcessPlugins()) {
519             if (lifecycleBindingsInjector == null) {
520                 throw new IllegalStateException("lifecycle bindings injector is missing");
521             }
522 
523             // lifecycle bindings injection
524             lifecycleBindingsInjector.injectLifecycleBindings(resultModel, request, problems);
525         }
526 
527         // dependency management import
528         importDependencyManagement(resultModel, request, problems, imports);
529 
530         // dependency management injection
531         dependencyManagementInjector.injectManagement(resultModel, request, problems);
532 
533         modelNormalizer.injectDefaultValues(resultModel, request, problems);
534 
535         if (request.isProcessPlugins()) {
536             // reports configuration
537             reportConfigurationExpander.expandPluginConfiguration(resultModel, request, problems);
538 
539             // reports conversion to decoupled site plugin
540             reportingConverter.convertReporting(resultModel, request, problems);
541 
542             // plugins configuration
543             pluginConfigurationExpander.expandPluginConfiguration(resultModel, request, problems);
544         }
545 
546         // effective model validation
547         modelValidator.validateEffectiveModel(resultModel, request, problems);
548 
549         if (hasModelErrors(problems)) {
550             throw problems.newModelBuildingException();
551         }
552 
553         return result;
554     }
555 
556     @Override
557     public Result<? extends Model> buildRawModel(File pomFile, int validationLevel, boolean locationTracking) {
558         final ModelBuildingRequest request = new DefaultModelBuildingRequest()
559                 .setValidationLevel(validationLevel)
560                 .setLocationTracking(locationTracking);
561         final DefaultModelProblemCollector collector =
562                 new DefaultModelProblemCollector(new DefaultModelBuildingResult());
563         try {
564             return newResult(readModel(null, pomFile, request, collector), collector.getProblems());
565         } catch (ModelBuildingException e) {
566             return error(collector.getProblems());
567         }
568     }
569 
570     private Model readModel(
571             ModelSource modelSource, File pomFile, ModelBuildingRequest request, DefaultModelProblemCollector problems)
572             throws ModelBuildingException {
573         Model model;
574 
575         if (modelSource == null) {
576             if (pomFile != null) {
577                 modelSource = new FileModelSource(pomFile);
578             } else {
579                 throw new NullPointerException("neither pomFile nor modelSource can be null");
580             }
581         }
582 
583         problems.setSource(modelSource.getLocation());
584         try {
585             boolean strict = request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
586             InputSource source = request.isLocationTracking() ? new InputSource() : null;
587 
588             Map<String, Object> options = new HashMap<>();
589             options.put(ModelProcessor.IS_STRICT, strict);
590             options.put(ModelProcessor.INPUT_SOURCE, source);
591             options.put(ModelProcessor.SOURCE, modelSource);
592 
593             try {
594                 model = modelProcessor.read(modelSource.getInputStream(), options);
595             } catch (ModelParseException e) {
596                 if (!strict) {
597                     throw e;
598                 }
599 
600                 options.put(ModelProcessor.IS_STRICT, Boolean.FALSE);
601 
602                 try {
603                     model = modelProcessor.read(modelSource.getInputStream(), options);
604                 } catch (ModelParseException ne) {
605                     // still unreadable even in non-strict mode, rethrow original error
606                     throw e;
607                 }
608 
609                 if (pomFile != null) {
610                     problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.V20)
611                             .setMessage("Malformed POM " + modelSource.getLocation() + ": " + e.getMessage())
612                             .setException(e));
613                 } else {
614                     problems.add(new ModelProblemCollectorRequest(Severity.WARNING, Version.V20)
615                             .setMessage("Malformed POM " + modelSource.getLocation() + ": " + e.getMessage())
616                             .setException(e));
617                 }
618             }
619 
620             if (source != null) {
621                 source.setModelId(ModelProblemUtils.toId(model));
622                 source.setLocation(modelSource.getLocation());
623             }
624         } catch (ModelParseException e) {
625             problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.BASE)
626                     .setMessage("Non-parseable POM " + modelSource.getLocation() + ": " + e.getMessage())
627                     .setException(e));
628             throw problems.newModelBuildingException();
629         } catch (IOException e) {
630             String msg = e.getMessage();
631             if (msg == null || msg.length() <= 0) {
632                 // NOTE: There's java.nio.charset.MalformedInputException and sun.io.MalformedInputException
633                 if (e.getClass().getName().endsWith("MalformedInputException")) {
634                     msg = "Some input bytes do not match the file encoding.";
635                 } else {
636                     msg = e.getClass().getSimpleName();
637                 }
638             }
639             problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.BASE)
640                     .setMessage("Non-readable POM " + modelSource.getLocation() + ": " + msg)
641                     .setException(e));
642             throw problems.newModelBuildingException();
643         }
644 
645         model.setPomFile(pomFile);
646 
647         problems.setSource(model);
648         modelValidator.validateRawModel(model, request, problems);
649 
650         if (hasFatalErrors(problems)) {
651             throw problems.newModelBuildingException();
652         }
653 
654         return model;
655     }
656 
657     private DefaultProfileActivationContext getProfileActivationContext(ModelBuildingRequest request, Model rawModel) {
658         DefaultProfileActivationContext context = new DefaultProfileActivationContext();
659 
660         context.setActiveProfileIds(request.getActiveProfileIds());
661         context.setInactiveProfileIds(request.getInactiveProfileIds());
662         context.setSystemProperties(request.getSystemProperties());
663         // enrich user properties with project packaging
664         Properties userProperties = request.getUserProperties();
665         userProperties.computeIfAbsent(
666                 (Object) ProfileActivationContext.PROPERTY_NAME_PACKAGING, (p) -> (Object) rawModel.getPackaging());
667         context.setUserProperties(userProperties);
668         context.setProjectDirectory(
669                 (request.getPomFile() != null) ? request.getPomFile().getParentFile() : null);
670 
671         return context;
672     }
673 
674     private void configureResolver(ModelResolver modelResolver, Model model, DefaultModelProblemCollector problems) {
675         configureResolver(modelResolver, model, problems, false);
676     }
677 
678     private void configureResolver(
679             ModelResolver modelResolver,
680             Model model,
681             DefaultModelProblemCollector problems,
682             boolean replaceRepositories) {
683         if (modelResolver == null) {
684             return;
685         }
686 
687         problems.setSource(model);
688 
689         List<Repository> repositories = model.getRepositories();
690 
691         for (Repository repository : repositories) {
692             try {
693                 modelResolver.addRepository(repository, replaceRepositories);
694             } catch (InvalidRepositoryException e) {
695                 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
696                         .setMessage("Invalid repository " + repository.getId() + ": " + e.getMessage())
697                         .setLocation(repository.getLocation(""))
698                         .setException(e));
699             }
700         }
701     }
702 
703     private void checkPluginVersions(
704             List<ModelData> lineage, ModelBuildingRequest request, ModelProblemCollector problems) {
705         if (request.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
706             return;
707         }
708 
709         Map<String, Plugin> plugins = new HashMap<>();
710         Map<String, String> versions = new HashMap<>();
711         Map<String, String> managedVersions = new HashMap<>();
712 
713         for (int i = lineage.size() - 1; i >= 0; i--) {
714             Model model = lineage.get(i).getModel();
715             Build build = model.getBuild();
716             if (build != null) {
717                 for (Plugin plugin : build.getPlugins()) {
718                     String key = plugin.getKey();
719                     if (versions.get(key) == null) {
720                         versions.put(key, plugin.getVersion());
721                         plugins.put(key, plugin);
722                     }
723                 }
724                 PluginManagement mgmt = build.getPluginManagement();
725                 if (mgmt != null) {
726                     for (Plugin plugin : mgmt.getPlugins()) {
727                         String key = plugin.getKey();
728                         if (managedVersions.get(key) == null) {
729                             managedVersions.put(key, plugin.getVersion());
730                         }
731                     }
732                 }
733             }
734         }
735 
736         for (String key : versions.keySet()) {
737             if (versions.get(key) == null && managedVersions.get(key) == null) {
738                 InputLocation location = plugins.get(key).getLocation("");
739                 problems.add(new ModelProblemCollectorRequest(Severity.WARNING, Version.V20)
740                         .setMessage("'build.plugins.plugin.version' for " + key + " is missing.")
741                         .setLocation(location));
742             }
743         }
744     }
745 
746     private void assembleInheritance(
747             List<ModelData> lineage, ModelBuildingRequest request, ModelProblemCollector problems) {
748         for (int i = lineage.size() - 2; i >= 0; i--) {
749             Model parent = lineage.get(i + 1).getModel();
750             Model child = lineage.get(i).getModel();
751             inheritanceAssembler.assembleModelInheritance(child, parent, request, problems);
752         }
753     }
754 
755     private List<Profile> getProfiles(Model model, boolean clone) {
756         ArrayList<Profile> profiles = new ArrayList<>();
757         for (Profile profile : model.getProfiles()) {
758             if (clone) {
759                 profile = profile.clone();
760             }
761             profiles.add(profile);
762         }
763         return profiles;
764     }
765 
766     private Model interpolateModel(Model model, ModelBuildingRequest request, ModelProblemCollector problems) {
767         // save profile activations before interpolation, since they are evaluated with limited scope
768         List<Profile> originalProfiles = getProfiles(model, true);
769 
770         Model interpolatedModel =
771                 modelInterpolator.interpolateModel(model, model.getProjectDirectory(), request, problems);
772         if (interpolatedModel.getParent() != null) {
773             StringSearchInterpolator ssi = new StringSearchInterpolator();
774             ssi.addValueSource(new MapBasedValueSource(request.getUserProperties()));
775 
776             ssi.addValueSource(new MapBasedValueSource(model.getProperties()));
777 
778             ssi.addValueSource(new MapBasedValueSource(request.getSystemProperties()));
779 
780             try {
781                 String interpolated =
782                         ssi.interpolate(interpolatedModel.getParent().getVersion());
783                 interpolatedModel.getParent().setVersion(interpolated);
784             } catch (Exception e) {
785                 ModelProblemCollectorRequest mpcr = new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
786                         .setMessage("Failed to interpolate field: "
787                                 + interpolatedModel.getParent().getVersion()
788                                 + " on class: ")
789                         .setException(e);
790                 problems.add(mpcr);
791             }
792         }
793         interpolatedModel.setPomFile(model.getPomFile());
794 
795         // restore profiles with any activation to their value before full interpolation
796         List<Profile> interpolatedProfiles = model.getProfiles();
797         IntStream.range(0, interpolatedProfiles.size()).forEach(i -> interpolatedProfiles
798                 .get(i)
799                 .setActivation(originalProfiles.get(i).getActivation()));
800 
801         return interpolatedModel;
802     }
803 
804     private ModelData readParent(
805             Model childModel,
806             ModelSource childSource,
807             ModelBuildingRequest request,
808             DefaultModelProblemCollector problems)
809             throws ModelBuildingException {
810         ModelData parentData;
811 
812         Parent parent = childModel.getParent();
813 
814         if (parent != null) {
815             String groupId = parent.getGroupId();
816             String artifactId = parent.getArtifactId();
817             String version = parent.getVersion();
818 
819             parentData = getCache(request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW);
820 
821             if (parentData == null) {
822                 parentData = readParentLocally(childModel, childSource, request, problems);
823 
824                 if (parentData == null) {
825                     parentData = readParentExternally(childModel, request, problems);
826                 }
827 
828                 putCache(request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW, parentData);
829             } else {
830                 /*
831                  * NOTE: This is a sanity check of the cache hit. If the cached parent POM was locally resolved, the
832                  * child's <relativePath> should point at that parent, too. If it doesn't, we ignore the cache and
833                  * resolve externally, to mimic the behavior if the cache didn't exist in the first place. Otherwise,
834                  * the cache would obscure a bad POM.
835                  */
836 
837                 File pomFile = parentData.getModel().getPomFile();
838                 if (pomFile != null) {
839                     FileModelSource pomSource = new FileModelSource(pomFile);
840                     ModelSource expectedParentSource = getParentPomFile(childModel, childSource);
841 
842                     if (expectedParentSource == null
843                             || (expectedParentSource instanceof ModelSource2
844                                     && !pomSource.equals(expectedParentSource))) {
845                         parentData = readParentExternally(childModel, request, problems);
846                     }
847                 }
848             }
849 
850             Model parentModel = parentData.getModel();
851 
852             if (!"pom".equals(parentModel.getPackaging())) {
853                 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
854                         .setMessage("Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint(parentModel)
855                                 + ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"")
856                         .setLocation(parentModel.getLocation("packaging")));
857             }
858         } else {
859             parentData = null;
860         }
861 
862         return parentData;
863     }
864 
865     private ModelData readParentLocally(
866             Model childModel,
867             ModelSource childSource,
868             ModelBuildingRequest request,
869             DefaultModelProblemCollector problems)
870             throws ModelBuildingException {
871         final Parent parent = childModel.getParent();
872         final ModelSource candidateSource;
873         final Model candidateModel;
874         final WorkspaceModelResolver resolver = request.getWorkspaceModelResolver();
875         if (resolver == null) {
876             candidateSource = getParentPomFile(childModel, childSource);
877 
878             if (candidateSource == null) {
879                 return null;
880             }
881 
882             File pomFile = null;
883             if (candidateSource instanceof FileModelSource) {
884                 pomFile = ((FileModelSource) candidateSource).getPomFile();
885             }
886 
887             candidateModel = readModel(candidateSource, pomFile, request, problems);
888         } else {
889             try {
890                 candidateModel =
891                         resolver.resolveRawModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion());
892             } catch (UnresolvableModelException e) {
893                 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.BASE) //
894                         .setMessage(e.getMessage().toString())
895                         .setLocation(parent.getLocation(""))
896                         .setException(e));
897                 throw problems.newModelBuildingException();
898             }
899             if (candidateModel == null) {
900                 return null;
901             }
902             candidateSource = new FileModelSource(candidateModel.getPomFile());
903         }
904 
905         //
906         // TODO jvz Why isn't all this checking the job of the duty of the workspace resolver, we know that we
907         // have a model that is suitable, yet more checks are done here and the one for the version is problematic
908         // before because with parents as ranges it will never work in this scenario.
909         //
910 
911         String groupId = candidateModel.getGroupId();
912         if (groupId == null && candidateModel.getParent() != null) {
913             groupId = candidateModel.getParent().getGroupId();
914         }
915         String artifactId = candidateModel.getArtifactId();
916         String version = candidateModel.getVersion();
917         if (version == null && candidateModel.getParent() != null) {
918             version = candidateModel.getParent().getVersion();
919         }
920 
921         if (groupId == null
922                 || !groupId.equals(parent.getGroupId())
923                 || artifactId == null
924                 || !artifactId.equals(parent.getArtifactId())) {
925             StringBuilder buffer = new StringBuilder(256);
926             buffer.append("'parent.relativePath'");
927             if (childModel != problems.getRootModel()) {
928                 buffer.append(" of POM ").append(ModelProblemUtils.toSourceHint(childModel));
929             }
930             buffer.append(" points at ").append(groupId).append(':').append(artifactId);
931             buffer.append(" instead of ").append(parent.getGroupId()).append(':');
932             buffer.append(parent.getArtifactId()).append(", please verify your project structure");
933 
934             problems.setSource(childModel);
935             problems.add(new ModelProblemCollectorRequest(Severity.WARNING, Version.BASE)
936                     .setMessage(buffer.toString())
937                     .setLocation(parent.getLocation("")));
938             return null;
939         }
940         if (version != null && parent.getVersion() != null && !version.equals(parent.getVersion())) {
941             try {
942                 VersionRange parentRange = VersionRange.createFromVersionSpec(parent.getVersion());
943                 if (!parentRange.hasRestrictions()) {
944                     // the parent version is not a range, we have version skew, drop back to resolution from repo
945                     return null;
946                 }
947                 if (!parentRange.containsVersion(new DefaultArtifactVersion(version))) {
948                     // version skew drop back to resolution from the repository
949                     return null;
950                 }
951 
952                 // Validate versions aren't inherited when using parent ranges the same way as when read externally.
953                 String rawChildModelVersion = childModel.getVersion();
954 
955                 if (rawChildModelVersion == null) {
956                     // Message below is checked for in the MNG-2199 core IT.
957                     problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.V31)
958                             .setMessage("Version must be a constant")
959                             .setLocation(childModel.getLocation("")));
960 
961                 } else {
962                     if (rawChildVersionReferencesParent(rawChildModelVersion)) {
963                         // Message below is checked for in the MNG-2199 core IT.
964                         problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.V31)
965                                 .setMessage("Version must be a constant")
966                                 .setLocation(childModel.getLocation("version")));
967                     }
968                 }
969 
970                 // MNG-2199: What else to check here ?
971             } catch (InvalidVersionSpecificationException e) {
972                 // invalid version range, so drop back to resolution from the repository
973                 return null;
974             }
975         }
976 
977         //
978         // Here we just need to know that a version is fine to use but this validation we can do in our workspace
979         // resolver.
980         //
981 
982         /*
983          * if ( version == null || !version.equals( parent.getVersion() ) ) { return null; }
984          */
985 
986         ModelData parentData = new ModelData(candidateSource, candidateModel, groupId, artifactId, version);
987 
988         return parentData;
989     }
990 
991     private boolean rawChildVersionReferencesParent(String rawChildModelVersion) {
992         return rawChildModelVersion.equals("${pom.version}")
993                 || rawChildModelVersion.equals("${project.version}")
994                 || rawChildModelVersion.equals("${pom.parent.version}")
995                 || rawChildModelVersion.equals("${project.parent.version}");
996     }
997 
998     private ModelSource getParentPomFile(Model childModel, ModelSource source) {
999         if (!(source instanceof ModelSource2)) {
1000             return null;
1001         }
1002 
1003         String parentPath = childModel.getParent().getRelativePath();
1004 
1005         if (parentPath == null || parentPath.length() <= 0) {
1006             return null;
1007         }
1008 
1009         return ((ModelSource2) source).getRelatedSource(parentPath);
1010     }
1011 
1012     private ModelData readParentExternally(
1013             Model childModel, ModelBuildingRequest request, DefaultModelProblemCollector problems)
1014             throws ModelBuildingException {
1015         problems.setSource(childModel);
1016 
1017         Parent parent = childModel.getParent().clone();
1018 
1019         String groupId = parent.getGroupId();
1020         String artifactId = parent.getArtifactId();
1021         String version = parent.getVersion();
1022 
1023         ModelResolver modelResolver = request.getModelResolver();
1024         Objects.requireNonNull(
1025                 modelResolver,
1026                 String.format(
1027                         "request.modelResolver cannot be null (parent POM %s and POM %s)",
1028                         ModelProblemUtils.toId(groupId, artifactId, version),
1029                         ModelProblemUtils.toSourceHint(childModel)));
1030 
1031         ModelSource modelSource;
1032         try {
1033             modelSource = modelResolver.resolveModel(parent);
1034         } catch (UnresolvableModelException e) {
1035             // Message below is checked for in the MNG-2199 core IT.
1036             StringBuilder buffer = new StringBuilder(256);
1037             buffer.append("Non-resolvable parent POM");
1038             if (!containsCoordinates(e.getMessage(), groupId, artifactId, version)) {
1039                 buffer.append(' ').append(ModelProblemUtils.toId(groupId, artifactId, version));
1040             }
1041             if (childModel != problems.getRootModel()) {
1042                 buffer.append(" for ").append(ModelProblemUtils.toId(childModel));
1043             }
1044             buffer.append(": ").append(e.getMessage());
1045             if (childModel.getProjectDirectory() != null) {
1046                 if (parent.getRelativePath() == null || parent.getRelativePath().length() <= 0) {
1047                     buffer.append(" and 'parent.relativePath' points at no local POM");
1048                 } else {
1049                     buffer.append(" and 'parent.relativePath' points at wrong local POM");
1050                 }
1051             }
1052 
1053             problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.BASE)
1054                     .setMessage(buffer.toString())
1055                     .setLocation(parent.getLocation(""))
1056                     .setException(e));
1057             throw problems.newModelBuildingException();
1058         }
1059 
1060         ModelBuildingRequest lenientRequest = request;
1061         if (request.getValidationLevel() > ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0) {
1062             lenientRequest = new FilterModelBuildingRequest(request) {
1063                 @Override
1064                 public int getValidationLevel() {
1065                     return ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
1066                 }
1067             };
1068         }
1069 
1070         Model parentModel = readModel(modelSource, null, lenientRequest, problems);
1071 
1072         if (!parent.getVersion().equals(version)) {
1073             String rawChildModelVersion = childModel.getVersion();
1074 
1075             if (rawChildModelVersion == null) {
1076                 // Message below is checked for in the MNG-2199 core IT.
1077                 problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.V31)
1078                         .setMessage("Version must be a constant")
1079                         .setLocation(childModel.getLocation("")));
1080 
1081             } else {
1082                 if (rawChildVersionReferencesParent(rawChildModelVersion)) {
1083                     // Message below is checked for in the MNG-2199 core IT.
1084                     problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.V31)
1085                             .setMessage("Version must be a constant")
1086                             .setLocation(childModel.getLocation("version")));
1087                 }
1088             }
1089 
1090             // MNG-2199: What else to check here ?
1091         }
1092 
1093         ModelData parentData = new ModelData(
1094                 modelSource, parentModel, parent.getGroupId(), parent.getArtifactId(), parent.getVersion());
1095 
1096         return parentData;
1097     }
1098 
1099     private Model getSuperModel() {
1100         return superPomProvider.getSuperModel("4.0.0").clone();
1101     }
1102 
1103     @SuppressWarnings("checkstyle:methodlength")
1104     private void importDependencyManagement(
1105             Model model,
1106             ModelBuildingRequest request,
1107             DefaultModelProblemCollector problems,
1108             Collection<String> importIds) {
1109         DependencyManagement depMgmt = model.getDependencyManagement();
1110 
1111         if (depMgmt == null) {
1112             return;
1113         }
1114 
1115         String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion();
1116 
1117         importIds.add(importing);
1118 
1119         final WorkspaceModelResolver workspaceResolver = request.getWorkspaceModelResolver();
1120         final ModelResolver modelResolver = request.getModelResolver();
1121 
1122         ModelBuildingRequest importRequest = null;
1123 
1124         List<DependencyManagement> importMgmts = null;
1125 
1126         for (Iterator<Dependency> it = depMgmt.getDependencies().iterator(); it.hasNext(); ) {
1127             Dependency dependency = it.next();
1128 
1129             if (!"pom".equals(dependency.getType()) || !"import".equals(dependency.getScope())) {
1130                 continue;
1131             }
1132 
1133             it.remove();
1134 
1135             String groupId = dependency.getGroupId();
1136             String artifactId = dependency.getArtifactId();
1137             String version = dependency.getVersion();
1138 
1139             if (groupId == null || groupId.length() <= 0) {
1140                 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
1141                         .setMessage("'dependencyManagement.dependencies.dependency.groupId' for "
1142                                 + dependency.getManagementKey() + " is missing.")
1143                         .setLocation(dependency.getLocation("")));
1144                 continue;
1145             }
1146             if (artifactId == null || artifactId.length() <= 0) {
1147                 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
1148                         .setMessage("'dependencyManagement.dependencies.dependency.artifactId' for "
1149                                 + dependency.getManagementKey() + " is missing.")
1150                         .setLocation(dependency.getLocation("")));
1151                 continue;
1152             }
1153             if (version == null || version.length() <= 0) {
1154                 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
1155                         .setMessage("'dependencyManagement.dependencies.dependency.version' for "
1156                                 + dependency.getManagementKey() + " is missing.")
1157                         .setLocation(dependency.getLocation("")));
1158                 continue;
1159             }
1160 
1161             String imported = groupId + ':' + artifactId + ':' + version;
1162 
1163             if (importIds.contains(imported)) {
1164                 String message = "The dependencies of type=pom and with scope=import form a cycle: ";
1165                 for (String modelId : importIds) {
1166                     message += modelId + " -> ";
1167                 }
1168                 message += imported;
1169                 problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE).setMessage(message));
1170 
1171                 continue;
1172             }
1173 
1174             DependencyManagement importMgmt =
1175                     getCache(request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT);
1176 
1177             if (importMgmt == null) {
1178                 if (workspaceResolver == null && modelResolver == null) {
1179                     throw new NullPointerException(String.format(
1180                             "request.workspaceModelResolver and request.modelResolver cannot be null"
1181                                     + " (parent POM %s and POM %s)",
1182                             ModelProblemUtils.toId(groupId, artifactId, version),
1183                             ModelProblemUtils.toSourceHint(model)));
1184                 }
1185 
1186                 Model importModel = null;
1187                 if (workspaceResolver != null) {
1188                     try {
1189                         importModel = workspaceResolver.resolveEffectiveModel(groupId, artifactId, version);
1190                     } catch (UnresolvableModelException e) {
1191                         problems.add(new ModelProblemCollectorRequest(Severity.FATAL, Version.BASE)
1192                                 .setMessage(e.getMessage().toString())
1193                                 .setException(e));
1194                         continue;
1195                     }
1196                 }
1197 
1198                 // no workspace resolver or workspace resolver returned null (i.e. model not in workspace)
1199                 if (importModel == null) {
1200                     final ModelSource importSource;
1201                     try {
1202                         importSource = modelResolver.resolveModel(groupId, artifactId, version);
1203                     } catch (UnresolvableModelException e) {
1204                         StringBuilder buffer = new StringBuilder(256);
1205                         buffer.append("Non-resolvable import POM");
1206                         if (!containsCoordinates(e.getMessage(), groupId, artifactId, version)) {
1207                             buffer.append(' ').append(ModelProblemUtils.toId(groupId, artifactId, version));
1208                         }
1209                         buffer.append(": ").append(e.getMessage());
1210 
1211                         problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
1212                                 .setMessage(buffer.toString())
1213                                 .setLocation(dependency.getLocation(""))
1214                                 .setException(e));
1215                         continue;
1216                     }
1217 
1218                     if (importRequest == null) {
1219                         importRequest = new DefaultModelBuildingRequest();
1220                         importRequest.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
1221                         importRequest.setModelCache(request.getModelCache());
1222                         importRequest.setSystemProperties(request.getSystemProperties());
1223                         importRequest.setUserProperties(request.getUserProperties());
1224                         importRequest.setLocationTracking(request.isLocationTracking());
1225                     }
1226 
1227                     importRequest.setModelSource(importSource);
1228                     importRequest.setModelResolver(modelResolver.newCopy());
1229 
1230                     final ModelBuildingResult importResult;
1231                     try {
1232                         importResult = build(importRequest, importIds);
1233                     } catch (ModelBuildingException e) {
1234                         problems.addAll(e.getProblems());
1235                         continue;
1236                     }
1237 
1238                     problems.addAll(importResult.getProblems());
1239 
1240                     importModel = importResult.getEffectiveModel();
1241                 }
1242 
1243                 importMgmt = importModel.getDependencyManagement();
1244 
1245                 if (importMgmt == null) {
1246                     importMgmt = new DependencyManagement();
1247                 }
1248 
1249                 putCache(request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, importMgmt);
1250             }
1251 
1252             if (importMgmts == null) {
1253                 importMgmts = new ArrayList<>();
1254             }
1255 
1256             importMgmts.add(importMgmt);
1257         }
1258 
1259         importIds.remove(importing);
1260 
1261         dependencyManagementImporter.importManagement(model, importMgmts, request, problems);
1262     }
1263 
1264     private <T> void putCache(
1265             ModelCache modelCache, String groupId, String artifactId, String version, ModelCacheTag<T> tag, T data) {
1266         if (modelCache != null) {
1267             modelCache.put(groupId, artifactId, version, tag.getName(), tag.intoCache(data));
1268         }
1269     }
1270 
1271     private <T> T getCache(
1272             ModelCache modelCache, String groupId, String artifactId, String version, ModelCacheTag<T> tag) {
1273         if (modelCache != null) {
1274             Object data = modelCache.get(groupId, artifactId, version, tag.getName());
1275             if (data != null) {
1276                 return tag.fromCache(tag.getType().cast(data));
1277             }
1278         }
1279         return null;
1280     }
1281 
1282     private void fireEvent(
1283             Model model,
1284             ModelBuildingRequest request,
1285             ModelProblemCollector problems,
1286             ModelBuildingEventCatapult catapult)
1287             throws ModelBuildingException {
1288         ModelBuildingListener listener = request.getModelBuildingListener();
1289 
1290         if (listener != null) {
1291             ModelBuildingEvent event = new DefaultModelBuildingEvent(model, request, problems);
1292 
1293             catapult.fire(listener, event);
1294         }
1295     }
1296 
1297     private boolean containsCoordinates(String message, String groupId, String artifactId, String version) {
1298         return message != null
1299                 && (groupId == null || message.contains(groupId))
1300                 && (artifactId == null || message.contains(artifactId))
1301                 && (version == null || message.contains(version));
1302     }
1303 
1304     protected boolean hasModelErrors(ModelProblemCollectorExt problems) {
1305         if (problems instanceof DefaultModelProblemCollector) {
1306             return ((DefaultModelProblemCollector) problems).hasErrors();
1307         } else {
1308             // the default execution path only knows the DefaultModelProblemCollector,
1309             // only reason it's not in signature is because it's package private
1310             throw new IllegalStateException();
1311         }
1312     }
1313 
1314     protected boolean hasFatalErrors(ModelProblemCollectorExt problems) {
1315         if (problems instanceof DefaultModelProblemCollector) {
1316             return ((DefaultModelProblemCollector) problems).hasFatalErrors();
1317         } else {
1318             // the default execution path only knows the DefaultModelProblemCollector,
1319             // only reason it's not in signature is because it's package private
1320             throw new IllegalStateException();
1321         }
1322     }
1323 }