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