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, boolean replaceRepositories )
584 {
585 if ( modelResolver == null )
586 {
587 return;
588 }
589
590 problems.setSource( model );
591
592 List<Repository> repositories = model.getRepositories();
593
594 for ( Repository repository : repositories )
595 {
596 try
597 {
598 modelResolver.addRepository( repository, replaceRepositories );
599 }
600 catch ( InvalidRepositoryException e )
601 {
602 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
603 .setMessage( "Invalid repository " + repository.getId() + ": " + e.getMessage() )
604 .setLocation( repository.getLocation( "" ) )
605 .setException( e ) );
606 }
607 }
608 }
609
610 private void checkPluginVersions( List<ModelData> lineage, ModelBuildingRequest request,
611 ModelProblemCollector problems )
612 {
613 if ( request.getValidationLevel() < ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
614 {
615 return;
616 }
617
618 Map<String, Plugin> plugins = new HashMap<String, Plugin>();
619 Map<String, String> versions = new HashMap<String, String>();
620 Map<String, String> managedVersions = new HashMap<String, String>();
621
622 for ( int i = lineage.size() - 1; i >= 0; i-- )
623 {
624 Model model = lineage.get( i ).getModel();
625 Build build = model.getBuild();
626 if ( build != null )
627 {
628 for ( Plugin plugin : build.getPlugins() )
629 {
630 String key = plugin.getKey();
631 if ( versions.get( key ) == null )
632 {
633 versions.put( key, plugin.getVersion() );
634 plugins.put( key, plugin );
635 }
636 }
637 PluginManagement mngt = build.getPluginManagement();
638 if ( mngt != null )
639 {
640 for ( Plugin plugin : mngt.getPlugins() )
641 {
642 String key = plugin.getKey();
643 if ( managedVersions.get( key ) == null )
644 {
645 managedVersions.put( key, plugin.getVersion() );
646 }
647 }
648 }
649 }
650 }
651
652 for ( String key : versions.keySet() )
653 {
654 if ( versions.get( key ) == null && managedVersions.get( key ) == null )
655 {
656 InputLocation location = plugins.get( key ).getLocation( "" );
657 problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.V20 )
658 .setMessage( "'build.plugins.plugin.version' for " + key + " is missing." )
659 .setLocation( location ) );
660 }
661 }
662 }
663
664 private void assembleInheritance( List<ModelData> lineage, ModelBuildingRequest request,
665 ModelProblemCollector problems )
666 {
667 for ( int i = lineage.size() - 2; i >= 0; i-- )
668 {
669 Model parent = lineage.get( i + 1 ).getModel();
670 Model child = lineage.get( i ).getModel();
671 inheritanceAssembler.assembleModelInheritance( child, parent, request, problems );
672 }
673 }
674
675 private Map<String, Activation> getProfileActivations( Model model, boolean clone )
676 {
677 Map<String, Activation> activations = new HashMap<String, Activation>();
678 for ( Profile profile : model.getProfiles() )
679 {
680 Activation activation = profile.getActivation();
681
682 if ( activation == null )
683 {
684 continue;
685 }
686
687 if ( clone )
688 {
689 activation = activation.clone();
690 }
691
692 activations.put( profile.getId(), activation );
693 }
694
695 return activations;
696 }
697
698 private void injectProfileActivations( Model model, Map<String, Activation> activations )
699 {
700 for ( Profile profile : model.getProfiles() )
701 {
702 Activation activation = profile.getActivation();
703
704 if ( activation == null )
705 {
706 continue;
707 }
708
709
710 profile.setActivation( activations.get( profile.getId() ) );
711 }
712 }
713
714 private Model interpolateModel( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
715 {
716
717 Map<String, Activation> originalActivations = getProfileActivations( model, true );
718
719 Model result = modelInterpolator.interpolateModel( model, model.getProjectDirectory(), request, problems );
720 result.setPomFile( model.getPomFile() );
721
722
723 injectProfileActivations( model, originalActivations );
724
725 return result;
726 }
727
728 private ModelData readParent( Model childModel, ModelSource childSource, ModelBuildingRequest request,
729 DefaultModelProblemCollector problems )
730 throws ModelBuildingException
731 {
732 ModelData parentData;
733
734 Parent parent = childModel.getParent();
735
736 if ( parent != null )
737 {
738 String groupId = parent.getGroupId();
739 String artifactId = parent.getArtifactId();
740 String version = parent.getVersion();
741
742 parentData = getCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW );
743
744 if ( parentData == null )
745 {
746 parentData = readParentLocally( childModel, childSource, request, problems );
747
748 if ( parentData == null )
749 {
750 parentData = readParentExternally( childModel, request, problems );
751 }
752
753 putCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.RAW, parentData );
754 }
755 else
756 {
757
758
759
760
761
762
763
764 File pomFile = parentData.getModel().getPomFile();
765 if ( pomFile != null )
766 {
767 ModelSource expectedParentSource = getParentPomFile( childModel, childSource );
768
769 if ( expectedParentSource instanceof ModelSource2
770 && !pomFile.toURI().equals( ( (ModelSource2) expectedParentSource ).getLocationURI() ) )
771 {
772 parentData = readParentExternally( childModel, request, problems );
773 }
774 }
775 }
776
777 Model parentModel = parentData.getModel();
778
779 if ( !"pom".equals( parentModel.getPackaging() ) )
780 {
781 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
782 .setMessage( "Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint( parentModel )
783 + ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"" )
784 .setLocation( parentModel.getLocation( "packaging" ) ) );
785 }
786 }
787 else
788 {
789 parentData = null;
790 }
791
792 return parentData;
793 }
794
795 private ModelData readParentLocally( Model childModel, ModelSource childSource, ModelBuildingRequest request,
796 DefaultModelProblemCollector problems )
797 throws ModelBuildingException
798 {
799 ModelSource candidateSource = getParentPomFile( childModel, childSource );
800
801 if ( candidateSource == null )
802 {
803 return null;
804 }
805
806 File pomFile = null;
807 if ( candidateSource instanceof FileModelSource )
808 {
809 pomFile = ( (FileModelSource) candidateSource ).getPomFile();
810 }
811
812 Model candidateModel = readModel( candidateSource, pomFile, request, problems );
813
814 String groupId = candidateModel.getGroupId();
815 if ( groupId == null && candidateModel.getParent() != null )
816 {
817 groupId = candidateModel.getParent().getGroupId();
818 }
819 String artifactId = candidateModel.getArtifactId();
820 String version = candidateModel.getVersion();
821 if ( version == null && candidateModel.getParent() != null )
822 {
823 version = candidateModel.getParent().getVersion();
824 }
825
826 Parent parent = childModel.getParent();
827
828 if ( groupId == null || !groupId.equals( parent.getGroupId() ) || artifactId == null
829 || !artifactId.equals( parent.getArtifactId() ) )
830 {
831 StringBuilder buffer = new StringBuilder( 256 );
832 buffer.append( "'parent.relativePath'" );
833 if ( childModel != problems.getRootModel() )
834 {
835 buffer.append( " of POM " ).append( ModelProblemUtils.toSourceHint( childModel ) );
836 }
837 buffer.append( " points at " ).append( groupId ).append( ":" ).append( artifactId );
838 buffer.append( " instead of " ).append( parent.getGroupId() ).append( ":" ).append( parent.getArtifactId() );
839 buffer.append( ", please verify your project structure" );
840
841 problems.setSource( childModel );
842 problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.BASE )
843 .setMessage( buffer.toString() )
844 .setLocation( parent.getLocation( "" ) ) );
845 return null;
846 }
847 if ( version == null || !version.equals( parent.getVersion() ) )
848 {
849 return null;
850 }
851
852 ModelData parentData = new ModelData( candidateSource, candidateModel, groupId, artifactId, version );
853
854 return parentData;
855 }
856
857 private ModelSource getParentPomFile( Model childModel, ModelSource source )
858 {
859 if ( !( source instanceof ModelSource2 ) )
860 {
861 return null;
862 }
863
864 String parentPath = childModel.getParent().getRelativePath();
865
866 if ( parentPath == null || parentPath.length() <= 0 )
867 {
868 return null;
869 }
870
871 return ( (ModelSource2) source ).getRelatedSource( parentPath );
872 }
873
874 private ModelData readParentExternally( Model childModel, ModelBuildingRequest request,
875 DefaultModelProblemCollector problems )
876 throws ModelBuildingException
877 {
878 problems.setSource( childModel );
879
880 Parent parent = childModel.getParent().clone();
881
882 String groupId = parent.getGroupId();
883 String artifactId = parent.getArtifactId();
884 String version = parent.getVersion();
885
886 ModelResolver modelResolver = request.getModelResolver();
887
888 if ( modelResolver == null )
889 {
890 throw new IllegalArgumentException( "no model resolver provided, cannot resolve parent POM "
891 + ModelProblemUtils.toId( groupId, artifactId, version ) + " for POM "
892 + ModelProblemUtils.toSourceHint( childModel ) );
893 }
894
895 ModelSource modelSource;
896 try
897 {
898 modelSource = modelResolver.resolveModel( parent );
899 }
900 catch ( UnresolvableModelException e )
901 {
902 StringBuilder buffer = new StringBuilder( 256 );
903 buffer.append( "Non-resolvable parent POM" );
904 if ( !containsCoordinates( e.getMessage(), groupId, artifactId, version ) )
905 {
906 buffer.append( " " ).append( ModelProblemUtils.toId( groupId, artifactId, version ) );
907 }
908 if ( childModel != problems.getRootModel() )
909 {
910 buffer.append( " for " ).append( ModelProblemUtils.toId( childModel ) );
911 }
912 buffer.append( ": " ).append( e.getMessage() );
913 if ( childModel.getProjectDirectory() != null )
914 {
915 if ( parent.getRelativePath() == null || parent.getRelativePath().length() <= 0 )
916 {
917 buffer.append( " and 'parent.relativePath' points at no local POM" );
918 }
919 else
920 {
921 buffer.append( " and 'parent.relativePath' points at wrong local POM" );
922 }
923 }
924
925 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.BASE )
926 .setMessage( buffer.toString() )
927 .setLocation( parent.getLocation( "" ) )
928 .setException( e ) );
929 throw problems.newModelBuildingException();
930 }
931
932 ModelBuildingRequest lenientRequest = request;
933 if ( request.getValidationLevel() > ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
934 {
935 lenientRequest = new FilterModelBuildingRequest( request )
936 {
937 @Override
938 public int getValidationLevel()
939 {
940 return ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0;
941 }
942 };
943 }
944
945 Model parentModel = readModel( modelSource, null, lenientRequest, problems );
946
947 if ( !parent.getVersion().equals( version ) )
948 {
949 if ( childModel.getVersion() == null )
950 {
951 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 ).
952 setMessage( "Version must be a constant" ).
953 setLocation( childModel.getLocation( "" ) ) );
954
955 }
956 else
957 {
958 if ( childModel.getVersion().indexOf( "${" ) > -1 )
959 {
960 problems.add( new ModelProblemCollectorRequest( Severity.FATAL, Version.V31 ).
961 setMessage( "Version must be a constant" ).
962 setLocation( childModel.getLocation( "version" ) ) );
963
964 }
965 }
966
967
968 }
969
970 ModelData parentData = new ModelData( modelSource, parentModel, parent.getGroupId(), parent.getArtifactId(),
971 parent.getVersion() );
972
973 return parentData;
974 }
975
976 private Model getSuperModel()
977 {
978 return superPomProvider.getSuperModel( "4.0.0" ).clone();
979 }
980
981 private void importDependencyManagement( Model model, ModelBuildingRequest request,
982 DefaultModelProblemCollector problems, Collection<String> importIds )
983 {
984 DependencyManagement depMngt = model.getDependencyManagement();
985
986 if ( depMngt == null )
987 {
988 return;
989 }
990
991 String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion();
992
993 importIds.add( importing );
994
995 ModelResolver modelResolver = request.getModelResolver();
996
997 ModelBuildingRequest importRequest = null;
998
999 List<DependencyManagement> importMngts = null;
1000
1001 for ( Iterator<Dependency> it = depMngt.getDependencies().iterator(); it.hasNext(); )
1002 {
1003 Dependency dependency = it.next();
1004
1005 if ( !"pom".equals( dependency.getType() ) || !"import".equals( dependency.getScope() ) )
1006 {
1007 continue;
1008 }
1009
1010 it.remove();
1011
1012 String groupId = dependency.getGroupId();
1013 String artifactId = dependency.getArtifactId();
1014 String version = dependency.getVersion();
1015
1016 if ( groupId == null || groupId.length() <= 0 )
1017 {
1018 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1019 .setMessage( "'dependencyManagement.dependencies.dependency.groupId' for "
1020 + dependency.getManagementKey() + " is missing." )
1021 .setLocation( dependency.getLocation( "" ) ) );
1022 continue;
1023 }
1024 if ( artifactId == null || artifactId.length() <= 0 )
1025 {
1026 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1027 .setMessage( "'dependencyManagement.dependencies.dependency.artifactId' for "
1028 + dependency.getManagementKey() + " is missing." )
1029 .setLocation( dependency.getLocation( "" ) ) );
1030 continue;
1031 }
1032 if ( version == null || version.length() <= 0 )
1033 {
1034 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1035 .setMessage( "'dependencyManagement.dependencies.dependency.version' for "
1036 + dependency.getManagementKey() + " is missing." )
1037 .setLocation( dependency.getLocation( "" ) ) );
1038 continue;
1039 }
1040
1041 String imported = groupId + ':' + artifactId + ':' + version;
1042
1043 if ( importIds.contains( imported ) )
1044 {
1045 String message = "The dependencies of type=pom and with scope=import form a cycle: ";
1046 for ( String modelId : importIds )
1047 {
1048 message += modelId + " -> ";
1049 }
1050 message += imported;
1051 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage( message ) );
1052
1053 continue;
1054 }
1055
1056 DependencyManagement importMngt =
1057 getCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT );
1058
1059 if ( importMngt == null )
1060 {
1061 if ( modelResolver == null )
1062 {
1063 throw new IllegalArgumentException( "no model resolver provided, cannot resolve import POM "
1064 + ModelProblemUtils.toId( groupId, artifactId, version ) + " for POM "
1065 + ModelProblemUtils.toSourceHint( model ) );
1066 }
1067
1068 ModelSource importSource;
1069 try
1070 {
1071 importSource = modelResolver.resolveModel( groupId, artifactId, version );
1072 }
1073 catch ( UnresolvableModelException e )
1074 {
1075 StringBuilder buffer = new StringBuilder( 256 );
1076 buffer.append( "Non-resolvable import POM" );
1077 if ( !containsCoordinates( e.getMessage(), groupId, artifactId, version ) )
1078 {
1079 buffer.append( " " ).append( ModelProblemUtils.toId( groupId, artifactId, version ) );
1080 }
1081 buffer.append( ": " ).append( e.getMessage() );
1082
1083 problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
1084 .setMessage( buffer.toString() )
1085 .setLocation( dependency.getLocation( "" ) )
1086 .setException( e ) );
1087 continue;
1088 }
1089
1090 if ( importRequest == null )
1091 {
1092 importRequest = new DefaultModelBuildingRequest();
1093 importRequest.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
1094 importRequest.setModelCache( request.getModelCache() );
1095 importRequest.setSystemProperties( request.getSystemProperties() );
1096 importRequest.setUserProperties( request.getUserProperties() );
1097 importRequest.setLocationTracking( request.isLocationTracking() );
1098 }
1099
1100 importRequest.setModelSource( importSource );
1101 importRequest.setModelResolver( modelResolver.newCopy() );
1102
1103 ModelBuildingResult importResult;
1104 try
1105 {
1106 importResult = build( importRequest );
1107 }
1108 catch ( ModelBuildingException e )
1109 {
1110 problems.addAll( e.getProblems() );
1111 continue;
1112 }
1113
1114 problems.addAll( importResult.getProblems() );
1115
1116 Model importModel = importResult.getEffectiveModel();
1117
1118 importMngt = importModel.getDependencyManagement();
1119
1120 if ( importMngt == null )
1121 {
1122 importMngt = new DependencyManagement();
1123 }
1124
1125 putCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, importMngt );
1126 }
1127
1128 if ( importMngts == null )
1129 {
1130 importMngts = new ArrayList<DependencyManagement>();
1131 }
1132
1133 importMngts.add( importMngt );
1134 }
1135
1136 importIds.remove( importing );
1137
1138 dependencyManagementImporter.importManagement( model, importMngts, request, problems );
1139 }
1140
1141 private <T> void putCache( ModelCache modelCache, String groupId, String artifactId, String version,
1142 ModelCacheTag<T> tag, T data )
1143 {
1144 if ( modelCache != null )
1145 {
1146 modelCache.put( groupId, artifactId, version, tag.getName(), tag.intoCache( data ) );
1147 }
1148 }
1149
1150 private <T> T getCache( ModelCache modelCache, String groupId, String artifactId, String version,
1151 ModelCacheTag<T> tag )
1152 {
1153 if ( modelCache != null )
1154 {
1155 Object data = modelCache.get( groupId, artifactId, version, tag.getName() );
1156 if ( data != null )
1157 {
1158 return tag.fromCache( tag.getType().cast( data ) );
1159 }
1160 }
1161 return null;
1162 }
1163
1164 private void fireEvent( Model model, ModelBuildingRequest request, ModelProblemCollector problems,
1165 ModelBuildingEventCatapult catapult )
1166 throws ModelBuildingException
1167 {
1168 ModelBuildingListener listener = request.getModelBuildingListener();
1169
1170 if ( listener != null )
1171 {
1172 ModelBuildingEvent event = new DefaultModelBuildingEvent( model, request, problems );
1173
1174 catapult.fire( listener, event );
1175 }
1176 }
1177
1178 private boolean containsCoordinates( String message, String groupId, String artifactId, String version )
1179 {
1180 return message != null && ( groupId == null || message.contains( groupId ) )
1181 && ( artifactId == null || message.contains( artifactId ) )
1182 && ( version == null || message.contains( version ) );
1183 }
1184
1185 protected boolean hasModelErrors( ModelProblemCollectorExt problems )
1186 {
1187 if ( problems instanceof DefaultModelProblemCollector )
1188 {
1189 return ( (DefaultModelProblemCollector) problems ).hasErrors();
1190 }
1191 else
1192 {
1193
1194
1195 throw new IllegalStateException();
1196 }
1197 }
1198
1199 protected boolean hasFatalErrors( ModelProblemCollectorExt problems )
1200 {
1201 if ( problems instanceof DefaultModelProblemCollector )
1202 {
1203 return ( (DefaultModelProblemCollector) problems ).hasFatalErrors();
1204 }
1205 else
1206 {
1207
1208
1209 throw new IllegalStateException();
1210 }
1211 }
1212
1213 }