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