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