1 package org.apache.maven.model.building;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Iterator;
27 import java.util.LinkedHashSet;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.HashMap;
31 import java.util.Properties;
32
33 import org.apache.maven.model.Build;
34 import org.apache.maven.model.Dependency;
35 import org.apache.maven.model.DependencyManagement;
36 import org.apache.maven.model.InputLocation;
37 import org.apache.maven.model.InputSource;
38 import org.apache.maven.model.Model;
39 import org.apache.maven.model.Parent;
40 import org.apache.maven.model.Plugin;
41 import org.apache.maven.model.PluginManagement;
42 import org.apache.maven.model.Profile;
43 import org.apache.maven.model.Repository;
44 import org.apache.maven.model.building.ModelProblem.Severity;
45 import org.apache.maven.model.composition.DependencyManagementImporter;
46 import org.apache.maven.model.inheritance.InheritanceAssembler;
47 import org.apache.maven.model.interpolation.ModelInterpolator;
48 import org.apache.maven.model.io.ModelParseException;
49 import org.apache.maven.model.management.DependencyManagementInjector;
50 import org.apache.maven.model.management.PluginManagementInjector;
51 import org.apache.maven.model.normalization.ModelNormalizer;
52 import org.apache.maven.model.path.ModelPathTranslator;
53 import org.apache.maven.model.path.ModelUrlNormalizer;
54 import org.apache.maven.model.plugin.LifecycleBindingsInjector;
55 import org.apache.maven.model.plugin.PluginConfigurationExpander;
56 import org.apache.maven.model.plugin.ReportConfigurationExpander;
57 import org.apache.maven.model.plugin.ReportingConverter;
58 import org.apache.maven.model.profile.DefaultProfileActivationContext;
59 import org.apache.maven.model.profile.ProfileInjector;
60 import org.apache.maven.model.profile.ProfileSelector;
61 import org.apache.maven.model.resolution.InvalidRepositoryException;
62 import org.apache.maven.model.resolution.ModelResolver;
63 import org.apache.maven.model.resolution.UnresolvableModelException;
64 import org.apache.maven.model.superpom.SuperPomProvider;
65 import org.apache.maven.model.validation.ModelValidator;
66 import org.codehaus.plexus.component.annotations.Component;
67 import org.codehaus.plexus.component.annotations.Requirement;
68
69
70
71
72 @Component( role = ModelBuilder.class )
73 public class DefaultModelBuilder
74 implements ModelBuilder
75 {
76 @Requirement
77 private ModelProcessor modelProcessor;
78
79 @Requirement
80 private ModelValidator modelValidator;
81
82 @Requirement
83 private ModelNormalizer modelNormalizer;
84
85 @Requirement
86 private ModelInterpolator modelInterpolator;
87
88 @Requirement
89 private ModelPathTranslator modelPathTranslator;
90
91 @Requirement
92 private ModelUrlNormalizer modelUrlNormalizer;
93
94 @Requirement
95 private SuperPomProvider superPomProvider;
96
97 @Requirement
98 private InheritanceAssembler inheritanceAssembler;
99
100 @Requirement
101 private ProfileSelector profileSelector;
102
103 @Requirement
104 private ProfileInjector profileInjector;
105
106 @Requirement
107 private PluginManagementInjector pluginManagementInjector;
108
109 @Requirement
110 private DependencyManagementInjector dependencyManagementInjector;
111
112 @Requirement
113 private DependencyManagementImporter dependencyManagementImporter;
114
115 @Requirement( optional = true )
116 private LifecycleBindingsInjector lifecycleBindingsInjector;
117
118 @Requirement
119 private PluginConfigurationExpander pluginConfigurationExpander;
120
121 @Requirement
122 private ReportConfigurationExpander reportConfigurationExpander;
123
124 @Requirement
125 private ReportingConverter reportingConverter;
126
127 public DefaultModelBuilder setModelProcessor( ModelProcessor modelProcessor )
128 {
129 this.modelProcessor = modelProcessor;
130 return this;
131 }
132
133 public DefaultModelBuilder setModelValidator( ModelValidator modelValidator )
134 {
135 this.modelValidator = modelValidator;
136 return this;
137 }
138
139 public DefaultModelBuilder setModelNormalizer( ModelNormalizer modelNormalizer )
140 {
141 this.modelNormalizer = modelNormalizer;
142 return this;
143 }
144
145 public DefaultModelBuilder setModelInterpolator( ModelInterpolator modelInterpolator )
146 {
147 this.modelInterpolator = modelInterpolator;
148 return this;
149 }
150
151 public DefaultModelBuilder setModelPathTranslator( ModelPathTranslator modelPathTranslator )
152 {
153 this.modelPathTranslator = modelPathTranslator;
154 return this;
155 }
156
157 public DefaultModelBuilder setModelUrlNormalizer( ModelUrlNormalizer modelUrlNormalizer )
158 {
159 this.modelUrlNormalizer = modelUrlNormalizer;
160 return this;
161 }
162
163 public DefaultModelBuilder setSuperPomProvider( SuperPomProvider superPomProvider )
164 {
165 this.superPomProvider = superPomProvider;
166 return this;
167 }
168
169 public DefaultModelBuilder setProfileSelector( ProfileSelector profileSelector )
170 {
171 this.profileSelector = profileSelector;
172 return this;
173 }
174
175 public DefaultModelBuilder setProfileInjector( ProfileInjector profileInjector )
176 {
177 this.profileInjector = profileInjector;
178 return this;
179 }
180
181 public DefaultModelBuilder setInheritanceAssembler( InheritanceAssembler inheritanceAssembler )
182 {
183 this.inheritanceAssembler = inheritanceAssembler;
184 return this;
185 }
186
187 public DefaultModelBuilder setDependencyManagementImporter( DependencyManagementImporter depMngmntImporter )
188 {
189 this.dependencyManagementImporter = depMngmntImporter;
190 return this;
191 }
192
193 public DefaultModelBuilder setDependencyManagementInjector( DependencyManagementInjector depMngmntInjector )
194 {
195 this.dependencyManagementInjector = depMngmntInjector;
196 return this;
197 }
198
199 public DefaultModelBuilder setLifecycleBindingsInjector( LifecycleBindingsInjector lifecycleBindingsInjector )
200 {
201 this.lifecycleBindingsInjector = lifecycleBindingsInjector;
202 return this;
203 }
204
205 public DefaultModelBuilder setPluginConfigurationExpander( PluginConfigurationExpander pluginConfigurationExpander )
206 {
207 this.pluginConfigurationExpander = pluginConfigurationExpander;
208 return this;
209 }
210
211 public DefaultModelBuilder setPluginManagementInjector( PluginManagementInjector pluginManagementInjector )
212 {
213 this.pluginManagementInjector = pluginManagementInjector;
214 return this;
215 }
216
217 public DefaultModelBuilder setReportConfigurationExpander( ReportConfigurationExpander reportConfigurationExpander )
218 {
219 this.reportConfigurationExpander = reportConfigurationExpander;
220 return this;
221 }
222
223 public DefaultModelBuilder setReportingConverter( ReportingConverter reportingConverter )
224 {
225 this.reportingConverter = reportingConverter;
226 return this;
227 }
228
229 public ModelBuildingResult build( ModelBuildingRequest request )
230 throws ModelBuildingException
231 {
232 return build( request, new LinkedHashSet<String>() );
233 }
234
235 private ModelBuildingResult build( ModelBuildingRequest request, Collection<String> importIds )
236 throws ModelBuildingException
237 {
238 DefaultModelBuildingResult result = new DefaultModelBuildingResult();
239
240 DefaultModelProblemCollector problems = new DefaultModelProblemCollector( result );
241
242 DefaultProfileActivationContext profileActivationContext = getProfileActivationContext( request );
243
244 problems.setSource( "(external profiles)" );
245 List<Profile> activeExternalProfiles =
246 profileSelector.getActiveProfiles( request.getProfiles(), profileActivationContext, problems );
247
248 result.setActiveExternalProfiles( activeExternalProfiles );
249
250 if ( !activeExternalProfiles.isEmpty() )
251 {
252 Properties profileProps = new Properties();
253 for ( Profile profile : activeExternalProfiles )
254 {
255 profileProps.putAll( profile.getProperties() );
256 }
257 profileProps.putAll( profileActivationContext.getUserProperties() );
258 profileActivationContext.setUserProperties( profileProps );
259 }
260
261 Model inputModel = readModel( request.getModelSource(), request.getPomFile(), request, problems );
262
263 problems.setRootModel( inputModel );
264
265 ModelData resultData = new ModelData( inputModel );
266 ModelData superData = new ModelData( getSuperModel() );
267
268 Collection<String> parentIds = new LinkedHashSet<String>();
269 parentIds.add( ModelProblemUtils.toId( inputModel ) );
270
271 List<ModelData> lineage = new ArrayList<ModelData>();
272
273 for ( ModelData currentData = resultData; currentData != null; )
274 {
275 lineage.add( currentData );
276
277 Model tmpModel = currentData.getModel();
278
279 Model rawModel = tmpModel.clone();
280 currentData.setRawModel( rawModel );
281
282 problems.setSource( tmpModel );
283
284 modelNormalizer.mergeDuplicates( tmpModel, request, problems );
285
286 List<Profile> activePomProfiles =
287 profileSelector.getActiveProfiles( rawModel.getProfiles(), profileActivationContext, problems );
288 currentData.setActiveProfiles( activePomProfiles );
289
290 for ( Profile activeProfile : activePomProfiles )
291 {
292 profileInjector.injectProfile( tmpModel, activeProfile, request, problems );
293 }
294
295 if ( currentData == resultData )
296 {
297 for ( Profile activeProfile : activeExternalProfiles )
298 {
299 profileInjector.injectProfile( tmpModel, activeProfile, request, problems );
300 }
301 }
302
303 if ( currentData == superData )
304 {
305 break;
306 }
307
308 configureResolver( request.getModelResolver(), tmpModel, problems );
309
310 currentData = readParent( tmpModel, request, problems );
311
312 if ( currentData == null )
313 {
314 currentData = superData;
315 }
316 else if ( !parentIds.add( currentData.getId() ) )
317 {
318 String message = "The parents form a cycle: ";
319 for ( String modelId : parentIds )
320 {
321 message += modelId + " -> ";
322 }
323 message += currentData.getId();
324
325 problems.add( ModelProblem.Severity.FATAL, message, null, null );
326 throw problems.newModelBuildingException();
327 }
328 }
329
330 problems.setSource( inputModel );
331 checkPluginVersions( lineage, request, problems );
332
333 assembleInheritance( lineage, request, problems );
334
335 Model resultModel = resultData.getModel();
336
337 problems.setSource( resultModel );
338 problems.setRootModel( resultModel );
339
340 resultModel = interpolateModel( resultModel, request, problems );
341 resultData.setModel( resultModel );
342
343 modelUrlNormalizer.normalize( resultModel, request );
344
345 resultData.setGroupId( resultModel.getGroupId() );
346 resultData.setArtifactId( resultModel.getArtifactId() );
347 resultData.setVersion( resultModel.getVersion() );
348
349 result.setEffectiveModel( resultModel );
350
351 for ( ModelData currentData : lineage )
352 {
353 String modelId = ( currentData != superData ) ? currentData.getId() : "";
354
355 result.addModelId( modelId );
356 result.setActivePomProfiles( modelId, currentData.getActiveProfiles() );
357 result.setRawModel( modelId, currentData.getRawModel() );
358 }
359
360 if ( !request.isTwoPhaseBuilding() )
361 {
362 build( request, result );
363 }
364
365 return result;
366 }
367
368 public ModelBuildingResult build( ModelBuildingRequest request, ModelBuildingResult result )
369 throws ModelBuildingException
370 {
371 return build( request, result, new LinkedHashSet<String>() );
372 }
373
374 private ModelBuildingResult build( ModelBuildingRequest request, ModelBuildingResult result,
375 Collection<String> imports )
376 throws ModelBuildingException
377 {
378 Model resultModel = result.getEffectiveModel();
379
380 DefaultModelProblemCollector problems = new DefaultModelProblemCollector( result );
381 problems.setSource( resultModel );
382 problems.setRootModel( resultModel );
383
384 modelPathTranslator.alignToBaseDirectory( resultModel, resultModel.getProjectDirectory(), request );
385
386 pluginManagementInjector.injectManagement( resultModel, request, problems );
387
388 fireEvent( resultModel, request, problems, ModelBuildingEventCatapult.BUILD_EXTENSIONS_ASSEMBLED );
389
390 if ( request.isProcessPlugins() )
391 {
392 if ( lifecycleBindingsInjector == null )
393 {
394 throw new IllegalStateException( "lifecycle bindings injector is missing" );
395 }
396
397 lifecycleBindingsInjector.injectLifecycleBindings( resultModel, request, problems );
398 }
399
400 importDependencyManagement( resultModel, request, problems, imports );
401
402 dependencyManagementInjector.injectManagement( resultModel, request, problems );
403
404 modelNormalizer.injectDefaultValues( resultModel, request, problems );
405
406 if ( request.isProcessPlugins() )
407 {
408 reportConfigurationExpander.expandPluginConfiguration( resultModel, request, problems );
409
410 reportingConverter.convertReporting( resultModel, request, problems );
411
412 pluginConfigurationExpander.expandPluginConfiguration( resultModel, request, problems );
413 }
414
415 modelValidator.validateEffectiveModel( resultModel, request, problems );
416
417 if ( problems.hasErrors() )
418 {
419 throw problems.newModelBuildingException();
420 }
421
422 return result;
423 }
424
425 private Model readModel( ModelSource modelSource, File pomFile, ModelBuildingRequest request,
426 DefaultModelProblemCollector problems )
427 throws ModelBuildingException
428 {
429 Model model;
430
431 if ( modelSource == null )
432 {
433 if ( pomFile != null )
434 {
435 modelSource = new FileModelSource( pomFile );
436 }
437 else
438 {
439 throw new IllegalArgumentException( "neither model source nor input file are specified" );
440 }
441 }
442
443 problems.setSource( modelSource.getLocation() );
444 try
445 {
446 boolean strict = request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
447 InputSource source = request.isLocationTracking() ? new InputSource() : null;
448
449 Map<String, Object> options = new HashMap<String, Object>();
450 options.put( ModelProcessor.IS_STRICT, Boolean.valueOf( strict ) );
451 options.put( ModelProcessor.INPUT_SOURCE, source );
452 options.put( ModelProcessor.SOURCE, modelSource );
453
454 try
455 {
456 model = modelProcessor.read( modelSource.getInputStream(), options );
457 }
458 catch ( ModelParseException e )
459 {
460 if ( !strict )
461 {
462 throw e;
463 }
464
465 options.put( ModelProcessor.IS_STRICT, Boolean.FALSE );
466
467 try
468 {
469 model = modelProcessor.read( modelSource.getInputStream(), options );
470 }
471 catch ( ModelParseException ne )
472 {
473
474 throw e;
475 }
476
477 if ( pomFile != null )
478 {
479 problems.add( Severity.ERROR, "Malformed POM " + modelSource.getLocation() + ": " + e.getMessage(),
480 null, e );
481 }
482 else
483 {
484 problems.add( Severity.WARNING, "Malformed POM " + modelSource.getLocation() + ": "
485 + e.getMessage(), null, e );
486 }
487 }
488
489 if ( source != null )
490 {
491 source.setModelId( ModelProblemUtils.toId( model ) );
492 source.setLocation( modelSource.getLocation() );
493 }
494 }
495 catch ( ModelParseException e )
496 {
497 problems.add( Severity.FATAL, "Non-parseable POM " + modelSource.getLocation() + ": " + e.getMessage(),
498 null, e );
499 throw problems.newModelBuildingException();
500 }
501 catch ( IOException e )
502 {
503 String msg = e.getMessage();
504 if ( msg == null || msg.length() <= 0 )
505 {
506
507 if ( e.getClass().getName().endsWith( "MalformedInputException" ) )
508 {
509 msg = "Some input bytes do not match the file encoding.";
510 }
511 else
512 {
513 msg = e.getClass().getSimpleName();
514 }
515 }
516 problems.add( Severity.FATAL, "Non-readable POM " + modelSource.getLocation() + ": " + msg, null, e );
517 throw problems.newModelBuildingException();
518 }
519
520 model.setPomFile( pomFile );
521
522 problems.setSource( model );
523 modelValidator.validateRawModel( model, request, problems );
524
525 if ( problems.hasFatalErrors() )
526 {
527 throw problems.newModelBuildingException();
528 }
529
530 return model;
531 }
532
533 private DefaultProfileActivationContext getProfileActivationContext( ModelBuildingRequest request )
534 {
535 DefaultProfileActivationContext context = new DefaultProfileActivationContext();
536
537 context.setActiveProfileIds( request.getActiveProfileIds() );
538 context.setInactiveProfileIds( request.getInactiveProfileIds() );
539 context.setSystemProperties( request.getSystemProperties() );
540 context.setUserProperties( request.getUserProperties() );
541 context.setProjectDirectory( ( request.getPomFile() != null ) ? request.getPomFile().getParentFile() : null );
542
543 return context;
544 }
545
546 private void configureResolver( ModelResolver modelResolver, Model model, DefaultModelProblemCollector problems )
547 {
548 if ( modelResolver == null )
549 {
550 return;
551 }
552
553 problems.setSource( model );
554
555 List<Repository> repositories = model.getRepositories();
556
557 for ( Repository repository : repositories )
558 {
559 try
560 {
561 modelResolver.addRepository( repository );
562 }
563 catch ( InvalidRepositoryException e )
564 {
565 problems.add( Severity.ERROR, "Invalid repository " + repository.getId() + ": " + e.getMessage(),
566 repository.getLocation( "" ), e );
567 }
568 }
569 }
570
571 private void checkPluginVersions( List<ModelData> lineage, ModelBuildingRequest request,
572 ModelProblemCollector problems )
573 {
574 if ( request.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
575 {
576 return;
577 }
578
579 Map<String, Plugin> plugins = new HashMap<String, Plugin>();
580 Map<String, String> versions = new HashMap<String, String>();
581 Map<String, String> managedVersions = new HashMap<String, String>();
582
583 for ( int i = lineage.size() - 1; i >= 0; i-- )
584 {
585 Model model = lineage.get( i ).getModel();
586 Build build = model.getBuild();
587 if ( build != null )
588 {
589 for ( Plugin plugin : build.getPlugins() )
590 {
591 String key = plugin.getKey();
592 if ( versions.get( key ) == null )
593 {
594 versions.put( key, plugin.getVersion() );
595 plugins.put( key, plugin );
596 }
597 }
598 PluginManagement mngt = build.getPluginManagement();
599 if ( mngt != null )
600 {
601 for ( Plugin plugin : mngt.getPlugins() )
602 {
603 String key = plugin.getKey();
604 if ( managedVersions.get( key ) == null )
605 {
606 managedVersions.put( key, plugin.getVersion() );
607 }
608 }
609 }
610 }
611 }
612
613 for ( String key : versions.keySet() )
614 {
615 if ( versions.get( key ) == null && managedVersions.get( key ) == null )
616 {
617 InputLocation location = plugins.get( key ).getLocation( "" );
618 problems.add( Severity.WARNING, "'build.plugins.plugin.version' for " + key + " is missing.", location,
619 null );
620 }
621 }
622 }
623
624 private void assembleInheritance( List<ModelData> lineage, ModelBuildingRequest request,
625 ModelProblemCollector problems )
626 {
627 for ( int i = lineage.size() - 2; i >= 0; i-- )
628 {
629 Model parent = lineage.get( i + 1 ).getModel();
630 Model child = lineage.get( i ).getModel();
631 inheritanceAssembler.assembleModelInheritance( child, parent, request, problems );
632 }
633 }
634
635 private Model interpolateModel( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
636 {
637 Model result = modelInterpolator.interpolateModel( model, model.getProjectDirectory(), request, problems );
638 result.setPomFile( model.getPomFile() );
639 return result;
640 }
641
642 private ModelData readParent( Model childModel, ModelBuildingRequest request,
643 DefaultModelProblemCollector problems )
644 throws ModelBuildingException
645 {
646 ModelData parentData;
647
648 Parent parent = childModel.getParent();
649
650 if ( parent != null )
651 {
652 String groupId = parent.getGroupId();
653 String artifactId = parent.getArtifactId();
654 String version = parent.getVersion();
655
656 parentData = getCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW );
657
658 if ( parentData == null )
659 {
660 parentData = readParentLocally( childModel, request, problems );
661
662 if ( parentData == null )
663 {
664 parentData = readParentExternally( childModel, request, problems );
665 }
666
667 putCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW, parentData );
668 }
669 else
670 {
671
672
673
674
675
676
677
678 File pomFile = parentData.getModel().getPomFile();
679 if ( pomFile != null )
680 {
681 File expectedParentFile = getParentPomFile( childModel );
682
683 if ( !pomFile.equals( expectedParentFile ) )
684 {
685 parentData = readParentExternally( childModel, request, problems );
686 }
687 }
688 }
689
690 Model parentModel = parentData.getModel();
691
692 if ( !"pom".equals( parentModel.getPackaging() ) )
693 {
694 problems.add( Severity.ERROR, "Invalid packaging for parent POM "
695 + ModelProblemUtils.toSourceHint( parentModel ) + ", must be \"pom\" but is \""
696 + parentModel.getPackaging() + "\"", parentModel.getLocation( "packaging" ), null );
697 }
698 }
699 else
700 {
701 parentData = null;
702 }
703
704 return parentData;
705 }
706
707 private ModelData readParentLocally( Model childModel, ModelBuildingRequest request,
708 DefaultModelProblemCollector problems )
709 throws ModelBuildingException
710 {
711 File pomFile = getParentPomFile( childModel );
712
713 if ( pomFile == null || !pomFile.isFile() )
714 {
715 return null;
716 }
717
718 Model candidateModel = readModel( null, pomFile, request, problems );
719
720 String groupId = candidateModel.getGroupId();
721 if ( groupId == null && candidateModel.getParent() != null )
722 {
723 groupId = candidateModel.getParent().getGroupId();
724 }
725 String artifactId = candidateModel.getArtifactId();
726 String version = candidateModel.getVersion();
727 if ( version == null && candidateModel.getParent() != null )
728 {
729 version = candidateModel.getParent().getVersion();
730 }
731
732 Parent parent = childModel.getParent();
733
734 if ( groupId == null || !groupId.equals( parent.getGroupId() ) || artifactId == null
735 || !artifactId.equals( parent.getArtifactId() ) )
736 {
737 StringBuilder buffer = new StringBuilder( 256 );
738 buffer.append( "'parent.relativePath'" );
739 if ( childModel != problems.getRootModel() )
740 {
741 buffer.append( " of POM " ).append( ModelProblemUtils.toSourceHint( childModel ) );
742 }
743 buffer.append( " points at " ).append( groupId ).append( ":" ).append( artifactId );
744 buffer.append( " instead of " ).append( parent.getGroupId() ).append( ":" ).append( parent.getArtifactId() );
745 buffer.append( ", please verify your project structure" );
746
747 problems.setSource( childModel );
748 problems.add( Severity.WARNING, buffer.toString(), parent.getLocation( "" ), null );
749 return null;
750 }
751 if ( version == null || !version.equals( parent.getVersion() ) )
752 {
753 return null;
754 }
755
756 ModelData parentData = new ModelData( candidateModel, groupId, artifactId, version );
757
758 return parentData;
759 }
760
761 private File getParentPomFile( Model childModel )
762 {
763 File projectDirectory = childModel.getProjectDirectory();
764
765 if ( projectDirectory == null )
766 {
767 return null;
768 }
769
770 String parentPath = childModel.getParent().getRelativePath();
771
772 if ( parentPath == null || parentPath.length() <= 0 )
773 {
774 return null;
775 }
776
777 parentPath = parentPath.replace( '\\', File.separatorChar ).replace( '/', File.separatorChar );
778
779 File pomFile = new File( new File( projectDirectory, parentPath ).toURI().normalize() );
780
781 if ( pomFile.isDirectory() )
782 {
783 pomFile = modelProcessor.locatePom( pomFile );
784 }
785
786 return pomFile;
787 }
788
789 private ModelData readParentExternally( Model childModel, ModelBuildingRequest request,
790 DefaultModelProblemCollector problems )
791 throws ModelBuildingException
792 {
793 problems.setSource( childModel );
794
795 Parent parent = childModel.getParent();
796
797 String groupId = parent.getGroupId();
798 String artifactId = parent.getArtifactId();
799 String version = parent.getVersion();
800
801 ModelResolver modelResolver = request.getModelResolver();
802
803 if ( modelResolver == null )
804 {
805 throw new IllegalArgumentException( "no model resolver provided, cannot resolve parent POM "
806 + ModelProblemUtils.toId( groupId, artifactId, version ) + " for POM "
807 + ModelProblemUtils.toSourceHint( childModel ) );
808 }
809
810 ModelSource modelSource;
811 try
812 {
813 modelSource = modelResolver.resolveModel( groupId, artifactId, version );
814 }
815 catch ( UnresolvableModelException e )
816 {
817 StringBuilder buffer = new StringBuilder( 256 );
818 buffer.append( "Non-resolvable parent POM" );
819 if ( !containsCoordinates( e.getMessage(), groupId, artifactId, version ) )
820 {
821 buffer.append( " " ).append( ModelProblemUtils.toId( groupId, artifactId, version ) );
822 }
823 if ( childModel != problems.getRootModel() )
824 {
825 buffer.append( " for " ).append( ModelProblemUtils.toId( childModel ) );
826 }
827 buffer.append( ": " ).append( e.getMessage() );
828 if ( childModel.getProjectDirectory() != null )
829 {
830 if ( parent.getRelativePath() == null || parent.getRelativePath().length() <= 0 )
831 {
832 buffer.append( " and 'parent.relativePath' points at no local POM" );
833 }
834 else
835 {
836 buffer.append( " and 'parent.relativePath' points at wrong local POM" );
837 }
838 }
839
840 problems.add( Severity.FATAL, buffer.toString(), parent.getLocation( "" ), e );
841 throw problems.newModelBuildingException();
842 }
843
844 ModelBuildingRequest lenientRequest = request;
845 if ( request.getValidationLevel() > ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
846 {
847 lenientRequest = new FilterModelBuildingRequest( request )
848 {
849 @Override
850 public int getValidationLevel()
851 {
852 return ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
853 }
854 };
855 }
856
857 Model parentModel = readModel( modelSource, null, lenientRequest, problems );
858
859 ModelData parentData = new ModelData( parentModel, groupId, artifactId, version );
860
861 return parentData;
862 }
863
864 private Model getSuperModel()
865 {
866 return superPomProvider.getSuperModel( "4.0.0" ).clone();
867 }
868
869 private void importDependencyManagement( Model model, ModelBuildingRequest request,
870 DefaultModelProblemCollector problems, Collection<String> importIds )
871 {
872 DependencyManagement depMngt = model.getDependencyManagement();
873
874 if ( depMngt == null )
875 {
876 return;
877 }
878
879 String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion();
880
881 importIds.add( importing );
882
883 ModelResolver modelResolver = request.getModelResolver();
884
885 ModelBuildingRequest importRequest = null;
886
887 List<DependencyManagement> importMngts = null;
888
889 for ( Iterator<Dependency> it = depMngt.getDependencies().iterator(); it.hasNext(); )
890 {
891 Dependency dependency = it.next();
892
893 if ( !"pom".equals( dependency.getType() ) || !"import".equals( dependency.getScope() ) )
894 {
895 continue;
896 }
897
898 it.remove();
899
900 String groupId = dependency.getGroupId();
901 String artifactId = dependency.getArtifactId();
902 String version = dependency.getVersion();
903
904 if ( groupId == null || groupId.length() <= 0 )
905 {
906 problems.add( Severity.ERROR, "'dependencyManagement.dependencies.dependency.groupId' for "
907 + dependency.getManagementKey() + " is missing.", dependency.getLocation( "" ), null );
908 continue;
909 }
910 if ( artifactId == null || artifactId.length() <= 0 )
911 {
912 problems.add( Severity.ERROR, "'dependencyManagement.dependencies.dependency.artifactId' for "
913 + dependency.getManagementKey() + " is missing.", dependency.getLocation( "" ), null );
914 continue;
915 }
916 if ( version == null || version.length() <= 0 )
917 {
918 problems.add( Severity.ERROR, "'dependencyManagement.dependencies.dependency.version' for "
919 + dependency.getManagementKey() + " is missing.", dependency.getLocation( "" ), null );
920 continue;
921 }
922
923 String imported = groupId + ':' + artifactId + ':' + version;
924
925 if ( importIds.contains( imported ) )
926 {
927 String message = "The dependencies of type=pom and with scope=import form a cycle: ";
928 for ( String modelId : importIds )
929 {
930 message += modelId + " -> ";
931 }
932 message += imported;
933 problems.add( Severity.ERROR, message, null, null );
934
935 continue;
936 }
937
938 DependencyManagement importMngt =
939 getCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT );
940
941 if ( importMngt == null )
942 {
943 if ( modelResolver == null )
944 {
945 throw new IllegalArgumentException( "no model resolver provided, cannot resolve import POM "
946 + ModelProblemUtils.toId( groupId, artifactId, version ) + " for POM "
947 + ModelProblemUtils.toSourceHint( model ) );
948 }
949
950 ModelSource importSource;
951 try
952 {
953 importSource = modelResolver.resolveModel( groupId, artifactId, version );
954 }
955 catch ( UnresolvableModelException e )
956 {
957 StringBuilder buffer = new StringBuilder( 256 );
958 buffer.append( "Non-resolvable import POM" );
959 if ( !containsCoordinates( e.getMessage(), groupId, artifactId, version ) )
960 {
961 buffer.append( " " ).append( ModelProblemUtils.toId( groupId, artifactId, version ) );
962 }
963 buffer.append( ": " ).append( e.getMessage() );
964
965 problems.add( Severity.ERROR, buffer.toString(), dependency.getLocation( "" ), e );
966 continue;
967 }
968
969 if ( importRequest == null )
970 {
971 importRequest = new DefaultModelBuildingRequest();
972 importRequest.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
973 importRequest.setModelCache( request.getModelCache() );
974 importRequest.setSystemProperties( request.getSystemProperties() );
975 importRequest.setUserProperties( request.getUserProperties() );
976 importRequest.setLocationTracking( request.isLocationTracking() );
977 }
978
979 importRequest.setModelSource( importSource );
980 importRequest.setModelResolver( modelResolver.newCopy() );
981
982 ModelBuildingResult importResult;
983 try
984 {
985 importResult = build( importRequest, importIds );
986 }
987 catch ( ModelBuildingException e )
988 {
989 problems.addAll( e.getProblems() );
990 continue;
991 }
992
993 problems.addAll( importResult.getProblems() );
994
995 Model importModel = importResult.getEffectiveModel();
996
997 importMngt = importModel.getDependencyManagement();
998
999 if ( importMngt == null )
1000 {
1001 importMngt = new DependencyManagement();
1002 }
1003
1004 putCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, importMngt );
1005 }
1006
1007 if ( importMngts == null )
1008 {
1009 importMngts = new ArrayList<DependencyManagement>();
1010 }
1011
1012 importMngts.add( importMngt );
1013 }
1014
1015 importIds.remove( importing );
1016
1017 dependencyManagementImporter.importManagement( model, importMngts, request, problems );
1018 }
1019
1020 private <T> void putCache( ModelCache modelCache, String groupId, String artifactId, String version,
1021 ModelCacheTag<T> tag, T data )
1022 {
1023 if ( modelCache != null )
1024 {
1025 modelCache.put( groupId, artifactId, version, tag.getName(), tag.intoCache( data ) );
1026 }
1027 }
1028
1029 private <T> T getCache( ModelCache modelCache, String groupId, String artifactId, String version,
1030 ModelCacheTag<T> tag )
1031 {
1032 if ( modelCache != null )
1033 {
1034 Object data = modelCache.get( groupId, artifactId, version, tag.getName() );
1035 if ( data != null )
1036 {
1037 return tag.fromCache( tag.getType().cast( data ) );
1038 }
1039 }
1040 return null;
1041 }
1042
1043 private void fireEvent( Model model, ModelBuildingRequest request, ModelProblemCollector problems,
1044 ModelBuildingEventCatapult catapult )
1045 throws ModelBuildingException
1046 {
1047 ModelBuildingListener listener = request.getModelBuildingListener();
1048
1049 if ( listener != null )
1050 {
1051 ModelBuildingEvent event = new DefaultModelBuildingEvent( model, request, problems );
1052
1053 catapult.fire( listener, event );
1054 }
1055 }
1056
1057 private boolean containsCoordinates( String message, String groupId, String artifactId, String version )
1058 {
1059 return message != null && ( groupId == null || message.contains( groupId ) )
1060 && ( artifactId == null || message.contains( artifactId ) )
1061 && ( version == null || message.contains( version ) );
1062 }
1063
1064 }