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