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